pkg/helpers/helpers.go (146 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package helpers import ( // "fmt" "bytes" "crypto/rand" "crypto/rsa" "encoding/json" "fmt" "io" "os" "runtime" "strings" "github.com/Azure/aks-engine-azurestack/pkg/i18n" "golang.org/x/crypto/ssh" ) // NormalizeAzureRegion returns a normalized Azure region with white spaces removed and converted to lower case func NormalizeAzureRegion(name string) string { return strings.ToLower(strings.Replace(name, " ", "", -1)) } // JSONMarshalIndent marshals formatted JSON w/ optional SetEscapeHTML func JSONMarshalIndent(content interface{}, prefix, indent string, escape bool) ([]byte, error) { b, err := JSONMarshal(content, escape) if err != nil { return nil, err } var bufIndent bytes.Buffer if err := json.Indent(&bufIndent, b, prefix, indent); err != nil { return nil, err } return bufIndent.Bytes(), nil } // JSONMarshal marshals JSON w/ optional SetEscapeHTML func JSONMarshal(content interface{}, escape bool) ([]byte, error) { var buf bytes.Buffer enc := json.NewEncoder(&buf) enc.SetEscapeHTML(escape) if err := enc.Encode(content); err != nil { return nil, err } return buf.Bytes(), nil } // EqualError is a nil-safe method which reports whether errors a and b are considered equal. // They're equal if both are nil, or both are not nil and a.Error() == b.Error(). func EqualError(a, b error) bool { return a == nil && b == nil || a != nil && b != nil && a.Error() == b.Error() } // CreateSSH creates an SSH key pair. func CreateSSH(rg io.Reader, s *i18n.Translator) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { privateKey, err = rsa.GenerateKey(rg, SSHKeySize) if err != nil { return nil, "", s.Errorf("failed to generate private key for ssh: %q", err) } publicKey := privateKey.PublicKey sshPublicKey, err := ssh.NewPublicKey(&publicKey) if err != nil { return nil, "", s.Errorf("failed to create openssh public key string: %q", err) } authorizedKeyBytes := ssh.MarshalAuthorizedKey(sshPublicKey) authorizedKey := string(authorizedKeyBytes) return privateKey, authorizedKey, nil } // GetHomeDir attempts to get the home dir from env func GetHomeDir() string { if runtime.GOOS == "windows" { home := os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH") if home == "" { home = os.Getenv("USERPROFILE") } return home } return os.Getenv("HOME") } // ShellQuote returns a string that is enclosed within single quotes. If the string already has single quotes, they will be escaped. func ShellQuote(s string) string { return `'` + strings.Replace(s, `'`, `'\''`, -1) + `'` } // CreateSaveSSH generates and stashes an SSH key pair. func CreateSaveSSH(username, outputDirectory string, s *i18n.Translator) (privateKey *rsa.PrivateKey, publicKeyString string, err error) { privateKey, publicKeyString, err = CreateSSH(rand.Reader, s) if err != nil { return nil, "", err } privateKeyPem := privateKeyToPem(privateKey) f := &FileSaver{ Translator: s, } err = f.SaveFile(outputDirectory, fmt.Sprintf("%s_rsa", username), privateKeyPem) if err != nil { return nil, "", err } return privateKey, publicKeyString, nil } // GetCloudTargetEnv determines and returns whether the region is a sovereign cloud which // have their own data compliance regulations (China/Germany/USGov) or standard // Azure public cloud func GetCloudTargetEnv(location string) string { loc := strings.ToLower(strings.Join(strings.Fields(location), "")) switch { case loc == "chinaeast" || loc == "chinanorth" || loc == "chinaeast2" || loc == "chinaeast3" || loc == "chinanorth2" || loc == "chinanorth3": return "AzureChinaCloud" case loc == "germanynortheast" || loc == "germanycentral": return "AzureGermanCloud" case strings.HasPrefix(loc, "usgov") || strings.HasPrefix(loc, "usdod"): return "AzureUSGovernmentCloud" default: return "AzurePublicCloud" } } // GetTargetEnv determines and returns whether the region is a sovereign cloud which // have their own data compliance regulations (China/Germany/USGov) or standard // Azure public cloud // CustomCloudName is name of environment if customCloudProfile is provided, it will be empty string if customCloudProfile is empty. // Because customCloudProfile is empty for deployment for AzurePublicCloud, AzureChinaCloud,AzureGermanCloud,AzureUSGovernmentCloud, // The customCloudName value will be empty string for those clouds // This value is also used in azure.json file, which is used by Kubernetes to read various endpoints specific to cloud func GetTargetEnv(location, customCloudName string) string { switch { // Kubernetes only understand "AzureStackCloud" env right now to read from custom endpoints: // https://github.com/Azure/go-autorest/blob/master/autorest/azure/environments.go // We should always return "AzureStackCloud" when CustomCloudProfile was used case customCloudName != "": return "AzureStackCloud" default: return GetCloudTargetEnv(location) } } // EnsureString returns an string for the default value. // If val is not empty, return val // If val is empty, return defaultVal func EnsureString(val, defaultVal string) string { if val != "" { return val } return defaultVal } // GetLogAnalyticsWorkspaceDomain gets the domain of azure log analytics workspace based on the cloud or azure stack dependenciesLocation func GetLogAnalyticsWorkspaceDomain(cloudOrDependenciesLocation string) string { var workspaceDomain string switch strings.ToLower(strings.TrimSpace(cloudOrDependenciesLocation)) { case "azurepubliccloud", "public": workspaceDomain = "opinsights.azure.com" case "azurechinacloud", "china": workspaceDomain = "opinsights.azure.cn" case "azureusgovernmentcloud", "usgovernment": workspaceDomain = "opinsights.azure.us" case "azuregermancloud", "german": workspaceDomain = "opinsights.azure.de" default: workspaceDomain = "opinsights.azure.com" } return workspaceDomain } // GetEnglishOrderedQuotedListWithOxfordCommas returns a string that you can use in an English statement to report a list of things // With each thing in quotes, e.g. "thing 1", "thing 2", and "thing 3" // Oxford Comma not optional! func GetEnglishOrderedQuotedListWithOxfordCommas(l []string) string { var ret string for i, item := range l { ret += fmt.Sprintf("\"%s\"", item) switch i { case len(l) - 2: if len(l) > 2 { ret += ", and " } else { ret += " and " } case len(l) - 2: ret += ", and " case len(l) - 1: break default: ret += ", " } } return ret }