diff --git a/cluster-autoscaler/cloudprovider/gce/autoscaling_gce_client.go b/cluster-autoscaler/cloudprovider/gce/autoscaling_gce_client.go index 12d88fb183c5..688da0552f19 100644 --- a/cluster-autoscaler/cloudprovider/gce/autoscaling_gce_client.go +++ b/cluster-autoscaler/cloudprovider/gce/autoscaling_gce_client.go @@ -103,8 +103,8 @@ type AutoscalingGceClient interface { FetchMigTargetSize(GceRef) (int64, error) FetchMigBasename(GceRef) (string, error) FetchMigInstances(GceRef) ([]GceInstance, error) - FetchMigTemplateName(migRef GceRef) (string, error) - FetchMigTemplate(migRef GceRef, templateName string) (*gce.InstanceTemplate, error) + FetchMigTemplateName(migRef GceRef) (InstanceTemplateNameType, error) + FetchMigTemplate(migRef GceRef, templateName string, regional bool) (*gce.InstanceTemplate, error) FetchMigsWithName(zone string, filter *regexp.Regexp) ([]string, error) FetchZones(region string) ([]string, error) FetchAvailableCpuPlatforms() (map[string][]string, error) @@ -580,26 +580,33 @@ func (client *autoscalingGceClientV1) FetchAvailableCpuPlatforms() (map[string][ return availableCpuPlatforms, nil } -func (client *autoscalingGceClientV1) FetchMigTemplateName(migRef GceRef) (string, error) { +func (client *autoscalingGceClientV1) FetchMigTemplateName(migRef GceRef) (InstanceTemplateNameType, error) { registerRequest("instance_group_managers", "get") igm, err := client.gceService.InstanceGroupManagers.Get(migRef.Project, migRef.Zone, migRef.Name).Do() if err != nil { if err, ok := err.(*googleapi.Error); ok { if err.Code == http.StatusNotFound { - return "", errors.NewAutoscalerError(errors.NodeGroupDoesNotExistError, "%s", err.Error()) + return InstanceTemplateNameType{}, errors.NewAutoscalerError(errors.NodeGroupDoesNotExistError, "%s", err.Error()) } } - return "", err + return InstanceTemplateNameType{}, err } templateUrl, err := url.Parse(igm.InstanceTemplate) + regional, _ := regexp.MatchString("(/projects/.*[A-Za-z0-9]+.*/regions/)", templateUrl.String()) if err != nil { - return "", err + return InstanceTemplateNameType{}, err } _, templateName := path.Split(templateUrl.EscapedPath()) - return templateName, nil + return InstanceTemplateNameType{templateName, regional}, nil } -func (client *autoscalingGceClientV1) FetchMigTemplate(migRef GceRef, templateName string) (*gce.InstanceTemplate, error) { +func (client *autoscalingGceClientV1) FetchMigTemplate(migRef GceRef, templateName string, regional bool) (*gce.InstanceTemplate, error) { + if regional { + zoneHyphenIndex := strings.LastIndex(migRef.Zone, "-") + region := migRef.Zone[:zoneHyphenIndex] + registerRequest("region_instance_templates", "get") + return client.gceService.RegionInstanceTemplates.Get(migRef.Project, region, templateName).Do() + } registerRequest("instance_templates", "get") return client.gceService.InstanceTemplates.Get(migRef.Project, templateName).Do() } diff --git a/cluster-autoscaler/cloudprovider/gce/cache.go b/cluster-autoscaler/cloudprovider/gce/cache.go index 1d46e4f353d5..379c43a43cf2 100644 --- a/cluster-autoscaler/cloudprovider/gce/cache.go +++ b/cluster-autoscaler/cloudprovider/gce/cache.go @@ -33,6 +33,11 @@ type MachineTypeKey struct { MachineTypeName string } +type InstanceTemplateNameType struct { + Name string + Regional bool +} + // GceCache is used for caching cluster resources state. // // It is needed to: @@ -67,7 +72,7 @@ type GceCache struct { migTargetSizeCache map[GceRef]int64 migBaseNameCache map[GceRef]string listManagedInstancesResultsCache map[GceRef]string - instanceTemplateNameCache map[GceRef]string + instanceTemplateNameCache map[GceRef]InstanceTemplateNameType instanceTemplatesCache map[GceRef]*gce.InstanceTemplate kubeEnvCache map[GceRef]KubeEnv } @@ -85,7 +90,7 @@ func NewGceCache() *GceCache { migTargetSizeCache: map[GceRef]int64{}, migBaseNameCache: map[GceRef]string{}, listManagedInstancesResultsCache: map[GceRef]string{}, - instanceTemplateNameCache: map[GceRef]string{}, + instanceTemplateNameCache: map[GceRef]InstanceTemplateNameType{}, instanceTemplatesCache: map[GceRef]*gce.InstanceTemplate{}, kubeEnvCache: map[GceRef]KubeEnv{}, } @@ -334,23 +339,23 @@ func (gc *GceCache) InvalidateAllMigTargetSizes() { } // GetMigInstanceTemplateName returns the cached instance template ref for a mig GceRef -func (gc *GceCache) GetMigInstanceTemplateName(ref GceRef) (string, bool) { +func (gc *GceCache) GetMigInstanceTemplateName(ref GceRef) (InstanceTemplateNameType, bool) { gc.cacheMutex.Lock() defer gc.cacheMutex.Unlock() - templateName, found := gc.instanceTemplateNameCache[ref] + instanceTemplateNameType, found := gc.instanceTemplateNameCache[ref] if found { klog.V(5).Infof("Instance template names cache hit for %s", ref) } - return templateName, found + return instanceTemplateNameType, found } // SetMigInstanceTemplateName sets instance template ref for a mig GceRef -func (gc *GceCache) SetMigInstanceTemplateName(ref GceRef, templateName string) { +func (gc *GceCache) SetMigInstanceTemplateName(ref GceRef, instanceTemplateNameType InstanceTemplateNameType) { gc.cacheMutex.Lock() defer gc.cacheMutex.Unlock() - gc.instanceTemplateNameCache[ref] = templateName + gc.instanceTemplateNameCache[ref] = instanceTemplateNameType } // InvalidateMigInstanceTemplateName clears the instance template ref cache for a mig GceRef @@ -370,7 +375,7 @@ func (gc *GceCache) InvalidateAllMigInstanceTemplateNames() { defer gc.cacheMutex.Unlock() klog.V(5).Infof("Instance template names cache invalidated") - gc.instanceTemplateNameCache = map[GceRef]string{} + gc.instanceTemplateNameCache = map[GceRef]InstanceTemplateNameType{} } // GetMigInstanceTemplate returns the cached gce.InstanceTemplate for a mig GceRef diff --git a/cluster-autoscaler/cloudprovider/gce/mig_info_provider.go b/cluster-autoscaler/cloudprovider/gce/mig_info_provider.go index bd7c61c2ef8e..6bfb9db42874 100644 --- a/cluster-autoscaler/cloudprovider/gce/mig_info_provider.go +++ b/cluster-autoscaler/cloudprovider/gce/mig_info_provider.go @@ -21,6 +21,7 @@ import ( "fmt" "net/url" "path" + "regexp" "strings" "sync" "time" @@ -43,7 +44,7 @@ type MigInfoProvider interface { // GetMigBasename returns basename for given MIG ref GetMigBasename(migRef GceRef) (string, error) // GetMigInstanceTemplateName returns instance template name for given MIG ref - GetMigInstanceTemplateName(migRef GceRef) (string, error) + GetMigInstanceTemplateName(migRef GceRef) (InstanceTemplateNameType, error) // GetMigInstanceTemplate returns instance template for given MIG ref GetMigInstanceTemplate(migRef GceRef) (*gce.InstanceTemplate, error) // GetMigKubeEnv returns kube-env for given MIG ref @@ -243,44 +244,44 @@ func (c *cachingMigInfoProvider) GetMigBasename(migRef GceRef) (string, error) { return basename, nil } -func (c *cachingMigInfoProvider) GetMigInstanceTemplateName(migRef GceRef) (string, error) { +func (c *cachingMigInfoProvider) GetMigInstanceTemplateName(migRef GceRef) (InstanceTemplateNameType, error) { c.migInfoMutex.Lock() defer c.migInfoMutex.Unlock() - templateName, found := c.cache.GetMigInstanceTemplateName(migRef) + instanceTemplateNameType, found := c.cache.GetMigInstanceTemplateName(migRef) if found { - return templateName, nil + return instanceTemplateNameType, nil } err := c.fillMigInfoCache() - templateName, found = c.cache.GetMigInstanceTemplateName(migRef) + instanceTemplateNameType, found = c.cache.GetMigInstanceTemplateName(migRef) if err == nil && found { - return templateName, nil + return instanceTemplateNameType, nil } // fallback to querying for single mig - templateName, err = c.gceClient.FetchMigTemplateName(migRef) + instanceTemplateNameType, err = c.gceClient.FetchMigTemplateName(migRef) if err != nil { c.migLister.HandleMigIssue(migRef, err) - return "", err + return InstanceTemplateNameType{}, err } - c.cache.SetMigInstanceTemplateName(migRef, templateName) - return templateName, nil + c.cache.SetMigInstanceTemplateName(migRef, instanceTemplateNameType) + return instanceTemplateNameType, nil } func (c *cachingMigInfoProvider) GetMigInstanceTemplate(migRef GceRef) (*gce.InstanceTemplate, error) { - templateName, err := c.GetMigInstanceTemplateName(migRef) + instanceTemplateNameType, err := c.GetMigInstanceTemplateName(migRef) if err != nil { return nil, err } template, found := c.cache.GetMigInstanceTemplate(migRef) - if found && template.Name == templateName { + if found && template.Name == instanceTemplateNameType.Name { return template, nil } - klog.V(2).Infof("Instance template of mig %v changed to %v", migRef.Name, templateName) - template, err = c.gceClient.FetchMigTemplate(migRef, templateName) + klog.V(2).Infof("Instance template of mig %v changed to %v", migRef.Name, instanceTemplateNameType.Name) + template, err = c.gceClient.FetchMigTemplate(migRef, instanceTemplateNameType.Name, instanceTemplateNameType.Regional) if err != nil { return nil, err } @@ -363,7 +364,8 @@ func (c *cachingMigInfoProvider) fillMigInfoCache() error { templateUrl, err := url.Parse(zoneMig.InstanceTemplate) if err == nil { _, templateName := path.Split(templateUrl.EscapedPath()) - c.cache.SetMigInstanceTemplateName(zoneMigRef, templateName) + regional, _ := regexp.MatchString("(/projects/.*[A-Za-z0-9]+.*/regions/)", templateUrl.String()) + c.cache.SetMigInstanceTemplateName(zoneMigRef, InstanceTemplateNameType{templateName, regional}) } } }