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.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.RegisterFlagCompletionFunc("control-plane-zones", completeZone(options))
cmd.RegisterFlagCompletionFunc("control-plane-zones", completeZone(options, &rootCommand))
if featureflag.ClusterAddons.Enabled() {
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
}
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) {
var allClouds []api.CloudProviderID
if options.CloudProvider != "" {
allClouds = []api.CloudProviderID{api.CloudProviderID(options.CloudProvider)}
} else {
allClouds = clouds.SupportedClouds()
return zones.WellKnownZonesForCloud(api.CloudProviderID(options.CloudProvider)), cobra.ShellCompDirectiveNoFileComp
}
var allZones []string
for _, c := range allClouds {
zones := zones.WellKnownZonesForCloud(c)
for _, z := range zones {
if options.CloudProvider == "" {
allZones = append(allZones, z+"\t"+string(c))
} else {
allZones = append(allZones, z)
}
}
cloud, err := clouds.GuessCloudForPath(rootCommand.RegistryPath)
if err != nil {
return commandutils.CompletionError("listing cloud zones", err)
}
sort.Strings(allZones)
return allZones, cobra.ShellCompDirectiveNoFileComp
return zones.WellKnownZonesForCloud(cloud), cobra.ShellCompDirectiveNoFileComp
}
}

View File

@ -17,6 +17,10 @@ limitations under the License.
package clouds
import (
"fmt"
"os"
"strings"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/featureflag"
)
@ -38,3 +42,26 @@ func SupportedClouds() []kops.CloudProviderID {
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
import (
"k8s.io/klog/v2"
"sort"
"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
@ -361,45 +361,23 @@ var azureZones = []string{
"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 {
var zones []string
switch matchCloud {
case kops.CloudProviderAWS:
return awsZones
zones = awsZones
case kops.CloudProviderAzure:
return azureZones
zones = azureZones
case kops.CloudProviderDO:
return doZones
zones = doZones
case kops.CloudProviderGCE:
return gceZones
zones = gceZones
case kops.CloudProviderHetzner:
return hetznerZones
zones = hetznerZones
default:
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/util"
"k8s.io/kops/pkg/client/simple"
"k8s.io/kops/pkg/clouds"
"k8s.io/kops/pkg/featureflag"
"k8s.io/kops/pkg/zones"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/azure"
@ -285,20 +285,12 @@ func NewCluster(opt *NewClusterOptions, clientset simple.Clientset) (*NewCluster
allZones.Insert(opt.ControlPlaneZones...)
if opt.CloudProvider == "" {
for _, zone := range allZones.List() {
cloud, known := zones.GuessCloudForZone(zone)
if known {
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")
cloud, err := clouds.GuessCloudForPath(cluster.Spec.ConfigBase)
if err != nil {
return nil, fmt.Errorf("pass in the cloud provider explicitly using --cloud: %w", err)
}
klog.V(2).Infof("Inferred %q cloud provider from state store %q", cloud, cluster.Spec.ConfigBase)
opt.CloudProvider = string(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 {
// 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 {
initializeOpenstackAPI(opt, cluster)
} else if cluster.Spec.GetCloudProvider() == api.CloudProviderAzure {