Merge pull request #14768 from hakman/guess_cloud

Guess cloud provider from state store path
This commit is contained in:
Kubernetes Prow Robot 2022-12-13 22:29:40 -08:00 committed by GitHub
commit 41fa042b89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 67 deletions

View File

@ -236,9 +236,9 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
}) })
cmd.Flags().StringSliceVar(&options.Zones, "zones", options.Zones, "Zones in which to run the cluster") cmd.Flags().StringSliceVar(&options.Zones, "zones", options.Zones, "Zones in which to run the cluster")
cmd.RegisterFlagCompletionFunc("zones", completeZone(options)) cmd.RegisterFlagCompletionFunc("zones", completeZone(options, &rootCommand))
cmd.Flags().StringSliceVar(&options.ControlPlaneZones, "control-plane-zones", options.ControlPlaneZones, "Zones in which to run control-plane nodes. (must be an odd number)") cmd.Flags().StringSliceVar(&options.ControlPlaneZones, "control-plane-zones", options.ControlPlaneZones, "Zones in which to run control-plane nodes. (must be an odd number)")
cmd.RegisterFlagCompletionFunc("control-plane-zones", completeZone(options)) cmd.RegisterFlagCompletionFunc("control-plane-zones", completeZone(options, &rootCommand))
if featureflag.ClusterAddons.Enabled() { if featureflag.ClusterAddons.Enabled() {
cmd.Flags().StringSliceVar(&options.AddonPaths, "add", options.AddonPaths, "Paths to addons we should add to the cluster") cmd.Flags().StringSliceVar(&options.AddonPaths, "add", options.AddonPaths, "Paths to addons we should add to the cluster")
@ -865,28 +865,17 @@ func loadSSHPublicKeys(sshPublicKey string) (map[string][]byte, error) {
return sshPublicKeys, nil return sshPublicKeys, nil
} }
func completeZone(options *CreateClusterOptions) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { func completeZone(options *CreateClusterOptions, rootCommand *RootCmd) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
var allClouds []api.CloudProviderID
if options.CloudProvider != "" { if options.CloudProvider != "" {
allClouds = []api.CloudProviderID{api.CloudProviderID(options.CloudProvider)} return zones.WellKnownZonesForCloud(api.CloudProviderID(options.CloudProvider)), cobra.ShellCompDirectiveNoFileComp
} else {
allClouds = clouds.SupportedClouds()
} }
var allZones []string cloud, err := clouds.GuessCloudForPath(rootCommand.RegistryPath)
for _, c := range allClouds { if err != nil {
zones := zones.WellKnownZonesForCloud(c) return commandutils.CompletionError("listing cloud zones", err)
for _, z := range zones {
if options.CloudProvider == "" {
allZones = append(allZones, z+"\t"+string(c))
} else {
allZones = append(allZones, z)
}
}
} }
sort.Strings(allZones) return zones.WellKnownZonesForCloud(cloud), cobra.ShellCompDirectiveNoFileComp
return allZones, cobra.ShellCompDirectiveNoFileComp
} }
} }

View File

@ -17,6 +17,10 @@ limitations under the License.
package clouds package clouds
import ( import (
"fmt"
"os"
"strings"
"k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag" "k8s.io/kops/pkg/featureflag"
) )
@ -38,3 +42,26 @@ func SupportedClouds() []kops.CloudProviderID {
return clouds return clouds
} }
// GuessCloudForPath tries to infer the cloud provider from a VFS path
func GuessCloudForPath(path string) (kops.CloudProviderID, error) {
switch {
case strings.HasPrefix(path, "azureblob://"):
return kops.CloudProviderAzure, nil
case strings.HasPrefix(path, "do://"):
return kops.CloudProviderDO, nil
case strings.HasPrefix(path, "gs://"):
return kops.CloudProviderGCE, nil
case strings.HasPrefix(path, "scw://"):
return kops.CloudProviderScaleway, nil
case strings.HasPrefix(path, "swift://"):
return kops.CloudProviderOpenstack, nil
case strings.HasPrefix(path, "s3://"):
if os.Getenv("HCLOUD_TOKEN") != "" {
return kops.CloudProviderHetzner, nil
}
return kops.CloudProviderAWS, nil
default:
return "", fmt.Errorf("cannot infer cloud provider from path: %q", path)
}
}

View File

