From af5a7e2488b33cc946c0c384f548b3c8fcf36e05 Mon Sep 17 00:00:00 2001 From: yankaiz Date: Fri, 16 Mar 2018 13:06:36 -0700 Subject: [PATCH] Unit tests for external load balancer. --- pkg/cloudprovider/providers/gce/BUILD | 2 + .../providers/gce/cloud/mock/mock.go | 25 + .../gce/gce_loadbalancer_external_test.go | 484 ++++++++++++++++++ .../gce/gce_loadbalancer_utils_test.go | 36 +- 4 files changed, 540 insertions(+), 7 deletions(-) diff --git a/pkg/cloudprovider/providers/gce/BUILD b/pkg/cloudprovider/providers/gce/BUILD index 769974b7b91..fea76b3aeca 100644 --- a/pkg/cloudprovider/providers/gce/BUILD +++ b/pkg/cloudprovider/providers/gce/BUILD @@ -115,6 +115,7 @@ go_test( "//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library", "//pkg/cloudprovider/providers/gce/cloud/mock:go_default_library", "//pkg/kubelet/apis:go_default_library", + "//pkg/util/net/sets:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/require:go_default_library", "//vendor/golang.org/x/oauth2/google:go_default_library", @@ -126,6 +127,7 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", ], ) diff --git a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go b/pkg/cloudprovider/providers/gce/cloud/mock/mock.go index acb1fb62ef8..e03c183dba7 100644 --- a/pkg/cloudprovider/providers/gce/cloud/mock/mock.go +++ b/pkg/cloudprovider/providers/gce/cloud/mock/mock.go @@ -408,3 +408,28 @@ func UpdateRegionBackendServiceHook(ctx context.Context, key *meta.Key, obj *ga. m.Objects[*key] = &cloud.MockRegionBackendServicesObj{Obj: obj} return nil } + +// InsertFirewallsUnauthorizedErrHook mocks firewall insertion. A forbidden error will be thrown as return. +func InsertFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, obj *ga.Firewall, m *cloud.MockFirewalls) (bool, error) { + return true, &googleapi.Error{Code: http.StatusForbidden} +} + +// UpdateFirewallsUnauthorizedErrHook mocks firewall updating. A forbidden error will be thrown as return. +func UpdateFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, obj *ga.Firewall, m *cloud.MockFirewalls) error { + return &googleapi.Error{Code: http.StatusForbidden} +} + +// DeleteFirewallsUnauthorizedErrHook mocks firewall deletion. A forbidden error will be thrown as return. +func DeleteFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, m *cloud.MockFirewalls) (bool, error) { + return true, &googleapi.Error{Code: http.StatusForbidden} +} + +// GetFirewallsUnauthorizedErrHook mocks firewall information retrival. A forbidden error will be thrown as return. +func GetFirewallsUnauthorizedErrHook(ctx context.Context, key *meta.Key, m *cloud.MockFirewalls) (bool, *ga.Firewall, error) { + return true, nil, &googleapi.Error{Code: http.StatusForbidden} +} + +// GetTargetPoolInternalErrHook mocks getting target pool. It returns a internal server error. +func GetTargetPoolInternalErrHook(ctx context.Context, key *meta.Key, m *cloud.MockTargetPools) (bool, *ga.TargetPool, error) { + return true, nil, &googleapi.Error{Code: http.StatusInternalServerError} +} diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go index 608a68d0792..e9f43f53eac 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go @@ -17,17 +17,26 @@ limitations under the License. package gce import ( + "context" "fmt" + "strings" "testing" + "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" computealpha "google.golang.org/api/compute/v0.alpha" + compute "google.golang.org/api/compute/v1" + ga "google.golang.org/api/compute/v1" "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" "k8s.io/kubernetes/pkg/cloudprovider" "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta" + "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock" + netsets "k8s.io/kubernetes/pkg/util/net/sets" ) func TestEnsureStaticIP(t *testing.T) { @@ -469,3 +478,478 @@ func TestLoadBalancerWrongTierResourceDeletion(t *testing.T) { _, err = gce.GetRegionAddress(lbName, gce.region) assert.True(t, isNotFound(err)) } + +func TestEnsureExternalLoadBalancerFailsIfInvalidNetworkTier(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + nodeNames := []string{"test-node-1"} + + nodes, err := createAndInsertNodes(gce, nodeNames, vals.ZoneName) + require.NoError(t, err) + + // Enable the cloud.NetworkTiers feature + gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true + fakeApiService.Annotations = map[string]string{NetworkTierAnnotationKey: wrongTier} + + _, err = gce.ensureExternalLoadBalancer(vals.ClusterName, vals.ClusterID, fakeApiService, nil, nodes) + require.Error(t, err) + assert.EqualError(t, err, errStrUnsupportedTier) +} + +func TestEnsureExternalLoadBalancerFailsWithNoNodes(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + _, err = gce.ensureExternalLoadBalancer(vals.ClusterName, vals.ClusterID, fakeApiService, nil, []*v1.Node{}) + require.Error(t, err) + assert.EqualError(t, err, errStrLbNoHosts) +} + +func TestForwardingRuleNeedsUpdate(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + status, err := createExternalLoadBalancer(gce, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NotNil(t, status) + require.NoError(t, err) + + lbName := cloudprovider.GetLoadBalancerName(fakeApiService) + ipAddr := status.Ingress[0].IP + + lbIP := fakeApiService.Spec.LoadBalancerIP + wrongPorts := []v1.ServicePort{fakeApiService.Spec.Ports[0]} + wrongPorts[0].Port = wrongPorts[0].Port + 1 + + wrongProtocolPorts := []v1.ServicePort{fakeApiService.Spec.Ports[0]} + wrongProtocolPorts[0].Protocol = v1.ProtocolUDP + + for desc, tc := range map[string]struct { + lbIP string + ports []v1.ServicePort + exists bool + needsUpdate bool + expectIpAddr string + expectError bool + }{ + "When the loadBalancerIP does not equal the FwdRule IP address.": { + lbIP: "1.2.3.4", + ports: fakeApiService.Spec.Ports, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When loadBalancerPortRange returns an error.": { + lbIP: lbIP, + ports: []v1.ServicePort{}, + exists: true, + needsUpdate: false, + expectIpAddr: "", + expectError: true, + }, + "When portRange not equals to the forwardingRule port range.": { + lbIP: lbIP, + ports: wrongPorts, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When the ports protocol does not equal the ForwardingRuel IP Protocol.": { + lbIP: lbIP, + ports: wrongProtocolPorts, + exists: true, + needsUpdate: true, + expectIpAddr: ipAddr, + expectError: false, + }, + "When basic workflow.": { + lbIP: lbIP, + ports: fakeApiService.Spec.Ports, + exists: true, + needsUpdate: false, + expectIpAddr: ipAddr, + expectError: false, + }, + } { + t.Run(desc, func(t *testing.T) { + exists, needsUpdate, ipAddress, err := gce.forwardingRuleNeedsUpdate(lbName, vals.Region, tc.lbIP, tc.ports) + assert.Equal(t, tc.exists, exists, "'exists' didn't return as expected "+desc) + assert.Equal(t, tc.needsUpdate, needsUpdate, "'needsUpdate' didn't return as expected "+desc) + assert.Equal(t, tc.expectIpAddr, ipAddress, "'ipAddress' didn't return as expected "+desc) + if tc.expectError { + assert.Error(t, err, "Should returns an error "+desc) + } else { + assert.NoError(t, err, "Should not returns an error "+desc) + } + }) + } +} + +func TestTargetPoolNeedsRecreation(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + serviceName := fakeApiService.ObjectMeta.Name + lbName := cloudprovider.GetLoadBalancerName(fakeApiService) + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + + var instances []string + for _, host := range hosts { + instances = append(instances, host.makeComparableHostPath()) + } + pool := &compute.TargetPool{ + Name: lbName, + Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName), + Instances: instances, + SessionAffinity: translateAffinityType(v1.ServiceAffinityNone), + } + err = gce.CreateTargetPool(pool, vals.Region) + require.NoError(t, err) + + c := gce.c.(*cloud.MockGCE) + c.MockTargetPools.GetHook = mock.GetTargetPoolInternalErrHook + exists, needsRecreation, err := gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityNone) + assert.True(t, exists) + assert.False(t, needsRecreation) + require.NotNil(t, err) + assert.True(t, strings.HasPrefix(err.Error(), errPrefixGetTargetPool)) + c.MockTargetPools.GetHook = nil + + exists, needsRecreation, err = gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityClientIP) + assert.True(t, exists) + assert.True(t, needsRecreation) + assert.NoError(t, err) + + exists, needsRecreation, err = gce.targetPoolNeedsRecreation(lbName, vals.Region, v1.ServiceAffinityNone) + assert.True(t, exists) + assert.False(t, needsRecreation) + assert.NoError(t, err) +} + +func TestFirewallNeedsUpdate(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + status, err := createExternalLoadBalancer(gce, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NotNil(t, status) + require.NoError(t, err) + svcName := "/" + fakeApiService.ObjectMeta.Name + region := vals.Region + + ipAddr := status.Ingress[0].IP + lbName := cloudprovider.GetLoadBalancerName(fakeApiService) + + ipnet, err := netsets.ParseIPNets("0.0.0.0/0") + require.NoError(t, err) + + wrongIpnet, err := netsets.ParseIPNets("1.0.0.0/10") + require.NoError(t, err) + + fw, err := gce.GetFirewall(MakeFirewallName(lbName)) + require.NoError(t, err) + + for desc, tc := range map[string]struct { + lbName string + ipAddr string + ports []v1.ServicePort + ipnet netsets.IPNet + fwIPProtocol string + getHook func(context.Context, *meta.Key, *cloud.MockFirewalls) (bool, *ga.Firewall, error) + sourceRange string + exists bool + needsUpdate bool + hasErr bool + }{ + "When response is a Non-400 HTTP error.": { + lbName: lbName, + ipAddr: ipAddr, + ports: fakeApiService.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: mock.GetFirewallsUnauthorizedErrHook, + sourceRange: fw.SourceRanges[0], + exists: false, + needsUpdate: false, + hasErr: true, + }, + "When given a wrong description.": { + lbName: lbName, + ipAddr: "", + ports: fakeApiService.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When IPProtocol doesn't match.": { + lbName: lbName, + ipAddr: ipAddr, + ports: fakeApiService.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "usps", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When the ports don't match.": { + lbName: lbName, + ipAddr: ipAddr, + ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(666)}}, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When parseIPNets returns an error.": { + lbName: lbName, + ipAddr: ipAddr, + ports: fakeApiService.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: "badSourceRange", + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When the source ranges are not equal.": { + lbName: lbName, + ipAddr: ipAddr, + ports: fakeApiService.Spec.Ports, + ipnet: wrongIpnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: true, + hasErr: false, + }, + "When basic flow without exceptions.": { + lbName: lbName, + ipAddr: ipAddr, + ports: fakeApiService.Spec.Ports, + ipnet: ipnet, + fwIPProtocol: "tcp", + getHook: nil, + sourceRange: fw.SourceRanges[0], + exists: true, + needsUpdate: false, + hasErr: false, + }, + } { + t.Run(desc, func(t *testing.T) { + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + fw.Allowed[0].IPProtocol = tc.fwIPProtocol + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + require.Equal(t, fw.Allowed[0].IPProtocol, tc.fwIPProtocol) + + trueSourceRange := fw.SourceRanges[0] + fw.SourceRanges[0] = tc.sourceRange + fw, err = gce.GetFirewall(MakeFirewallName(lbName)) + require.Equal(t, fw.SourceRanges[0], tc.sourceRange) + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.GetHook = tc.getHook + + exists, needsUpdate, err := gce.firewallNeedsUpdate( + tc.lbName, + svcName, + region, + tc.ipAddr, + tc.ports, + tc.ipnet) + + assert.Equal(t, tc.exists, exists, "'exists' didn't return as expected "+desc) + assert.Equal(t, tc.needsUpdate, needsUpdate, "'needsUpdate' didn't return as expected "+desc) + if tc.hasErr { + assert.Error(t, err, "Should returns an error "+desc) + } else { + assert.NoError(t, err, "Should not returns an error "+desc) + } + + c.MockFirewalls.GetHook = nil + + fw.Allowed[0].IPProtocol = "tcp" + fw.SourceRanges[0] = trueSourceRange + fw, err = gce.GetFirewall(MakeFirewallName(tc.lbName)) + require.Equal(t, fw.Allowed[0].IPProtocol, "tcp") + require.Equal(t, fw.SourceRanges[0], trueSourceRange) + + }) + } +} + +func TestDeleteWrongNetworkTieredResourcesSucceedsWhenNotFound(t *testing.T) { + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true + assert.Nil(t, gce.deleteWrongNetworkTieredResources("Wrong_LB_Name", "", cloud.NetworkTier(""))) +} + +func TestEnsureTargetPoolAndHealthCheck(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + status, err := gce.ensureExternalLoadBalancer( + vals.ClusterName, + vals.ClusterID, + fakeApiService, + nil, + nodes, + ) + require.NotNil(t, status) + require.NoError(t, err) + + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + clusterID := vals.ClusterID + + ipAddr := status.Ingress[0].IP + lbName := cloudprovider.GetLoadBalancerName(fakeApiService) + region := vals.Region + + hcToCreate := makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) + hcToDelete := makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort()) + + // Apply a tag on the target pool. By verifying the change of the tag, target pool update can be ensured. + tag := "A Tag" + pool, err := gce.GetTargetPool(lbName, region) + pool.CreationTimestamp = tag + pool, err = gce.GetTargetPool(lbName, region) + require.Equal(t, tag, pool.CreationTimestamp) + err = gce.ensureTargetPoolAndHealthCheck(true, true, fakeApiService, lbName, clusterID, ipAddr, hosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + pool, err = gce.GetTargetPool(lbName, region) + assert.NotEqual(t, pool.CreationTimestamp, tag) + + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, 1, len(pool.Instances)) + var manyNodeName [maxTargetPoolCreateInstances + 1]string + for i := 0; i < maxTargetPoolCreateInstances+1; i += 1 { + manyNodeName[i] = fmt.Sprintf("testnode_%d", i) + } + manyNodes, err := createAndInsertNodes(gce, manyNodeName[:], vals.ZoneName) + require.NoError(t, err) + manyHostNames := nodeNames(manyNodes) + manyHosts, err := gce.getInstancesByNames(manyHostNames) + err = gce.ensureTargetPoolAndHealthCheck(true, true, fakeApiService, lbName, clusterID, ipAddr, manyHosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, maxTargetPoolCreateInstances+1, len(pool.Instances)) + + err = gce.ensureTargetPoolAndHealthCheck(true, false, fakeApiService, lbName, clusterID, ipAddr, hosts, hcToCreate, hcToDelete) + assert.NoError(t, err) + pool, err = gce.GetTargetPool(lbName, region) + assert.Equal(t, 1, len(pool.Instances)) +} + +func checkEvent(t *testing.T, recorder *record.FakeRecorder, expected string, shouldMatch bool) bool { + select { + case received := <-recorder.Events: + if strings.HasPrefix(received, expected) != shouldMatch { + t.Errorf(received) + if shouldMatch { + t.Errorf("Should receive message \"%v\" but got \"%v\".", expected, received) + } else { + t.Errorf("Unexpected event \"%v\".", received) + } + } + return false + case <-time.After(2 * time.Second): + if shouldMatch { + t.Errorf("Should receive message \"%v\" but got timed out.", expected) + } + return true + } +} + +func TestCreateAndUpdateFirewallSucceedsOnXPN(t *testing.T) { + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + vals := DefaultTestClusterValues() + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.InsertHook = mock.InsertFirewallsUnauthorizedErrHook + c.MockFirewalls.UpdateHook = mock.UpdateFirewallsUnauthorizedErrHook + gce.onXPN = true + require.True(t, gce.OnXPN()) + + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + + nodes, err := createAndInsertNodes(gce, []string{"test-node-1"}, vals.ZoneName) + require.NoError(t, err) + hostNames := nodeNames(nodes) + hosts, err := gce.getInstancesByNames(hostNames) + require.NoError(t, err) + ipnet, err := netsets.ParseIPNets("10.0.0.0/20") + require.NoError(t, err) + gce.createFirewall( + fakeApiService, + cloudprovider.GetLoadBalancerName(fakeApiService), + gce.region, + "A sad little firewall", + ipnet, + fakeApiService.Spec.Ports, + hosts) + require.Nil(t, err) + + msg := fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) + + gce.updateFirewall( + fakeApiService, + cloudprovider.GetLoadBalancerName(fakeApiService), + gce.region, + "A sad little firewall", + ipnet, + fakeApiService.Spec.Ports, + hosts) + require.Nil(t, err) + + msg = fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) +} + +func TestEnsureExternalLoadBalancerDeletedSucceedsOnXPN(t *testing.T) { + vals := DefaultTestClusterValues() + gce, err := fakeGCECloud(DefaultTestClusterValues()) + require.NoError(t, err) + + _, err = createExternalLoadBalancer(gce, []string{"test-node-1"}, vals.ClusterName, vals.ClusterID, vals.ZoneName) + require.NoError(t, err) + + c := gce.c.(*cloud.MockGCE) + c.MockFirewalls.DeleteHook = mock.DeleteFirewallsUnauthorizedErrHook + gce.onXPN = true + require.True(t, gce.OnXPN()) + + recorder := record.NewFakeRecorder(1024) + gce.eventRecorder = recorder + + err = gce.ensureExternalLoadBalancerDeleted(vals.ClusterName, vals.ClusterID, fakeApiService) + require.NoError(t, err) + + msg := fmt.Sprintf("%s %s %s", v1.EventTypeNormal, eventReasonManualChange, eventMsgFirewallChange) + checkEvent(t, recorder, msg, true) +} diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go index 1dcdb19beea..caea1925d19 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_utils_test.go @@ -23,7 +23,9 @@ package gce import ( "fmt" "net/http" + "os" "sync" + "testing" compute "google.golang.org/api/compute/v1" @@ -35,6 +37,16 @@ import ( kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" ) +// TODO(yankaiz): Create shared error types for both test/non-test codes. +const ( + eventReasonManualChange = "LoadBalancerManualChange" + eventMsgFirewallChange = "Firewall change required by network admin" + errPrefixGetTargetPool = "error getting load balancer's target pool:" + errStrLbNoHosts = "Cannot EnsureLoadBalancer() with no hosts" + wrongTier = "SupremeLuxury" + errStrUnsupportedTier = "unsupported network tier: \"" + wrongTier + "\"" +) + type TestClusterValues struct { ProjectID string Region string @@ -53,13 +65,7 @@ func DefaultTestClusterValues() TestClusterValues { } } -var fakeApiService = &v1.Service{ - Spec: v1.ServiceSpec{ - SessionAffinity: v1.ServiceAffinityClientIP, - Type: v1.ServiceTypeClusterIP, - Ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(123)}}, - }, -} +var fakeApiService *v1.Service type fakeRoundTripper struct{} @@ -173,3 +179,19 @@ func createAndInsertNodes(gce *GCECloud, nodeNames []string, zoneName string) ([ return nodes, nil } + +func setup() { + fakeApiService = &v1.Service{ + ObjectMeta: metav1.ObjectMeta{Name: ""}, + Spec: v1.ServiceSpec{ + SessionAffinity: v1.ServiceAffinityClientIP, + Type: v1.ServiceTypeClusterIP, + Ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(123)}}, + }, + } +} + +func TestMain(m *testing.M) { + setup() + os.Exit(m.Run()) +}