diff --git a/cluster/gce/gci/configure-helper.sh b/cluster/gce/gci/configure-helper.sh index 331213b150..48c1c02133 100644 --- a/cluster/gce/gci/configure-helper.sh +++ b/cluster/gce/gci/configure-helper.sh @@ -570,6 +570,12 @@ EOF cat <>/etc/gce.conf token-url = ${TOKEN_URL} token-body = ${TOKEN_BODY} +EOF + fi + if [[ -n "${CONTAINER_API_ENDPOINT:-}" ]]; then + use_cloud_config="true" + cat <>/etc/gce.conf +container-api-endpoint = ${CONTAINER_API_ENDPOINT} EOF fi if [[ -n "${PROJECT_ID:-}" ]]; then diff --git a/pkg/cloudprovider/providers/gce/gce.go b/pkg/cloudprovider/providers/gce/gce.go index c2defec389..36ccd264ea 100644 --- a/pkg/cloudprovider/providers/gce/gce.go +++ b/pkg/cloudprovider/providers/gce/gce.go @@ -178,6 +178,9 @@ type ConfigGlobal struct { // ApiEndpoint is the GCE compute API endpoint to use. If this is blank, // then the default endpoint is used. ApiEndpoint string `gcfg:"api-endpoint"` + // ContainerApiEndpoint is the GCE container API endpoint to use. If this is blank, + // then the default endpoint is used. + ContainerApiEndpoint string `gcfg:"container-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. @@ -194,22 +197,23 @@ type ConfigFile struct { // 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 - NodeInstancePrefix string - TokenSource oauth2.TokenSource - UseMetadataServer bool - AlphaFeatureGate *AlphaFeatureGate + ApiEndpoint string + ContainerApiEndpoint string + ProjectID string + NetworkProjectID string + Region string + Zone string + ManagedZones []string + NetworkName string + NetworkURL string + SubnetworkName string + SubnetworkURL string + SecondaryRangeName string + NodeTags []string + NodeInstancePrefix string + TokenSource oauth2.TokenSource + UseMetadataServer bool + AlphaFeatureGate *AlphaFeatureGate } func init() { @@ -238,6 +242,11 @@ func (g *GCECloud) Compute() cloud.Cloud { return g.c } +// ContainerService returns the container service. +func (g *GCECloud) ContainerService() *container.Service { + return g.containerService +} + // newGCECloud creates a new instance of GCECloud. func newGCECloud(config io.Reader) (gceCloud *GCECloud, err error) { var cloudConfig *CloudConfig @@ -278,6 +287,10 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err cloudConfig.ApiEndpoint = configFile.Global.ApiEndpoint } + if configFile.Global.ContainerApiEndpoint != "" { + cloudConfig.ContainerApiEndpoint = configFile.Global.ContainerApiEndpoint + } + if configFile.Global.TokenURL != "" { // if tokenURL is nil, set tokenSource to nil. This will force the OAuth client to fall // back to use DefaultTokenSource. This allows running gceCloud remotely. @@ -419,6 +432,9 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) { return nil, err } containerService.UserAgent = userAgent + if config.ContainerApiEndpoint != "" { + containerService.BasePath = config.ContainerApiEndpoint + } tpuService, err := newTPUService(client) if err != nil { diff --git a/pkg/cloudprovider/providers/gce/gce_clusters.go b/pkg/cloudprovider/providers/gce/gce_clusters.go index 615f9379b2..ecd935716a 100644 --- a/pkg/cloudprovider/providers/gce/gce_clusters.go +++ b/pkg/cloudprovider/providers/gce/gce_clusters.go @@ -16,7 +16,10 @@ limitations under the License. package gce -import "context" +import ( + "context" + container "google.golang.org/api/container/v1" +) func newClustersMetricContext(request, zone string) *metricContext { return newGenericMetricContext("clusters", request, unusedMetricLabel, zone, computeV1Version) @@ -37,11 +40,37 @@ func (gce *GCECloud) ListClusters(ctx context.Context) ([]string, error) { return allClusters, nil } +func (gce *GCECloud) GetManagedClusters(ctx context.Context) ([]*container.Cluster, error) { + managedClusters := []*container.Cluster{} + for _, zone := range gce.managedZones { + clusters, err := gce.getClustersInZone(zone) + if err != nil { + return nil, err + } + managedClusters = append(managedClusters, clusters...) + } + + return managedClusters, nil +} + func (gce *GCECloud) Master(ctx context.Context, clusterName string) (string, error) { return "k8s-" + clusterName + "-master.internal", nil } func (gce *GCECloud) listClustersInZone(zone string) ([]string, error) { + clusters, err := gce.getClustersInZone(zone) + if err != nil { + return nil, err + } + + result := []string{} + for _, cluster := range clusters { + result = append(result, cluster.Name) + } + return result, nil +} + +func (gce *GCECloud) getClustersInZone(zone string) ([]*container.Cluster, error) { mc := newClustersMetricContext("list_zone", zone) // TODO: use PageToken to list all not just the first 500 list, err := gce.containerService.Projects.Zones.Clusters.List(gce.projectID, zone).Do() @@ -49,9 +78,5 @@ func (gce *GCECloud) listClustersInZone(zone string) ([]string, error) { return nil, mc.Observe(err) } - result := []string{} - for _, cluster := range list.Clusters { - result = append(result, cluster.Name) - } - return result, mc.Observe(nil) + return list.Clusters, mc.Observe(nil) }