@ -17,9 +17,9 @@ limitations under the License.
package zones package zones
import ( import (
"k8s.io/klog/v2" "sort"
"k8s.io/kops/pkg/apis/kops" "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/clouds"
) )
// These lists allows us to infer from certain well-known zones to a cloud // These lists allows us to infer from certain well-known zones to a cloud
@ -361,45 +361,23 @@ var azureZones = []string{
"westusstage", "westusstage",
} }
// GuessCloudForZone tries to infer the cloudprovider from the zone name
// Ali has the same zoneNames as AWS in the regions outside China, so if use AliCloud to install k8s in the regions outside China,
// the users need to provide parameter "--cloud". But the regions inside China can be easily identified.
func GuessCloudForZone(zone string) (kops.CloudProviderID, bool) {
providers := clouds.SupportedClouds()
var matches []kops.CloudProviderID
for _, provider := range providers {
zones := WellKnownZonesForCloud(provider)
for _, z := range zones {
if z == zone {
matches = append(matches, provider)
}
}
}
if len(matches) == 0 {
return "", false
}
if len(matches) > 1 {
klog.Warningf("found multiple providers for zone %q, must pass --cloud", zone)
return "", false
}
return matches[0], true
}
func WellKnownZonesForCloud(matchCloud kops.CloudProviderID) []string { func WellKnownZonesForCloud(matchCloud kops.CloudProviderID) []string {
var zones []string
switch matchCloud { switch matchCloud {
case kops.CloudProviderAWS: case kops.CloudProviderAWS:
return awsZones zones = awsZones
case kops.CloudProviderAzure: case kops.CloudProviderAzure:
return azureZones zones = azureZones
case kops.CloudProviderDO: case kops.CloudProviderDO:
return doZones zones = doZones
case kops.CloudProviderGCE: case kops.CloudProviderGCE:
return gceZones zones = gceZones
case kops.CloudProviderHetzner: case kops.CloudProviderHetzner:
return hetznerZones zones = hetznerZones
default: default:
return nil return nil
} }
sort.Strings(zones)
return zones
} }

View File

@ -33,8 +33,8 @@ import (
"k8s.io/kops/pkg/apis/kops/model" "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/kops/util" "k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/pkg/client/simple" "k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/clouds"
"k8s.io/kops/pkg/featureflag" "k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/zones"
"k8s.io/kops/upup/pkg/fi" "k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup" "k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/azure" "k8s.io/kops/upup/pkg/fi/cloudup/azure"
@ -285,20 +285,12 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
allZones.Insert(opt.ControlPlaneZones...) allZones.Insert(opt.ControlPlaneZones...)
if opt.CloudProvider == "" { if opt.CloudProvider == "" {
for _, zone := range allZones.List() { cloud, err := clouds.GuessCloudForPath(cluster.Spec.ConfigBase)
cloud, known := zones.GuessCloudForZone(zone) if err != nil {
if known { return nil, fmt.Errorf("pass in the cloud provider explicitly using --cloud: %w", err)
klog.Infof("Inferred %q cloud provider from zone %q", cloud, zone)
opt.CloudProvider = string(cloud)
break
}
}
if opt.CloudProvider == "" {
if allZones.Len() == 0 {
return nil, fmt.Errorf("must specify --zones or --cloud")
}
return nil, fmt.Errorf("unable to infer cloud provider from zones. pass in the cloud provider explicitly using --cloud")
} }
klog.V(2).Infof("Inferred %q cloud provider from state store %q", cloud, cluster.Spec.ConfigBase)
opt.CloudProvider = string(cloud)
} }
var cloud fi.Cloud var cloud fi.Cloud
@ -1350,7 +1342,7 @@ func setupTopology(opt *NewClusterOptions, cluster *api.Cluster, allZones sets.S
func setupAPI(opt *NewClusterOptions, cluster *api.Cluster) error { func setupAPI(opt *NewClusterOptions, cluster *api.Cluster) error {
// Populate the API access, so that it can be discoverable // Populate the API access, so that it can be discoverable
klog.Infof(" Cloud Provider ID = %s", cluster.Spec.GetCloudProvider()) klog.Infof("Cloud Provider ID: %q", cluster.Spec.GetCloudProvider())
if cluster.Spec.GetCloudProvider() == api.CloudProviderOpenstack { if cluster.Spec.GetCloudProvider() == api.CloudProviderOpenstack {
initializeOpenstackAPI(opt, cluster) initializeOpenstackAPI(opt, cluster)
} else if cluster.Spec.GetCloudProvider() == api.CloudProviderAzure { } else if cluster.Spec.GetCloudProvider() == api.CloudProviderAzure {