From 0d55f6bdcbcb16fe6f5f117acc946aa0e94732eb Mon Sep 17 00:00:00 2001 From: Nick Sardo Date: Fri, 25 Aug 2017 18:02:10 -0700 Subject: [PATCH] Revert "GCE: Consume new config value for network project id" --- pkg/cloudprovider/providers/gce/gce.go | 156 +++----- .../providers/gce/gce_firewall.go | 14 +- .../gce/gce_loadbalancer_external.go | 4 +- pkg/cloudprovider/providers/gce/gce_op.go | 90 ++--- pkg/cloudprovider/providers/gce/gce_routes.go | 14 +- pkg/cloudprovider/providers/gce/gce_test.go | 336 ++++++++++-------- test/e2e/e2e.go | 4 +- 7 files changed, 286 insertions(+), 332 deletions(-) diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index 14cefb31eb4..c11c961d2d0 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -144,51 +144,42 @@ type GCEServiceManager struct { gce *GCECloud } -type ConfigGlobal struct { - TokenURL string `gcfg:"token-url"` - TokenBody string `gcfg:"token-body"` - // ProjectID and NetworkProjectID can either be the numeric or string-based - // unique identifier that starts with [a-z]. - ProjectID string `gcfg:"project-id"` - // NetworkProjectID refers to the project which owns the network being used. - NetworkProjectID string `gcfg:"network-project-id"` - NetworkName string `gcfg:"network-name"` - SubnetworkName string `gcfg:"subnetwork-name"` - // SecondaryRangeName is the name of the secondary range to allocate IP - // aliases. The secondary range must be present on the subnetwork the - // cluster is attached to. - SecondaryRangeName string `gcfg:"secondary-range-name"` - NodeTags []string `gcfg:"node-tags"` - NodeInstancePrefix string `gcfg:"node-instance-prefix"` - Multizone bool `gcfg:"multizone"` - // ApiEndpoint is the GCE compute API endpoint to use. If this is blank, - // then the default endpoint is used. - ApiEndpoint string `gcfg:"api-endpoint"` - // LocalZone specifies the GCE zone that gce cloud client instance is - // located in (i.e. where the controller will be running). If this is - // blank, then the local zone will be discovered via the metadata server. - LocalZone string `gcfg:"local-zone"` - // Possible values: List of api names separated by comma. Default to none. - // For example: MyFeatureFlag - AlphaFeatures []string `gcfg:"alpha-features"` -} - // ConfigFile is the struct used to parse the /etc/gce.conf configuration file. type ConfigFile struct { - Global ConfigGlobal `gcfg:"global"` + Global struct { + TokenURL string `gcfg:"token-url"` + TokenBody string `gcfg:"token-body"` + ProjectID string `gcfg:"project-id"` + NetworkName string `gcfg:"network-name"` + SubnetworkName string `gcfg:"subnetwork-name"` + // SecondaryRangeName is the name of the secondary range to allocate IP + // aliases. The secondary range must be present on the subnetwork the + // cluster is attached to. + SecondaryRangeName string `gcfg:"secondary-range-name"` + NodeTags []string `gcfg:"node-tags"` + NodeInstancePrefix string `gcfg:"node-instance-prefix"` + Multizone bool `gcfg:"multizone"` + // ApiEndpoint is the GCE compute API endpoint to use. If this is blank, + // then the default endpoint is used. + ApiEndpoint string `gcfg:"api-endpoint"` + // LocalZone specifies the GCE zone that gce cloud client instance is + // located in (i.e. where the controller will be running). If this is + // blank, then the local zone will be discovered via the metadata server. + LocalZone string `gcfg:"local-zone"` + // AlphaFeatures is a list of API flags to be enabled. Defaults to none. + // Example API name format: "MyFeatureFlag" + AlphaFeatures []string `gcfg:"alpha-features"` + } } // CloudConfig includes all the necessary configuration for creating GCECloud type CloudConfig struct { ApiEndpoint string ProjectID string - NetworkProjectID string Region string Zone string ManagedZones []string - NetworkName string NetworkURL string - SubnetworkName string SubnetworkURL string SecondaryRangeName string NodeTags []string @@ -216,6 +207,11 @@ func (g *GCECloud) GetKMSService() *cloudkms.Service { return g.cloudkmsService } +// Returns the ProjectID corresponding to the project this cloud is in. +func (g *GCECloud) GetProjectID() string { + return g.projectID +} + // newGCECloud creates a new instance of GCECloud. func newGCECloud(config io.Reader) (gceCloud *GCECloud, err error) { var cloudConfig *CloudConfig @@ -284,7 +280,6 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err return nil, err } } - if configFile != nil { if configFile.Global.ProjectID != "" { cloudConfig.ProjectID = configFile.Global.ProjectID @@ -292,9 +287,6 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err if configFile.Global.LocalZone != "" { cloudConfig.Zone = configFile.Global.LocalZone } - if configFile.Global.NetworkProjectID != "" { - cloudConfig.NetworkProjectID = configFile.Global.NetworkProjectID - } } // retrieve region @@ -309,27 +301,27 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err cloudConfig.ManagedZones = nil // Use all zones in region } - // Determine if network parameter is URL or Name + // generate networkURL if configFile != nil && configFile.Global.NetworkName != "" { if strings.Contains(configFile.Global.NetworkName, "/") { cloudConfig.NetworkURL = configFile.Global.NetworkName } else { - cloudConfig.NetworkName = configFile.Global.NetworkName + cloudConfig.NetworkURL = gceNetworkURL(cloudConfig.ApiEndpoint, cloudConfig.ProjectID, configFile.Global.NetworkName) } } else { - cloudConfig.NetworkName, err = getNetworkNameViaMetadata() + networkName, err := getNetworkNameViaMetadata() if err != nil { return nil, err } + cloudConfig.NetworkURL = gceNetworkURL("", cloudConfig.ProjectID, networkName) } - // Determine if subnetwork parameter is URL or Name - // If cluster is on a GCP network of mode=custom, then `SubnetName` must be specified in config file. + // generate subnetworkURL if configFile != nil && configFile.Global.SubnetworkName != "" { if strings.Contains(configFile.Global.SubnetworkName, "/") { cloudConfig.SubnetworkURL = configFile.Global.SubnetworkName } else { - cloudConfig.SubnetworkName = configFile.Global.SubnetworkName + cloudConfig.SubnetworkURL = gceSubnetworkURL(cloudConfig.ApiEndpoint, cloudConfig.ProjectID, cloudConfig.Region, configFile.Global.SubnetworkName) } } @@ -340,15 +332,11 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err return cloudConfig, err } -// CreateGCECloud creates a GCECloud object using the specified parameters. +// Creates a GCECloud object using the specified parameters. // If no networkUrl is specified, loads networkName via rest call. // If no tokenSource is specified, uses oauth2.DefaultTokenSource. // If managedZones is nil / empty all zones in the region will be managed. func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { - // Use ProjectID for NetworkProjectID, if it wasn't explicitly set. - if config.NetworkProjectID == "" { - config.NetworkProjectID = config.ProjectID - } client, err := newOauthClient(config.TokenSource) if err != nil { @@ -397,49 +385,19 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { return nil, err } - // config.ProjectID may be the id or project number - // In gce_routes.go, the generated networkURL is compared with a URL within a route - // therefore, we need to make sure the URL is constructed with the string ID. - projID, err := getProjectID(service, config.ProjectID) - if err != nil { - return nil, fmt.Errorf("failed to get project %v, err: %v", config.ProjectID, err) - } - - // config.NetworkProjectID may be the id or project number. In order to compare project ID - // to network project ID to determine XPN status, we need to verify both are actual IDs. - netProjID := projID - if config.NetworkProjectID != config.ProjectID { - netProjID, err = getProjectID(service, config.NetworkProjectID) - if err != nil { - return nil, fmt.Errorf("failed to get network project %v, err: %v", config.NetworkProjectID, err) - } - } - - onXPN := projID != netProjID - - var networkURL string - var subnetURL string - - if config.NetworkName == "" && config.NetworkURL == "" { - // TODO: Stop using this call and return an error. - // This function returns the first network in a list of networks for a project. The project - // should be set via configuration instead of randomly taking the first. - networkName, err := getNetworkNameViaAPICall(service, config.NetworkProjectID) + if config.NetworkURL == "" { + networkName, err := getNetworkNameViaAPICall(service, config.ProjectID) if err != nil { return nil, err } - networkURL = gceNetworkURL(config.ApiEndpoint, netProjID, networkName) - } else if config.NetworkURL != "" { - networkURL = config.NetworkURL - } else { - networkURL = gceNetworkURL(config.ApiEndpoint, netProjID, config.NetworkName) + config.NetworkURL = gceNetworkURL(config.ApiEndpoint, config.ProjectID, networkName) } - if config.SubnetworkURL != "" { - subnetURL = config.SubnetworkURL - } else if config.SubnetworkName != "" { - subnetURL = gceSubnetworkURL(config.ApiEndpoint, netProjID, config.Region, config.SubnetworkName) + networkProjectID, err := getProjectIDInURL(config.NetworkURL) + if err != nil { + return nil, err } + onXPN := networkProjectID != config.ProjectID if len(config.ManagedZones) == 0 { config.ManagedZones, err = getZonesForRegion(service, config.ProjectID, config.Region) @@ -459,14 +417,14 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { serviceBeta: serviceBeta, containerService: containerService, cloudkmsService: cloudkmsService, - projectID: projID, - networkProjectID: netProjID, + projectID: config.ProjectID, + networkProjectID: networkProjectID, onXPN: onXPN, region: config.Region, localZone: config.Zone, managedZones: config.ManagedZones, - networkURL: networkURL, - subnetworkURL: subnetURL, + networkURL: config.NetworkURL, + subnetworkURL: config.SubnetworkURL, secondaryRangeName: config.SecondaryRangeName, nodeTags: config.NodeTags, nodeInstancePrefix: config.NodeInstancePrefix, @@ -515,16 +473,6 @@ func (gce *GCECloud) ProviderName() string { return ProviderName } -// ProjectID returns the ProjectID corresponding to the project this cloud is in. -func (g *GCECloud) ProjectID() string { - return g.projectID -} - -// NetworkProjectID returns the ProjectID corresponding to the project this cluster's network is in. -func (g *GCECloud) NetworkProjectID() string { - return g.networkProjectID -} - // Region returns the region func (gce *GCECloud) Region() string { return gce.region @@ -621,16 +569,6 @@ func getNetworkNameViaAPICall(svc *compute.Service, projectID string) (string, e return networkList.Items[0].Name, nil } -// getProjectID returns the project's string ID given a project number or string -func getProjectID(svc *compute.Service, projectNumberOrID string) (string, error) { - proj, err := svc.Projects.Get(projectNumberOrID).Do() - if err != nil { - return "", err - } - - return proj.Name, nil -} - func getZonesForRegion(svc *compute.Service, projectID, region string) ([]string, error) { // TODO: use PageToken to list all not just the first 500 listCall := svc.Zones.List(projectID) diff --git a/pkg/cloudprovider/providers/gce/gce_firewall.go b/pkg/cloudprovider/providers/gce/gce_firewall.go index 2e5297275f9..b08d3f28067 100644 --- a/pkg/cloudprovider/providers/gce/gce_firewall.go +++ b/pkg/cloudprovider/providers/gce/gce_firewall.go @@ -27,38 +27,38 @@ func newFirewallMetricContext(request string) *metricContext { // GetFirewall returns the Firewall by name. func (gce *GCECloud) GetFirewall(name string) (*compute.Firewall, error) { mc := newFirewallMetricContext("get") - v, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), name).Do() + v, err := gce.service.Firewalls.Get(gce.projectID, name).Do() return v, mc.Observe(err) } // CreateFirewall creates the passed firewall func (gce *GCECloud) CreateFirewall(f *compute.Firewall) error { mc := newFirewallMetricContext("create") - op, err := gce.service.Firewalls.Insert(gce.NetworkProjectID(), f).Do() + op, err := gce.service.Firewalls.Insert(gce.projectID, f).Do() if err != nil { return mc.Observe(err) } - return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc) + return gce.waitForGlobalOp(op, mc) } // DeleteFirewall deletes the given firewall rule. func (gce *GCECloud) DeleteFirewall(name string) error { mc := newFirewallMetricContext("delete") - op, err := gce.service.Firewalls.Delete(gce.NetworkProjectID(), name).Do() + op, err := gce.service.Firewalls.Delete(gce.projectID, name).Do() if err != nil { return mc.Observe(err) } - return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc) + return gce.waitForGlobalOp(op, mc) } // UpdateFirewall applies the given firewall as an update to an existing service. func (gce *GCECloud) UpdateFirewall(f *compute.Firewall) error { mc := newFirewallMetricContext("update") - op, err := gce.service.Firewalls.Update(gce.NetworkProjectID(), f.Name, f).Do() + op, err := gce.service.Firewalls.Update(gce.projectID, f.Name, f).Do() if err != nil { return mc.Observe(err) } - return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc) + return gce.waitForGlobalOp(op, mc) } diff --git a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go index 129086e77c5..37047f6483b 100644 --- a/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go +++ b/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go @@ -729,7 +729,7 @@ func (gce *GCECloud) firewallNeedsUpdate(name, serviceName, region, ipAddress st return false, false, nil } - fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), makeFirewallName(name)).Do() + fw, err := gce.service.Firewalls.Get(gce.projectID, makeFirewallName(name)).Do() if err != nil { if isHTTPErrorCode(err, http.StatusNotFound) { return false, true, nil @@ -776,7 +776,7 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(serviceName, ipAddress, regio ports := []v1.ServicePort{{Protocol: "tcp", Port: hcPort}} fwName := MakeHealthCheckFirewallName(clusterID, hcName, isNodesHealthCheck) - fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), fwName).Do() + fw, err := gce.service.Firewalls.Get(gce.projectID, fwName).Do() if err != nil { if !isHTTPErrorCode(err, http.StatusNotFound) { return fmt.Errorf("error getting firewall for health checks: %v", err) diff --git a/pkg/cloudprovider/providers/gce/gce_op.go b/pkg/cloudprovider/providers/gce/gce_op.go index b354d79cea7..fc1549d448a 100644 --- a/pkg/cloudprovider/providers/gce/gce_op.go +++ b/pkg/cloudprovider/providers/gce/gce_op.go @@ -93,74 +93,62 @@ func getErrorFromOp(op *computev1.Operation) error { } func (gce *GCECloud) waitForGlobalOp(op gceObject, mc *metricContext) error { - return gce.waitForGlobalOpInProject(op, gce.ProjectID(), mc) + switch v := op.(type) { + case *computealpha.Operation: + return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { + op, err := gce.serviceAlpha.GlobalOperations.Get(gce.projectID, operationName).Do() + return convertToV1Operation(op), err + }, mc) + case *computebeta.Operation: + return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { + op, err := gce.serviceBeta.GlobalOperations.Get(gce.projectID, operationName).Do() + return convertToV1Operation(op), err + }, mc) + case *computev1.Operation: + return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { + return gce.service.GlobalOperations.Get(gce.projectID, operationName).Do() + }, mc) + default: + return fmt.Errorf("unexpected type: %T", v) + } } func (gce *GCECloud) waitForRegionOp(op gceObject, region string, mc *metricContext) error { - return gce.waitForRegionOpInProject(op, gce.ProjectID(), region, mc) + switch v := op.(type) { + case *computealpha.Operation: + return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { + op, err := gce.serviceAlpha.RegionOperations.Get(gce.projectID, region, operationName).Do() + return convertToV1Operation(op), err + }, mc) + case *computebeta.Operation: + return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { + op, err := gce.serviceBeta.RegionOperations.Get(gce.projectID, region, operationName).Do() + return convertToV1Operation(op), err + }, mc) + case *computev1.Operation: + return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { + return gce.service.RegionOperations.Get(gce.projectID, region, operationName).Do() + }, mc) + default: + return fmt.Errorf("unexpected type: %T", v) + } } func (gce *GCECloud) waitForZoneOp(op gceObject, zone string, mc *metricContext) error { - return gce.waitForZoneOpInProject(op, gce.ProjectID(), zone, mc) -} - -func (gce *GCECloud) waitForGlobalOpInProject(op gceObject, projectID string, mc *metricContext) error { switch v := op.(type) { case *computealpha.Operation: return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.GlobalOperations.Get(projectID, operationName).Do() + op, err := gce.serviceAlpha.ZoneOperations.Get(gce.projectID, zone, operationName).Do() return convertToV1Operation(op), err }, mc) case *computebeta.Operation: return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.GlobalOperations.Get(projectID, operationName).Do() + op, err := gce.serviceBeta.ZoneOperations.Get(gce.projectID, zone, operationName).Do() return convertToV1Operation(op), err }, mc) case *computev1.Operation: return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.GlobalOperations.Get(projectID, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForRegionOpInProject(op gceObject, projectID, region string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.RegionOperations.Get(projectID, region, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.RegionOperations.Get(projectID, region, operationName).Do() - }, mc) - default: - return fmt.Errorf("unexpected type: %T", v) - } -} - -func (gce *GCECloud) waitForZoneOpInProject(op gceObject, projectID, zone string, mc *metricContext) error { - switch v := op.(type) { - case *computealpha.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceAlpha.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computebeta.Operation: - return gce.waitForOp(convertToV1Operation(op), func(operationName string) (*computev1.Operation, error) { - op, err := gce.serviceBeta.ZoneOperations.Get(projectID, zone, operationName).Do() - return convertToV1Operation(op), err - }, mc) - case *computev1.Operation: - return gce.waitForOp(op.(*computev1.Operation), func(operationName string) (*computev1.Operation, error) { - return gce.service.ZoneOperations.Get(projectID, zone, operationName).Do() + return gce.service.ZoneOperations.Get(gce.projectID, zone, operationName).Do() }, mc) default: return fmt.Errorf("unexpected type: %T", v) diff --git a/pkg/cloudprovider/providers/gce/gce_routes.go b/pkg/cloudprovider/providers/gce/gce_routes.go index 87184aef114..5f6459cd1a8 100644 --- a/pkg/cloudprovider/providers/gce/gce_routes.go +++ b/pkg/cloudprovider/providers/gce/gce_routes.go @@ -38,13 +38,13 @@ func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, err page := 0 for ; page == 0 || (pageToken != "" && page < maxPages); page++ { mc := newRoutesMetricContext("list_page") - listCall := gce.service.Routes.List(gce.NetworkProjectID()) + listCall := gce.service.Routes.List(gce.projectID) prefix := truncateClusterName(clusterName) // Filter for routes starting with clustername AND belonging to the // relevant gcp network AND having description = "k8s-node-route". filter := "(name eq " + prefix + "-.*) " - filter = filter + "(network eq " + gce.NetworkURL() + ") " + filter = filter + "(network eq " + gce.networkURL + ") " filter = filter + "(description eq " + k8sNodeRouteTag + ")" listCall = listCall.Filter(filter) if pageToken != "" { @@ -80,11 +80,11 @@ func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *clo } mc := newRoutesMetricContext("create") - insertOp, err := gce.service.Routes.Insert(gce.NetworkProjectID(), &compute.Route{ + insertOp, err := gce.service.Routes.Insert(gce.projectID, &compute.Route{ Name: routeName, DestRange: route.DestinationCIDR, NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name), - Network: gce.NetworkURL(), + Network: gce.networkURL, Priority: 1000, Description: k8sNodeRouteTag, }).Do() @@ -96,16 +96,16 @@ func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *clo return mc.Observe(err) } } - return gce.waitForGlobalOpInProject(insertOp, gce.NetworkProjectID(), mc) + return gce.waitForGlobalOp(insertOp, mc) } func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error { mc := newRoutesMetricContext("delete") - deleteOp, err := gce.service.Routes.Delete(gce.NetworkProjectID(), route.Name).Do() + deleteOp, err := gce.service.Routes.Delete(gce.projectID, route.Name).Do() if err != nil { return mc.Observe(err) } - return gce.waitForGlobalOpInProject(deleteOp, gce.NetworkProjectID(), mc) + return gce.waitForGlobalOp(deleteOp, mc) } func truncateClusterName(clusterName string) string { diff --git a/pkg/cloudprovider/providers/gce/gce_test.go b/pkg/cloudprovider/providers/gce/gce_test.go index cc8a70300b7..d05296fec01 100644 --- a/pkg/cloudprovider/providers/gce/gce_test.go +++ b/pkg/cloudprovider/providers/gce/gce_test.go @@ -29,43 +29,6 @@ import ( computev1 "google.golang.org/api/compute/v1" ) -func TestReadConfigFile(t *testing.T) { - const s = `[Global] -token-url = my-token-url -token-body = my-token-body -project-id = my-project -network-project-id = my-network-project -network-name = my-network -subnetwork-name = my-subnetwork -secondary-range-name = my-secondary-range -node-tags = my-node-tag1 -node-instance-prefix = my-prefix -multizone = true - ` - reader := strings.NewReader(s) - config, err := readConfig(reader) - if err != nil { - t.Fatalf("Unexpected config parsing error %v", err) - } - - expected := &ConfigFile{Global: ConfigGlobal{ - TokenURL: "my-token-url", - TokenBody: "my-token-body", - ProjectID: "my-project", - NetworkProjectID: "my-network-project", - NetworkName: "my-network", - SubnetworkName: "my-subnetwork", - SecondaryRangeName: "my-secondary-range", - NodeTags: []string{"my-node-tag1"}, - NodeInstancePrefix: "my-prefix", - Multizone: true, - }} - - if !reflect.DeepEqual(expected, config) { - t.Fatalf("Expected config file values to be read into ConfigFile struct. \nExpected:\n%+v\nActual:\n%+v", expected, config) - } -} - func TestExtraKeyInConfig(t *testing.T) { const s = `[Global] project-id = my-project @@ -300,8 +263,23 @@ func TestSplitProviderID(t *testing.T) { } } -func TestGenerateCloudConfigs(t *testing.T) { - configBoilerplate := ConfigGlobal{ +type generateConfigParams struct { + TokenURL string + TokenBody string + ProjectID string + NetworkName string + SubnetworkName string + SecondaryRangeName string + NodeTags []string + NodeInstancePrefix string + Multizone bool + ApiEndpoint string + LocalZone string + AlphaFeatures []string +} + +func newGenerateConfigDefaults() *generateConfigParams { + return &generateConfigParams{ TokenURL: "", TokenBody: "", ProjectID: "project-id", @@ -315,147 +293,197 @@ func TestGenerateCloudConfigs(t *testing.T) { LocalZone: "us-central1-a", AlphaFeatures: []string{}, } +} - cloudBoilerplate := CloudConfig{ - ApiEndpoint: "", - ProjectID: "project-id", - NetworkProjectID: "", - Region: "us-central1", - Zone: "us-central1-a", - ManagedZones: []string{"us-central1-a"}, - NetworkName: "network-name", - SubnetworkName: "", - NetworkURL: "", - SubnetworkURL: "", - SecondaryRangeName: "", - NodeTags: []string{"node-tag"}, - TokenSource: google.ComputeTokenSource(""), - NodeInstancePrefix: "node-prefix", - UseMetadataServer: true, - AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, - } - +func TestGenerateCloudConfigs(t *testing.T) { testCases := []struct { - name string - config func() ConfigGlobal - cloud func() CloudConfig + TokenURL string + TokenBody string + ProjectID string + NetworkName string + SubnetworkName string + NodeTags []string + NodeInstancePrefix string + Multizone bool + ApiEndpoint string + LocalZone string + cloudConfig *CloudConfig + AlphaFeatures []string }{ + // default config { - name: "Empty Config", - config: func() ConfigGlobal { return configBoilerplate }, - cloud: func() CloudConfig { return cloudBoilerplate }, - }, - { - name: "Nil token URL", - config: func() ConfigGlobal { - v := configBoilerplate - v.TokenURL = "nil" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.TokenSource = nil - return v + cloudConfig: &CloudConfig{ + ApiEndpoint: "", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: []string{"us-central1-a"}, + NetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: google.ComputeTokenSource(""), + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, + // nil token source { - name: "Network Project ID", - config: func() ConfigGlobal { - v := configBoilerplate - v.NetworkProjectID = "my-awesome-project" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.NetworkProjectID = "my-awesome-project" - return v + TokenURL: "nil", + cloudConfig: &CloudConfig{ + ApiEndpoint: "", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: []string{"us-central1-a"}, + NetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: nil, + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, + // specified api endpoint { - name: "Specified API Endpint", - config: func() ConfigGlobal { - v := configBoilerplate - v.ApiEndpoint = "https://www.googleapis.com/compute/staging_v1/" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.ApiEndpoint = "https://www.googleapis.com/compute/staging_v1/" - return v + ApiEndpoint: "https://www.googleapis.com/compute/staging_v1/", + cloudConfig: &CloudConfig{ + ApiEndpoint: "https://www.googleapis.com/compute/staging_v1/", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: []string{"us-central1-a"}, + NetworkURL: "https://www.googleapis.com/compute/staging_v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: google.ComputeTokenSource(""), + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, + // fqdn subnetname { - name: "Network & Subnetwork names", - config: func() ConfigGlobal { - v := configBoilerplate - v.NetworkName = "my-network" - v.SubnetworkName = "my-subnetwork" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.NetworkName = "my-network" - v.SubnetworkName = "my-subnetwork" - return v + SubnetworkName: "https://www.googleapis.com/compute/v1/projects/project-id/regions/us-central1/subnetworks/subnetwork-name", + cloudConfig: &CloudConfig{ + ApiEndpoint: "", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: []string{"us-central1-a"}, + NetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/regions/us-central1/subnetworks/subnetwork-name", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: google.ComputeTokenSource(""), + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, + // subnetname { - name: "Network & Subnetwork URLs", - config: func() ConfigGlobal { - v := configBoilerplate - v.NetworkName = "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/my-network" - v.SubnetworkName = "https://www.googleapis.com/compute/v1/projects/project-id/regions/us-central1/subnetworks/my-subnetwork" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.NetworkName = "" - v.SubnetworkName = "" - v.NetworkURL = "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/my-network" - v.SubnetworkURL = "https://www.googleapis.com/compute/v1/projects/project-id/regions/us-central1/subnetworks/my-subnetwork" - return v + SubnetworkName: "subnetwork-name", + cloudConfig: &CloudConfig{ + ApiEndpoint: "", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: []string{"us-central1-a"}, + NetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/regions/us-central1/subnetworks/subnetwork-name", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: google.ComputeTokenSource(""), + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, + // multi zone { - name: "Multizone", - config: func() ConfigGlobal { - v := configBoilerplate - v.Multizone = true - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.ManagedZones = nil - return v - }, - }, - { - name: "Secondary Range Name", - config: func() ConfigGlobal { - v := configBoilerplate - v.SecondaryRangeName = "my-secondary" - return v - }, - cloud: func() CloudConfig { - v := cloudBoilerplate - v.SecondaryRangeName = "my-secondary" - return v + Multizone: true, + cloudConfig: &CloudConfig{ + ApiEndpoint: "", + ProjectID: "project-id", + Region: "us-central1", + Zone: "us-central1-a", + ManagedZones: nil, + NetworkURL: "https://www.googleapis.com/compute/v1/projects/project-id/global/networks/network-name", + SubnetworkURL: "", + NodeTags: []string{"node-tag"}, + NodeInstancePrefix: "node-prefix", + TokenSource: google.ComputeTokenSource(""), + UseMetadataServer: true, + AlphaFeatureGate: &AlphaFeatureGate{map[string]bool{}}, }, }, } for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - resultCloud, err := generateCloudConfig(&ConfigFile{Global: tc.config()}) - if err != nil { - t.Fatalf("Unexpect error: %v", err) - } + config := newGenerateConfigDefaults() + config.Multizone = tc.Multizone + config.ApiEndpoint = tc.ApiEndpoint + config.AlphaFeatures = tc.AlphaFeatures + config.TokenBody = tc.TokenBody - v := tc.cloud() - if !reflect.DeepEqual(*resultCloud, v) { - t.Errorf("Got: \n%v\nWant\n%v\n", v, *resultCloud) - } + if tc.TokenURL != "" { + config.TokenURL = tc.TokenURL + } + if tc.ProjectID != "" { + config.ProjectID = tc.ProjectID + } + if tc.NetworkName != "" { + config.NetworkName = tc.NetworkName + } + if tc.SubnetworkName != "" { + config.SubnetworkName = tc.SubnetworkName + } + if len(tc.NodeTags) > 0 { + config.NodeTags = tc.NodeTags + } + if tc.NodeInstancePrefix != "" { + config.NodeInstancePrefix = tc.NodeInstancePrefix + } + if tc.LocalZone != "" { + config.LocalZone = tc.LocalZone + } + + cloudConfig, err := generateCloudConfig(&ConfigFile{ + Global: struct { + TokenURL string `gcfg:"token-url"` + TokenBody string `gcfg:"token-body"` + ProjectID string `gcfg:"project-id"` + NetworkName string `gcfg:"network-name"` + SubnetworkName string `gcfg:"subnetwork-name"` + SecondaryRangeName string `gcfg:"secondary-range-name"` + NodeTags []string `gcfg:"node-tags"` + NodeInstancePrefix string `gcfg:"node-instance-prefix"` + Multizone bool `gcfg:"multizone"` + ApiEndpoint string `gcfg:"api-endpoint"` + LocalZone string `gcfg:"local-zone"` + AlphaFeatures []string `gcfg:"alpha-features"` + }{ + TokenURL: config.TokenURL, + TokenBody: config.TokenBody, + ProjectID: config.ProjectID, + NetworkName: config.NetworkName, + SubnetworkName: config.SubnetworkName, + SecondaryRangeName: config.SecondaryRangeName, + NodeTags: config.NodeTags, + NodeInstancePrefix: config.NodeInstancePrefix, + Multizone: config.Multizone, + ApiEndpoint: config.ApiEndpoint, + LocalZone: config.LocalZone, + AlphaFeatures: config.AlphaFeatures, + }, }) + if err != nil { + t.Fatalf("Unexpect error: %v", err) + } + + if !reflect.DeepEqual(cloudConfig, tc.cloudConfig) { + t.Errorf("Got %v, want %v", cloudConfig, tc.cloudConfig) + } } } diff --git a/test/e2e/e2e.go b/test/e2e/e2e.go index d25f664a819..dd20e04cf98 100644 --- a/test/e2e/e2e.go +++ b/test/e2e/e2e.go @@ -84,8 +84,8 @@ func setupProviderConfig() error { Region: region, Zone: zone, ManagedZones: managedZones, - NetworkName: "", // TODO: Change this to use framework.TestContext.CloudConfig.Network? - SubnetworkName: "", + NetworkURL: "", + SubnetworkURL: "", NodeTags: nil, NodeInstancePrefix: "", TokenSource: nil,