mirror of
https://github.com/cloudnativelabs/kube-router.git
synced 2025-11-20 20:41:06 +01:00
* Makefile: Add lint using golangci-lint
* build/travis-test.sh: Run lint step
* metrics_controller: Lint
pkg/metrics/metrics_controller.go:150:2: `mu` is unused (structcheck)
mu sync.Mutex
^
pkg/metrics/metrics_controller.go:151:2: `nodeIP` is unused (structcheck)
nodeIP net.IP
^
* network_service_graceful: Lint
pkg/controllers/proxy/network_service_graceful.go:21:6: `gracefulQueueItem` is unused (deadcode)
type gracefulQueueItem struct {
^
pkg/controllers/proxy/network_service_graceful.go:22:2: `added` is unused (structcheck)
added time.Time
^
pkg/controllers/proxy/network_service_graceful.go:23:2: `service` is unused (structcheck)
service *ipvs.Service
^
* network_services_controller_test: Lint
pkg/controllers/proxy/network_services_controller_test.go:80:6: func `logf` is unused (unused)
* ecmp_vip: Lint
pkg/controllers/routing/ecmp_vip.go:208:4: S1023: redundant `return` statement (gosimple)
return
^
* bgp_peers: Lint
pkg/controllers/routing/bgp_peers.go:331:4: S1023: redundant `return` statement (gosimple)
return
^
* bgp_policies: Lint
pkg/controllers/routing/bgp_policies.go:80:3: S1011: should replace loop with `externalBgpPeers = append(externalBgpPeers, nrc.nodePeerRouters...)` (gosimple)
for _, peer := range nrc.nodePeerRouters {
^
pkg/controllers/routing/bgp_policies.go:23:20: ineffectual assignment to `err` (ineffassign)
podCidrPrefixSet, err := table.NewPrefixSet(config.PrefixSet{
^
pkg/controllers/routing/bgp_policies.go:42:22: ineffectual assignment to `err` (ineffassign)
clusterIPPrefixSet, err := table.NewPrefixSet(config.PrefixSet{
^
pkg/controllers/routing/bgp_policies.go:33:30: Error return value of `nrc.bgpServer.AddDefinedSet` is not checked (errcheck)
nrc.bgpServer.AddDefinedSet(podCidrPrefixSet)
^
pkg/controllers/routing/bgp_policies.go:48:30: Error return value of `nrc.bgpServer.AddDefinedSet` is not checked (errcheck)
nrc.bgpServer.AddDefinedSet(clusterIPPrefixSet)
^
pkg/controllers/routing/bgp_policies.go:69:31: Error return value of `nrc.bgpServer.AddDefinedSet` is not checked (errcheck)
nrc.bgpServer.AddDefinedSet(iBGPPeerNS)
^
pkg/controllers/routing/bgp_policies.go:108:31: Error return value of `nrc.bgpServer.AddDefinedSet` is not checked (errcheck)
nrc.bgpServer.AddDefinedSet(ns)
^
pkg/controllers/routing/bgp_policies.go:120:30: Error return value of `nrc.bgpServer.AddDefinedSet` is not checked (errcheck)
nrc.bgpServer.AddDefinedSet(ns)
^
^
* network_policy_controller: Lint
pkg/controllers/netpol/network_policy_controller.go:35:2: `networkPolicyAnnotation` is unused (deadcode)
networkPolicyAnnotation = "net.beta.kubernetes.io/network-policy"
^
pkg/controllers/netpol/network_policy_controller.go:1047:4: SA9003: empty branch (staticcheck)
if err != nil {
^
pkg/controllers/netpol/network_policy_controller.go:969:10: SA4006: this value of `err` is never used (staticcheck)
chains, err := iptablesCmdHandler.ListChains("filter")
^
pkg/controllers/netpol/network_policy_controller.go:1568:4: SA4006: this value of `err` is never used (staticcheck)
err = iptablesCmdHandler.Delete("filter", "FORWARD", strconv.Itoa(i-realRuleNo))
^
pkg/controllers/netpol/network_policy_controller.go:1584:4: SA4006: this value of `err` is never used (staticcheck)
err = iptablesCmdHandler.Delete("filter", "OUTPUT", strconv.Itoa(i-realRuleNo))
^
* network_services_controller: Lint
pkg/controllers/proxy/network_services_controller.go:66:2: `h` is unused (deadcode)
h *ipvs.Handle
^
pkg/controllers/proxy/network_services_controller.go:879:23: SA1019: client.NewEnvClient is deprecated: use NewClientWithOpts(FromEnv) (staticcheck)
dockerClient, err := client.NewEnvClient()
^
pkg/controllers/proxy/network_services_controller.go:944:5: unreachable: unreachable code (govet)
glog.V(3).Infof("Waiting for tunnel interface %s to come up in the pod, retrying", KUBE_TUNNEL_IF)
^
pkg/controllers/proxy/network_services_controller.go:1289:5: S1002: should omit comparison to bool constant, can be simplified to `!hasHairpinChain` (gosimple)
if hasHairpinChain != true {
^
pkg/controllers/proxy/network_services_controller.go:1237:43: S1019: should use make(map[string][]string) instead (gosimple)
rulesNeeded := make(map[string][]string, 0)
^
pkg/controllers/proxy/network_services_controller.go:1111:4: S1023: redundant break statement (gosimple)
break
^
pkg/controllers/proxy/network_services_controller.go:1114:4: S1023: redundant break statement (gosimple)
break
^
pkg/controllers/proxy/network_services_controller.go:1117:4: S1023: redundant break statement (gosimple)
break
^
pkg/controllers/proxy/network_services_controller.go:445:21: Error return value of `nsc.publishMetrics` is not checked (errcheck)
nsc.publishMetrics(nsc.serviceMap)
^
pkg/controllers/proxy/network_services_controller.go:1609:9: Error return value of `h.Write` is not checked (errcheck)
h.Write([]byte(ip + "-" + protocol + "-" + port))
^
pkg/controllers/proxy/network_services_controller.go:912:13: Error return value of `netns.Set` is not checked (errcheck)
netns.Set(hostNetworkNamespaceHandle)
^
pkg/controllers/proxy/network_services_controller.go:926:13: Error return value of `netns.Set` is not checked (errcheck)
netns.Set(hostNetworkNamespaceHandle)
^
pkg/controllers/proxy/network_services_controller.go:950:13: Error return value of `netns.Set` is not checked (errcheck)
netns.Set(hostNetworkNamespaceHandle)
^
pkg/controllers/proxy/network_services_controller.go:641:9: SA4006: this value of `err` is never used (staticcheck)
addrs, err := getAllLocalIPs()
^
* network_routes_controller: Lint
pkg/controllers/routing/network_routes_controller.go:340:2: S1000: should use for range instead of for { select {} } (gosimple)
for {
^
pkg/controllers/routing/network_routes_controller.go:757:22: Error return value of `nrc.bgpServer.Stop` is not checked (errcheck)
nrc.bgpServer.Stop()
^
pkg/controllers/routing/network_routes_controller.go:770:22: Error return value of `nrc.bgpServer.Stop` is not checked (errcheck)
nrc.bgpServer.Stop()
^
pkg/controllers/routing/network_routes_controller.go:782:23: Error return value of `nrc.bgpServer.Stop` is not checked (errcheck)
nrc.bgpServer.Stop()
^
pkg/controllers/routing/network_routes_controller.go:717:12: Error return value of `g.Serve` is not checked (errcheck)
go g.Serve()
* ipset: Lint
pkg/utils/ipset.go:243:23: Error return value of `entry.Set.Parent.Save` is not checked (errcheck)
entry.Set.Parent.Save()
^
* pkg/cmd/kube-router: Lint
pkg/cmd/kube-router.go:214:26: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
fmt.Fprintf(os.Stderr, output)
^
pkg/cmd/kube-router.go:184:15: SA1017: the channel used with signal.Notify should be buffered (staticcheck)
signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM)
^
pkg/cmd/kube-router.go:94:17: Error return value of `hc.RunServer` is not checked (errcheck)
go hc.RunServer(stopCh, &wg)
^
pkg/cmd/kube-router.go:112:16: Error return value of `hc.RunCheck` is not checked (errcheck)
go hc.RunCheck(healthChan, stopCh, &wg)
^
pkg/cmd/kube-router.go:121:12: Error return value of `mc.Run` is not checked (errcheck)
go mc.Run(healthChan, stopCh, &wg)
^
* cmd/kube-router/kube-router: Lint
cmd/kube-router/kube-router.go:31:24: Error return value of `flag.CommandLine.Parse` is not checked (errcheck)
flag.CommandLine.Parse([]string{})
^
cmd/kube-router/kube-router.go:33:10: Error return value of `flag.Set` is not checked (errcheck)
flag.Set("logtostderr", "true")
^
cmd/kube-router/kube-router.go:34:10: Error return value of `flag.Set` is not checked (errcheck)
flag.Set("v", config.VLevel)
^
cmd/kube-router/kube-router.go:62:27: SA1006: printf-style function with dynamic format string and no further arguments should use print-style function instead (staticcheck)
fmt.Fprintf(os.Stdout, http.ListenAndServe("0.0.0.0:6060", nil).Error())
^
* kube-router_test: Lint
cmd/kube-router/kube-router_test.go:21:10: Error return value of `io.Copy` is not checked (errcheck)
io.Copy(stderrBuf, stderrR)
^
cmd/kube-router/kube-router_test.go:40:17: Error return value of `docBuf.ReadFrom` is not checked (errcheck)
docBuf.ReadFrom(docF)
^
* service_endpoints_sync: Lint
pkg/controllers/proxy/service_endpoints_sync.go:460:2: ineffectual assignment to `ipvsSvcs` (ineffassign)
ipvsSvcs, err := nsc.ln.ipvsGetServices()
^
pkg/controllers/proxy/service_endpoints_sync.go:311:5: SA4006: this value of `err` is never used (staticcheck)
err = nsc.ln.ipAddrDel(dummyVipInterface, externalIP)
^
* node: Lint
pkg/utils/node.go:19:16: SA1019: clientset.Core is deprecated: please explicitly pick a version if possible. (staticcheck)
node, err := clientset.Core().Nodes().Get(nodeName, metav1.GetOptions{})
^
pkg/utils/node.go:27:15: SA1019: clientset.Core is deprecated: please explicitly pick a version if possible. (staticcheck)
node, err := clientset.Core().Nodes().Get(hostName, metav1.GetOptions{})
^
pkg/utils/node.go:34:15: SA1019: clientset.Core is deprecated: please explicitly pick a version if possible. (staticcheck)
node, err = clientset.Core().Nodes().Get(hostnameOverride, metav1.GetOptions{})
^
* aws: Lint
pkg/controllers/routing/aws.go:31:8: SA4006: this value of `err` is never used (staticcheck)
URL, err := url.Parse(providerID)
^
* health_controller: Lint
pkg/healthcheck/health_controller.go:54:10: Error return value of `w.Write` is not checked (errcheck)
w.Write([]byte("OK\n"))
^
pkg/healthcheck/health_controller.go:68:10: Error return value of `w.Write` is not checked (errcheck)
w.Write([]byte("Unhealthy"))
^
pkg/healthcheck/health_controller.go:159:2: S1000: should use a simple channel send/receive instead of `select` with a single case (gosimple)
select {
^
* network_routes_controller_test: Lint
pkg/controllers/routing/network_routes_controller_test.go:1113:37: Error return value of `testcase.nrc.bgpServer.Stop` is not checked (errcheck)
defer testcase.nrc.bgpServer.Stop()
^
pkg/controllers/routing/network_routes_controller_test.go:1314:37: Error return value of `testcase.nrc.bgpServer.Stop` is not checked (errcheck)
defer testcase.nrc.bgpServer.Stop()
^
pkg/controllers/routing/network_routes_controller_test.go:2327:37: Error return value of `testcase.nrc.bgpServer.Stop` is not checked (errcheck)
defer testcase.nrc.bgpServer.Stop()
^
* .golangci.yml: Increase timeout
Default is 1m, increase to 5m otherwise travis might fail
* Makefile: Update golangci-lint to 1.27.0
* kube-router_test.go: defer waitgroup
Co-authored-by: Aaron U'Ren <aauren@users.noreply.github.com>
* network_routes_controller: Incorporate review
* bgp_policies: Incorporate review
* network_routes_controller: Incorporate review
* bgp_policies: Log error instead
* network_services_controller: Incorporate review
Co-authored-by: Aaron U'Ren <aauren@users.noreply.github.com>
522 lines
16 KiB
Go
522 lines
16 KiB
Go
package proxy
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"time"
|
|
|
|
"github.com/docker/libnetwork/ipvs"
|
|
. "github.com/onsi/ginkgo"
|
|
. "github.com/onsi/gomega"
|
|
"github.com/vishvananda/netlink"
|
|
v1core "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/client-go/informers"
|
|
"k8s.io/client-go/kubernetes"
|
|
"k8s.io/client-go/kubernetes/fake"
|
|
"k8s.io/client-go/tools/cache"
|
|
)
|
|
|
|
type LinuxNetworkingMockImpl struct {
|
|
ipvsSvcs []*ipvs.Service
|
|
}
|
|
|
|
func NewLinuxNetworkMock() *LinuxNetworkingMockImpl {
|
|
lnm := &LinuxNetworkingMockImpl{
|
|
ipvsSvcs: make([]*ipvs.Service, 0, 64),
|
|
}
|
|
return lnm
|
|
}
|
|
|
|
func (lnm *LinuxNetworkingMockImpl) getKubeDummyInterface() (netlink.Link, error) {
|
|
var iface netlink.Link
|
|
iface, err := netlink.LinkByName("lo")
|
|
return iface, err
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) setupPolicyRoutingForDSR() error {
|
|
return nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) setupRoutesForExternalIPForDSR(s serviceInfoMap) error {
|
|
return nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipvsGetServices() ([]*ipvs.Service, error) {
|
|
// need to return a copy, else if the caller does `range svcs` and then calls
|
|
// DelService (on the returned svcs reference), it'll skip the "next" element
|
|
svcsCopy := make([]*ipvs.Service, len(lnm.ipvsSvcs))
|
|
copy(svcsCopy, lnm.ipvsSvcs)
|
|
return svcsCopy, nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipAddrAdd(iface netlink.Link, addr string, addRouter bool) error {
|
|
return nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipvsAddServer(ipvsSvc *ipvs.Service, ipvsDst *ipvs.Destination) error {
|
|
return nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipvsAddService(svcs []*ipvs.Service, vip net.IP, protocol, port uint16, persistent bool, persistentTimeout int32, scheduler string, flags schedFlags) (*ipvs.Service, error) {
|
|
svc := &ipvs.Service{
|
|
Address: vip,
|
|
Protocol: protocol,
|
|
Port: port,
|
|
}
|
|
lnm.ipvsSvcs = append(lnm.ipvsSvcs, svc)
|
|
return svc, nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipvsDelService(ipvsSvc *ipvs.Service) error {
|
|
for idx, svc := range lnm.ipvsSvcs {
|
|
if svc.Address.Equal(ipvsSvc.Address) && svc.Protocol == ipvsSvc.Protocol && svc.Port == ipvsSvc.Port {
|
|
lnm.ipvsSvcs = append(lnm.ipvsSvcs[:idx], lnm.ipvsSvcs[idx+1:]...)
|
|
break
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) ipvsGetDestinations(ipvsSvc *ipvs.Service) ([]*ipvs.Destination, error) {
|
|
return []*ipvs.Destination{}, nil
|
|
}
|
|
func (lnm *LinuxNetworkingMockImpl) cleanupMangleTableRule(ip string, protocol string, port string, fwmark string) error {
|
|
return nil
|
|
}
|
|
|
|
func fatalf(format string, a ...interface{}) {
|
|
msg := fmt.Sprintf("FATAL: "+format+"\n", a...)
|
|
Fail(msg)
|
|
}
|
|
|
|
// There's waitForListerWithTimeout in network_routes_controller_test.go
|
|
// that receives a 2nd *testing argument - mixing testing and ginkgo
|
|
// is discouraged (latter uses own GinkgoWriter), so need to create
|
|
// our own here.
|
|
func waitForListerWithTimeoutG(lister cache.Indexer, timeout time.Duration) {
|
|
tick := time.Tick(100 * time.Millisecond)
|
|
timeoutCh := time.After(timeout)
|
|
for {
|
|
select {
|
|
case <-timeoutCh:
|
|
fatalf("timeout exceeded waiting for service lister to fill cache")
|
|
case <-tick:
|
|
if len(lister.List()) != 0 {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
type TestCaseSvcEPs struct {
|
|
existingService *v1core.Service
|
|
existingEndpoint *v1core.Endpoints
|
|
nodeHasEndpoints bool
|
|
}
|
|
|
|
var _ = Describe("NetworkServicesController", func() {
|
|
var lnm *LinuxNetworkingMockImpl
|
|
var testcase *TestCaseSvcEPs
|
|
var mockedLinuxNetworking *LinuxNetworkingMock
|
|
var nsc *NetworkServicesController
|
|
BeforeEach(func() {
|
|
lnm = NewLinuxNetworkMock()
|
|
mockedLinuxNetworking = &LinuxNetworkingMock{
|
|
cleanupMangleTableRuleFunc: lnm.cleanupMangleTableRule,
|
|
getKubeDummyInterfaceFunc: lnm.getKubeDummyInterface,
|
|
ipAddrAddFunc: lnm.ipAddrAdd,
|
|
ipvsAddServerFunc: lnm.ipvsAddServer,
|
|
ipvsAddServiceFunc: lnm.ipvsAddService,
|
|
ipvsDelServiceFunc: lnm.ipvsDelService,
|
|
ipvsGetDestinationsFunc: lnm.ipvsGetDestinations,
|
|
ipvsGetServicesFunc: lnm.ipvsGetServices,
|
|
setupPolicyRoutingForDSRFunc: lnm.setupPolicyRoutingForDSR,
|
|
setupRoutesForExternalIPForDSRFunc: lnm.setupRoutesForExternalIPForDSR,
|
|
}
|
|
|
|
})
|
|
JustBeforeEach(func() {
|
|
clientset := fake.NewSimpleClientset()
|
|
|
|
_, err := clientset.CoreV1().Endpoints("default").Create(testcase.existingEndpoint)
|
|
if err != nil {
|
|
fatalf("failed to create existing endpoints: %v", err)
|
|
}
|
|
|
|
_, err = clientset.CoreV1().Services("default").Create(testcase.existingService)
|
|
if err != nil {
|
|
fatalf("failed to create existing services: %v", err)
|
|
}
|
|
|
|
nsc = &NetworkServicesController{
|
|
nodeIP: net.ParseIP("10.0.0.0"),
|
|
nodeHostName: "node-1",
|
|
ln: mockedLinuxNetworking,
|
|
}
|
|
|
|
startInformersForServiceProxy(nsc, clientset)
|
|
waitForListerWithTimeoutG(nsc.svcLister, time.Second*10)
|
|
waitForListerWithTimeoutG(nsc.epLister, time.Second*10)
|
|
|
|
nsc.serviceMap = nsc.buildServicesInfo()
|
|
nsc.endpointsMap = nsc.buildEndpointsInfo()
|
|
})
|
|
Context("service no endpoints with externalIPs", func() {
|
|
var fooSvc1, fooSvc2 *ipvs.Service
|
|
var syncErr error
|
|
BeforeEach(func() {
|
|
testcase = &TestCaseSvcEPs{
|
|
&v1core.Service{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "svc-1"},
|
|
Spec: v1core.ServiceSpec{
|
|
Type: "ClusterIP",
|
|
ClusterIP: "10.0.0.1",
|
|
ExternalIPs: []string{"1.1.1.1", "2.2.2.2"},
|
|
Ports: []v1core.ServicePort{
|
|
{Name: "port-1", Port: 8080, Protocol: "TCP"},
|
|
},
|
|
},
|
|
},
|
|
&v1core.Endpoints{},
|
|
false,
|
|
}
|
|
})
|
|
JustBeforeEach(func() {
|
|
// pre-inject some foo ipvs Service to verify its deletion
|
|
fooSvc1, _ = lnm.ipvsAddService(lnm.ipvsSvcs, net.ParseIP("1.2.3.4"), 6, 1234, false, 0, "rr", schedFlags{})
|
|
fooSvc2, _ = lnm.ipvsAddService(lnm.ipvsSvcs, net.ParseIP("5.6.7.8"), 6, 5678, false, 0, "rr", schedFlags{true, true, false})
|
|
syncErr = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
|
|
})
|
|
It("Should have called syncIpvsServices OK", func() {
|
|
Expect(syncErr).To(Succeed())
|
|
})
|
|
It("Should have called cleanupMangleTableRule for ExternalIPs", func() {
|
|
fwmark1, _ := generateFwmark("1.1.1.1", "tcp", "8080")
|
|
fwmark2, _ := generateFwmark("2.2.2.2", "tcp", "8080")
|
|
Expect(
|
|
fmt.Sprintf("%v", mockedLinuxNetworking.cleanupMangleTableRuleCalls())).To(
|
|
Equal(
|
|
fmt.Sprintf("[{1.1.1.1 tcp 8080 %d} {2.2.2.2 tcp 8080 %d}]",
|
|
fwmark1,
|
|
fwmark2)))
|
|
})
|
|
It("Should have called setupPolicyRoutingForDSR", func() {
|
|
Expect(
|
|
mockedLinuxNetworking.setupPolicyRoutingForDSRCalls()).To(
|
|
HaveLen(1))
|
|
})
|
|
It("Should have called getKubeDummyInterface", func() {
|
|
Expect(
|
|
mockedLinuxNetworking.getKubeDummyInterfaceCalls()).To(
|
|
HaveLen(1))
|
|
})
|
|
It("Should have called setupRoutesForExternalIPForDSR with serviceInfoMap", func() {
|
|
Expect(
|
|
mockedLinuxNetworking.setupRoutesForExternalIPForDSRCalls()).To(
|
|
ContainElement(
|
|
struct{ In1 serviceInfoMap }{In1: nsc.serviceMap}))
|
|
})
|
|
It("Should have called ipAddrAdd for ClusterIP and ExternalIPs", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, addr := range mockedLinuxNetworking.ipAddrAddCalls() {
|
|
ret = append(ret, addr.IP)
|
|
}
|
|
return ret
|
|
})()).To(
|
|
ConsistOf("10.0.0.1", "1.1.1.1", "2.2.2.2"))
|
|
})
|
|
It("Should have called ipvsDelService for pre-existing fooSvc1 fooSvc2", func() {
|
|
Expect(fmt.Sprintf("%v", mockedLinuxNetworking.ipvsDelServiceCalls())).To(
|
|
Equal(
|
|
fmt.Sprintf("[{%p} {%p}]", fooSvc1, fooSvc2)))
|
|
})
|
|
It("Should have called ipvsAddService for ClusterIP and ExternalIPs", func() {
|
|
Expect(func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServiceCalls() {
|
|
ret = append(ret, fmt.Sprintf("%v:%v:%v:%v:%v",
|
|
args.Vip, args.Protocol, args.Port,
|
|
args.Persistent, args.Scheduler))
|
|
}
|
|
return ret
|
|
}()).To(
|
|
ConsistOf(
|
|
"10.0.0.1:6:8080:false:rr",
|
|
"1.1.1.1:6:8080:false:rr",
|
|
"2.2.2.2:6:8080:false:rr"))
|
|
})
|
|
})
|
|
Context("service no endpoints with loadbalancer IPs", func() {
|
|
var syncErr error
|
|
BeforeEach(func() {
|
|
testcase = &TestCaseSvcEPs{
|
|
&v1core.Service{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "svc-1",
|
|
},
|
|
Spec: v1core.ServiceSpec{
|
|
Type: "LoadBalancer",
|
|
ClusterIP: "10.0.0.1",
|
|
ExternalIPs: []string{"1.1.1.1", "2.2.2.2"},
|
|
Ports: []v1core.ServicePort{
|
|
{Name: "port-1", Protocol: "TCP", Port: 8080},
|
|
},
|
|
},
|
|
Status: v1core.ServiceStatus{
|
|
LoadBalancer: v1core.LoadBalancerStatus{
|
|
Ingress: []v1core.LoadBalancerIngress{
|
|
{IP: "10.255.0.1"},
|
|
{IP: "10.255.0.2"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&v1core.Endpoints{},
|
|
false,
|
|
}
|
|
})
|
|
JustBeforeEach(func() {
|
|
syncErr = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
|
|
})
|
|
It("Should have called syncIpvsServices OK", func() {
|
|
Expect(syncErr).To(Succeed())
|
|
})
|
|
It("Should have called ipAddrAdd for ClusterIP, ExternalIPs and LoadBalancerIPs", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, addr := range mockedLinuxNetworking.ipAddrAddCalls() {
|
|
ret = append(ret, addr.IP)
|
|
}
|
|
return ret
|
|
})()).To(
|
|
ConsistOf(
|
|
"10.0.0.1", "1.1.1.1", "2.2.2.2", "10.255.0.1", "10.255.0.2"))
|
|
})
|
|
It("Should have called ipvsAddService for ClusterIP, ExternalIPs and LoadBalancerIPs", func() {
|
|
Expect(func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServiceCalls() {
|
|
ret = append(ret, fmt.Sprintf("%v:%v:%v:%v:%v",
|
|
args.Vip, args.Protocol, args.Port,
|
|
args.Persistent, args.Scheduler))
|
|
}
|
|
return ret
|
|
}()).To(
|
|
ConsistOf(
|
|
"10.0.0.1:6:8080:false:rr",
|
|
"1.1.1.1:6:8080:false:rr",
|
|
"2.2.2.2:6:8080:false:rr",
|
|
"10.255.0.1:6:8080:false:rr",
|
|
"10.255.0.2:6:8080:false:rr"))
|
|
})
|
|
})
|
|
Context("service no endpoints with loadbalancer IPs with skiplbips annotation", func() {
|
|
var syncErr error
|
|
BeforeEach(func() {
|
|
testcase = &TestCaseSvcEPs{
|
|
&v1core.Service{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "svc-1",
|
|
Annotations: map[string]string{
|
|
"kube-router.io/service.skiplbips": "true",
|
|
},
|
|
},
|
|
Spec: v1core.ServiceSpec{
|
|
Type: "LoadBalancer",
|
|
ClusterIP: "10.0.0.1",
|
|
ExternalIPs: []string{"1.1.1.1", "2.2.2.2"},
|
|
Ports: []v1core.ServicePort{
|
|
{Name: "port-1", Protocol: "TCP", Port: 8080},
|
|
},
|
|
},
|
|
Status: v1core.ServiceStatus{
|
|
LoadBalancer: v1core.LoadBalancerStatus{
|
|
Ingress: []v1core.LoadBalancerIngress{
|
|
{IP: "10.255.0.1"},
|
|
{IP: "10.255.0.2"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&v1core.Endpoints{},
|
|
false,
|
|
}
|
|
})
|
|
JustBeforeEach(func() {
|
|
syncErr = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
|
|
})
|
|
It("Should have called syncIpvsServices OK", func() {
|
|
Expect(syncErr).To(Succeed())
|
|
})
|
|
It("Should have called ipAddrAdd only for ClusterIP and ExternalIPs", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, addr := range mockedLinuxNetworking.ipAddrAddCalls() {
|
|
ret = append(ret, addr.IP)
|
|
}
|
|
return ret
|
|
})()).To(
|
|
ConsistOf(
|
|
"10.0.0.1", "1.1.1.1", "2.2.2.2"))
|
|
})
|
|
It("Should have called ipvsAddService only for ClusterIP and ExternalIPs", func() {
|
|
Expect(func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServiceCalls() {
|
|
ret = append(ret, fmt.Sprintf("%v:%v:%v:%v:%v",
|
|
args.Vip, args.Protocol, args.Port,
|
|
args.Persistent, args.Scheduler))
|
|
}
|
|
return ret
|
|
}()).To(
|
|
ConsistOf(
|
|
"10.0.0.1:6:8080:false:rr",
|
|
"1.1.1.1:6:8080:false:rr",
|
|
"2.2.2.2:6:8080:false:rr"))
|
|
})
|
|
})
|
|
Context("service no endpoints with loadbalancer without IPs", func() {
|
|
var syncErr error
|
|
BeforeEach(func() {
|
|
testcase = &TestCaseSvcEPs{
|
|
&v1core.Service{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "svc-1",
|
|
},
|
|
Spec: v1core.ServiceSpec{
|
|
Type: "LoadBalancer",
|
|
ClusterIP: "10.0.0.1",
|
|
ExternalIPs: []string{"1.1.1.1", "2.2.2.2"},
|
|
Ports: []v1core.ServicePort{
|
|
{Name: "port-1", Protocol: "TCP", Port: 8080},
|
|
},
|
|
},
|
|
Status: v1core.ServiceStatus{
|
|
LoadBalancer: v1core.LoadBalancerStatus{
|
|
Ingress: []v1core.LoadBalancerIngress{
|
|
{Hostname: "foo-bar.zone.elb.example.com"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
&v1core.Endpoints{},
|
|
false,
|
|
}
|
|
})
|
|
JustBeforeEach(func() {
|
|
syncErr = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
|
|
})
|
|
It("Should have called syncIpvsServices OK", func() {
|
|
Expect(syncErr).To(Succeed())
|
|
})
|
|
It("Should have called ipAddrAdd only for ClusterIP and ExternalIPs", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, addr := range mockedLinuxNetworking.ipAddrAddCalls() {
|
|
ret = append(ret, addr.IP)
|
|
}
|
|
return ret
|
|
})()).To(
|
|
ConsistOf(
|
|
"10.0.0.1", "1.1.1.1", "2.2.2.2"))
|
|
})
|
|
It("Should have properly ipvsAddService only for ClusterIP and ExternalIPs", func() {
|
|
Expect(func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServiceCalls() {
|
|
ret = append(ret, fmt.Sprintf("%v:%v:%v:%v:%v",
|
|
args.Vip, args.Protocol, args.Port,
|
|
args.Persistent, args.Scheduler))
|
|
}
|
|
return ret
|
|
}()).To(
|
|
ConsistOf(
|
|
"10.0.0.1:6:8080:false:rr",
|
|
"1.1.1.1:6:8080:false:rr",
|
|
"2.2.2.2:6:8080:false:rr"))
|
|
})
|
|
})
|
|
Context("node has endpoints for service", func() {
|
|
var syncErr error
|
|
BeforeEach(func() {
|
|
testcase = &TestCaseSvcEPs{
|
|
&v1core.Service{
|
|
ObjectMeta: metav1.ObjectMeta{Name: "svc-1", Namespace: "default"},
|
|
Spec: v1core.ServiceSpec{
|
|
Type: "ClusterIP",
|
|
ClusterIP: "10.0.0.1",
|
|
ExternalIPs: []string{"1.1.1.1", "2.2.2.2"},
|
|
Ports: []v1core.ServicePort{
|
|
{Name: "port-1", Protocol: "TCP", Port: 8080},
|
|
},
|
|
},
|
|
},
|
|
&v1core.Endpoints{
|
|
ObjectMeta: metav1.ObjectMeta{
|
|
Name: "svc-1",
|
|
Namespace: "default",
|
|
},
|
|
Subsets: []v1core.EndpointSubset{
|
|
{
|
|
Addresses: []v1core.EndpointAddress{
|
|
{IP: "172.20.1.1", NodeName: ptrToString("node-1")},
|
|
{IP: "172.20.1.2", NodeName: ptrToString("node-2")},
|
|
},
|
|
Ports: []v1core.EndpointPort{
|
|
{Name: "port-1", Port: 80, Protocol: "TCP"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
true,
|
|
}
|
|
})
|
|
JustBeforeEach(func() {
|
|
syncErr = nsc.syncIpvsServices(nsc.serviceMap, nsc.endpointsMap)
|
|
})
|
|
It("Should have called syncIpvsServices OK", func() {
|
|
Expect(syncErr).To(Succeed())
|
|
})
|
|
It("Should have called AddServiceCalls for ClusterIP and ExternalIPs", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServiceCalls() {
|
|
ret = append(ret, fmt.Sprintf("%v:%v:%v:%v:%v",
|
|
args.Vip, args.Protocol, args.Port,
|
|
args.Persistent, args.Scheduler))
|
|
}
|
|
return ret
|
|
})()).To(ConsistOf(
|
|
"10.0.0.1:6:8080:false:rr", "1.1.1.1:6:8080:false:rr", "2.2.2.2:6:8080:false:rr"))
|
|
})
|
|
It("Should have added proper Endpoints", func() {
|
|
Expect((func() []string {
|
|
ret := []string{}
|
|
for _, args := range mockedLinuxNetworking.ipvsAddServerCalls() {
|
|
svc := args.IpvsSvc
|
|
dst := args.IpvsDst
|
|
ret = append(ret, fmt.Sprintf("%v:%v->%v:%v",
|
|
svc.Address, svc.Port,
|
|
dst.Address, dst.Port))
|
|
}
|
|
return ret
|
|
})()).To(ConsistOf(
|
|
"10.0.0.1:8080->172.20.1.1:80", "1.1.1.1:8080->172.20.1.1:80", "2.2.2.2:8080->172.20.1.1:80",
|
|
"10.0.0.1:8080->172.20.1.2:80", "1.1.1.1:8080->172.20.1.2:80", "2.2.2.2:8080->172.20.1.2:80",
|
|
))
|
|
})
|
|
})
|
|
})
|
|
|
|
func startInformersForServiceProxy(nsc *NetworkServicesController, clientset kubernetes.Interface) {
|
|
informerFactory := informers.NewSharedInformerFactory(clientset, 0)
|
|
svcInformer := informerFactory.Core().V1().Services().Informer()
|
|
epInformer := informerFactory.Core().V1().Endpoints().Informer()
|
|
podInformer := informerFactory.Core().V1().Pods().Informer()
|
|
|
|
go informerFactory.Start(nil)
|
|
informerFactory.WaitForCacheSync(nil)
|
|
|
|
nsc.svcLister = svcInformer.GetIndexer()
|
|
nsc.epLister = epInformer.GetIndexer()
|
|
nsc.podLister = podInformer.GetIndexer()
|
|
}
|
|
|
|
func ptrToString(str string) *string {
|
|
return &str
|
|
}
|