func CreateGCECloud()

in providers/gce/gce.go [418:563]


func CreateGCECloud(config *CloudConfig) (*Cloud, error) {
	// Remove any pre-release version and build metadata from the semver,
	// leaving only the MAJOR.MINOR.PATCH portion. See http://semver.org/.
	version := strings.TrimLeft(strings.Split(strings.Split(version.Get().GitVersion, "-")[0], "+")[0], "v")

	// Create a user-agent header append string to supply to the Google API
	// clients, to identify Kubernetes as the origin of the GCP API calls.
	userAgent := fmt.Sprintf("Kubernetes/%s (%s %s)", version, runtime.GOOS, runtime.GOARCH)

	// Use ProjectID for NetworkProjectID, if it wasn't explicitly set.
	if config.NetworkProjectID == "" {
		config.NetworkProjectID = config.ProjectID
	}

	service, err := compute.NewService(context.Background(), option.WithTokenSource(config.TokenSource))
	if err != nil {
		return nil, err
	}
	service.UserAgent = userAgent

	serviceBeta, err := computebeta.NewService(context.Background(), option.WithTokenSource(config.TokenSource))
	if err != nil {
		return nil, err
	}
	serviceBeta.UserAgent = userAgent

	serviceAlpha, err := computealpha.NewService(context.Background(), option.WithTokenSource(config.TokenSource))
	if err != nil {
		return nil, err
	}
	serviceAlpha.UserAgent = userAgent

	// Expect override api endpoint to always be v1 api and follows the same pattern as prod.
	// Generate alpha and beta api endpoints based on override v1 api endpoint.
	// For example,
	// staging API endpoint: https://www.googleapis.com/compute/staging_v1/
	if config.APIEndpoint != "" {
		service.BasePath = config.APIEndpoint
		serviceBeta.BasePath = strings.Replace(config.APIEndpoint, "v1", "beta", -1)
		serviceAlpha.BasePath = strings.Replace(config.APIEndpoint, "v1", "alpha", -1)
	}

	// Previously "projects/" was a part of BasePath, but recent changes in Google Cloud SDK removed it from there.
	// To bring the old format back we update BasePath including "projects/" there again.
	service.BasePath += "projects/"
	serviceBeta.BasePath += "projects/"
	serviceAlpha.BasePath += "projects/"

	containerService, err := container.NewService(context.Background(), option.WithTokenSource(config.TokenSource))
	if err != nil {
		return nil, err
	}
	containerService.UserAgent = userAgent
	if config.ContainerAPIEndpoint != "" {
		containerService.BasePath = config.ContainerAPIEndpoint
	}

	client, err := newOauthClient(config.TokenSource)
	if err != nil {
		return nil, err
	}
	tpuService, err := newTPUService(client)
	if err != nil {
		return nil, err
	}

	// ProjectID and.NetworkProjectID may be project number or name.
	projID, netProjID := tryConvertToProjectNames(config.ProjectID, config.NetworkProjectID, service)
	onXPN := projID != netProjID

	var networkURL string
	var subnetURL string
	var isLegacyNetwork bool

	if config.NetworkURL != "" {
		networkURL = config.NetworkURL
	} else if config.NetworkName != "" {
		networkURL = gceNetworkURL(config.APIEndpoint, netProjID, config.NetworkName)
	} else {
		// Other consumers may use the cloudprovider without utilizing the wrapped GCE API functions
		// or functions requiring network/subnetwork URLs (e.g. Kubelet).
		klog.Warningf("No network name or URL specified.")
	}

	if config.SubnetworkURL != "" {
		subnetURL = config.SubnetworkURL
	} else if config.SubnetworkName != "" {
		subnetURL = gceSubnetworkURL(config.APIEndpoint, netProjID, config.Region, config.SubnetworkName)
	}
	// If neither SubnetworkURL nor SubnetworkName are provided, defer to
	// lazy initialization. Determining subnetURL and isLegacyNetwork requires
	// GCE API call. Given that it's not used in many cases and the fact that
	// the provider is initialized also for Kubelets (and there can be thousands
	// of them) we defer to lazy initialization here.

	if len(config.ManagedZones) == 0 {
		config.ManagedZones, err = getZonesForRegion(service, config.ProjectID, config.Region)
		if err != nil {
			return nil, err
		}
	}
	if len(config.ManagedZones) > 1 {
		klog.Infof("managing multiple zones: %v", config.ManagedZones)
	}

	operationPollRateLimiter := flowcontrol.NewTokenBucketRateLimiter(5, 5) // 5 qps, 5 burst.

	gce := &Cloud{
		service:                  service,
		serviceAlpha:             serviceAlpha,
		serviceBeta:              serviceBeta,
		containerService:         containerService,
		tpuService:               tpuService,
		projectID:                projID,
		networkProjectID:         netProjID,
		onXPN:                    onXPN,
		region:                   config.Region,
		regional:                 config.Regional,
		localZone:                config.Zone,
		managedZones:             config.ManagedZones,
		networkURL:               networkURL,
		unsafeIsLegacyNetwork:    isLegacyNetwork,
		unsafeSubnetworkURL:      subnetURL,
		secondaryRangeName:       config.SecondaryRangeName,
		nodeTags:                 config.NodeTags,
		nodeInstancePrefix:       config.NodeInstancePrefix,
		useMetadataServer:        config.UseMetadataServer,
		operationPollRateLimiter: operationPollRateLimiter,
		AlphaFeatureGate:         config.AlphaFeatureGate,
		nodeZones:                map[string]sets.String{},
		metricsCollector:         newLoadBalancerMetrics(),
		stackType:                StackType(config.StackType),
	}

	gce.manager = &gceServiceManager{gce}
	gce.s = &cloud.Service{
		GA:            service,
		Alpha:         serviceAlpha,
		Beta:          serviceBeta,
		ProjectRouter: &gceProjectRouter{gce},
		RateLimiter:   &gceRateLimiter{gce},
	}
	gce.c = cloud.NewGCE(gce.s)

	return gce, nil
}