From e6721038043384be300dbcfc807de7506c68b7f8 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 16 Dec 2024 15:45:00 -0800 Subject: [PATCH 01/19] Option to load addon configs from file --- cmd/minikube/cmd/config/configure.go | 107 +++++++++++++++++++++------ 1 file changed, 83 insertions(+), 24 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 435dabdb904a..58c342b4eac7 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -17,6 +17,7 @@ limitations under the License. package config import ( + "log" "net" "os" "regexp" @@ -38,6 +39,7 @@ import ( "k8s.io/minikube/pkg/minikube/sysinit" ) +var AddonConfigFile = "" var posResponses = []string{"yes", "y"} var negResponses = []string{"no", "n"} @@ -73,25 +75,56 @@ var addonsConfigureCmd = &cobra.Command{ acrClientID := "changeme" acrPassword := "changeme" - enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) - if enableAWSECR { - awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") - awsAccessKey = AskForStaticValue("-- Enter AWS Secret Access Key: ") - awsSessionToken = AskForStaticValueOptional("-- (Optional) Enter AWS Session Token: ") - awsRegion = AskForStaticValue("-- Enter AWS Region: ") - awsAccount = AskForStaticValue("-- Enter 12 digit AWS Account ID (Comma separated list): ") - awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") + regCredsConfig := make(map[string]any) + + if regCredsConfig == nil || regCredsConfig["enableAWSEcr"] == "prompt" { + enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) + if enableAWSECR { + awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") + awsAccessKey = AskForStaticValue("-- Enter AWS Secret Access Key: ") + awsSessionToken = AskForStaticValueOptional("-- (Optional) Enter AWS Session Token: ") + awsRegion = AskForStaticValue("-- Enter AWS Region: ") + awsAccount = AskForStaticValue("-- Enter 12 digit AWS Account ID (Comma separated list): ") + awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") + } + } else if regCredsConfig["enableAWSEcr"] == "enable" { + log.Println("Loading AWS ECR configs from: ", AddonConfigFile) + // Then read the configs + awsAccessID = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessID") + awsAccessKey = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessKey") + awsSessionToken = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsSessionToken") + awsRegion = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsRegion") + awsAccount = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccount") + awsRole = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsRole") + } else if regCredsConfig["enableAWSEcr"] == "disable" { + log.Println("Ignoring AWS ECR configs") + } else { + log.Printf("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableAWSEcr"]) } - enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) - if enableGCR { - gcrPath := AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") - gcrchangeURL := AskForYesNoConfirmation("-- Do you want to change the GCR URL (Default https://gcr.io)?", posResponses, negResponses) + gcrPath := "" + if regCredsConfig == nil || regCredsConfig["enableGCR"] == "prompt" { + enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) + if enableGCR { + gcrPath = AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") + gcrchangeURL := AskForYesNoConfirmation("-- Do you want to change the GCR URL (Default https://gcr.io)?", posResponses, negResponses) - if gcrchangeURL { - gcrURL = AskForStaticValue("-- Enter GCR URL (e.g. https://asia.gcr.io):") + if gcrchangeURL { + gcrURL = AskForStaticValue("-- Enter GCR URL (e.g. https://asia.gcr.io):") + } } + } else if regCredsConfig["enableGCR"] == "enable" { + log.Println("Loading GCR configs from: ", AddonConfigFile) + // Then read the configs + gcrPath = GetNextedJsonString(regCredsConfig, "gcrConfigs", "gcrPath") + gcrURL = GetNextedJsonString(regCredsConfig, "gcrConfigs", "gcrURL") + } else if regCredsConfig["enableGCR"] == "disable" { + log.Println("Ignoring GCR configs") + } else { + log.Printf("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableGCR"]) + } + if gcrPath != "" { // Read file from disk dat, err := os.ReadFile(gcrPath) @@ -102,18 +135,39 @@ var addonsConfigureCmd = &cobra.Command{ } } - enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) - if enableDR { - dockerServer = AskForStaticValue("-- Enter docker registry server url: ") - dockerUser = AskForStaticValue("-- Enter docker registry username: ") - dockerPass = AskForPasswordValue("-- Enter docker registry password: ") + if regCredsConfig == nil || regCredsConfig["enableDockerRegistry"] == "prompt" { + enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) + if enableDR { + dockerServer = AskForStaticValue("-- Enter docker registry server url: ") + dockerUser = AskForStaticValue("-- Enter docker registry username: ") + dockerPass = AskForPasswordValue("-- Enter docker registry password: ") + } + } else if regCredsConfig["enableDockerRegistry"] == "enable" { + dockerServer = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerServer") + dockerUser = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerUser") + dockerPass = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerPass") + } else if regCredsConfig["enableDockerRegistry"] == "disable" { + log.Println("Ignoring Docker Registry configs") + } else { + log.Printf("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableDockerRegistry"]) } - enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) - if enableACR { - acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") - acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") - acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") + if regCredsConfig == nil || regCredsConfig["enableACR"] == "prompt" { + enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) + if enableACR { + acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") + acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") + acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") + } + } else if regCredsConfig == nil || regCredsConfig["enableACR"] == "enable" { + log.Println("Loading ACR configs from: ", AddonConfigFile) + acrURL = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrURL") + acrClientID = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrClientID") + acrPassword = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrPassword") + } else if regCredsConfig["enableDockerRegistry"] == "disable" { + log.Println("Ignoring ACR configs") + } else { + log.Printf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableACR"]) } namespace := "kube-system" @@ -339,5 +393,10 @@ func unpauseWholeCluster(co mustload.ClusterController) { } func init() { + addonsConfigureCmd.Flags().StringVarP(&AddonConfigFile, "config-file", "c", "", "An optional configuration file to read addon specific configs from instead of being prompted each time.") AddonsCmd.AddCommand(addonsConfigureCmd) } + +func GetNextedJsonString(configMap map[string]any, keypath ...string) (out string) { + return +} From da060c14ace7f68b801b601c0c5c0918e506bad2 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 16 Dec 2024 17:28:26 -0800 Subject: [PATCH 02/19] properly using minikube.out pkg for printing messages --- cmd/minikube/cmd/config/configure.go | 104 ++++++++++++++++++--------- 1 file changed, 72 insertions(+), 32 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 58c342b4eac7..1f60bb6791bb 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -17,9 +17,13 @@ limitations under the License. package config import ( + "encoding/json" + "errors" + "fmt" "log" "net" "os" + "reflect" "regexp" "time" @@ -77,7 +81,19 @@ var addonsConfigureCmd = &cobra.Command{ regCredsConfig := make(map[string]any) - if regCredsConfig == nil || regCredsConfig["enableAWSEcr"] == "prompt" { + out.Ln("Reading %s configs from %s", addon, AddonConfigFile) + if confData, err := os.ReadFile(AddonConfigFile); err != nil && errors.Is(err, os.ErrNotExist) { + exit.Message(reason.Usage, "config file does not exist") + } else if err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } else if err = json.Unmarshal(confData, ®CredsConfig); err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } + + awsEcrAction := getNestedJsonString(regCredsConfig, "enableAWSEcr") + if regCredsConfig == nil || awsEcrAction == "prompt" { enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) if enableAWSECR { awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") @@ -87,23 +103,24 @@ var addonsConfigureCmd = &cobra.Command{ awsAccount = AskForStaticValue("-- Enter 12 digit AWS Account ID (Comma separated list): ") awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") } - } else if regCredsConfig["enableAWSEcr"] == "enable" { + } else if awsEcrAction == "enable" { log.Println("Loading AWS ECR configs from: ", AddonConfigFile) // Then read the configs - awsAccessID = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessID") - awsAccessKey = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessKey") - awsSessionToken = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsSessionToken") - awsRegion = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsRegion") - awsAccount = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccount") - awsRole = GetNextedJsonString(regCredsConfig, "awsEcrConfigs", "awsRole") - } else if regCredsConfig["enableAWSEcr"] == "disable" { + awsAccessID = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessID") + awsAccessKey = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessKey") + awsSessionToken = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsSessionToken") + awsRegion = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsRegion") + awsAccount = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccount") + awsRole = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsRole") + } else if awsEcrAction == "disable" { log.Println("Ignoring AWS ECR configs") } else { - log.Printf("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableAWSEcr"]) + out.Ln("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", awsEcrAction) } gcrPath := "" - if regCredsConfig == nil || regCredsConfig["enableGCR"] == "prompt" { + gcrAction := getNestedJsonString(regCredsConfig, "enableGCR") + if regCredsConfig == nil || gcrAction == "prompt" { enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) if enableGCR { gcrPath = AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") @@ -113,15 +130,15 @@ var addonsConfigureCmd = &cobra.Command{ gcrURL = AskForStaticValue("-- Enter GCR URL (e.g. https://asia.gcr.io):") } } - } else if regCredsConfig["enableGCR"] == "enable" { + } else if gcrAction == "enable" { log.Println("Loading GCR configs from: ", AddonConfigFile) // Then read the configs - gcrPath = GetNextedJsonString(regCredsConfig, "gcrConfigs", "gcrPath") - gcrURL = GetNextedJsonString(regCredsConfig, "gcrConfigs", "gcrURL") - } else if regCredsConfig["enableGCR"] == "disable" { + gcrPath = getNestedJsonString(regCredsConfig, "gcrConfigs", "gcrPath") + gcrURL = getNestedJsonString(regCredsConfig, "gcrConfigs", "gcrURL") + } else if gcrAction == "disable" { log.Println("Ignoring GCR configs") } else { - log.Printf("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableGCR"]) + out.Ln("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", gcrAction) } if gcrPath != "" { @@ -135,39 +152,41 @@ var addonsConfigureCmd = &cobra.Command{ } } - if regCredsConfig == nil || regCredsConfig["enableDockerRegistry"] == "prompt" { + dockerRegistryAction := getNestedJsonString(regCredsConfig, "enableDockerRegistry") + if regCredsConfig == nil || dockerRegistryAction == "prompt" { enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) if enableDR { dockerServer = AskForStaticValue("-- Enter docker registry server url: ") dockerUser = AskForStaticValue("-- Enter docker registry username: ") dockerPass = AskForPasswordValue("-- Enter docker registry password: ") } - } else if regCredsConfig["enableDockerRegistry"] == "enable" { - dockerServer = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerServer") - dockerUser = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerUser") - dockerPass = GetNextedJsonString(regCredsConfig, "dockerConfigs", "dockerPass") - } else if regCredsConfig["enableDockerRegistry"] == "disable" { + } else if dockerRegistryAction == "enable" { + dockerServer = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerServer") + dockerUser = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerUser") + dockerPass = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerPass") + } else if dockerRegistryAction == "disable" { log.Println("Ignoring Docker Registry configs") } else { - log.Printf("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableDockerRegistry"]) + out.Ln("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", dockerRegistryAction) } - if regCredsConfig == nil || regCredsConfig["enableACR"] == "prompt" { + acrAction := getNestedJsonString(regCredsConfig, "enableACR") + if regCredsConfig == nil || acrAction == "prompt" { enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) if enableACR { acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") } - } else if regCredsConfig == nil || regCredsConfig["enableACR"] == "enable" { + } else if regCredsConfig == nil || acrAction == "enable" { log.Println("Loading ACR configs from: ", AddonConfigFile) - acrURL = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrURL") - acrClientID = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrClientID") - acrPassword = GetNextedJsonString(regCredsConfig, "acrConfigs", "acrPassword") - } else if regCredsConfig["enableDockerRegistry"] == "disable" { + acrURL = getNestedJsonString(regCredsConfig, "acrConfigs", "acrURL") + acrClientID = getNestedJsonString(regCredsConfig, "acrConfigs", "acrClientID") + acrPassword = getNestedJsonString(regCredsConfig, "acrConfigs", "acrPassword") + } else if acrAction == "disable" { log.Println("Ignoring ACR configs") } else { - log.Printf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableACR"]) + out.Stringf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableACR"]) } namespace := "kube-system" @@ -397,6 +416,27 @@ func init() { AddonsCmd.AddCommand(addonsConfigureCmd) } -func GetNextedJsonString(configMap map[string]any, keypath ...string) (out string) { - return +func getNestedJsonString(configMap map[string]any, keypath ...string) string { + for idx, key := range keypath { + next, ok := configMap[key] + if !ok || next == nil { + break + } + if idx == len(keypath)-1 { + if strval, ok := next.(string); ok { + return strval + } else { + log.Println("Expected string at last key, found: ", reflect.TypeOf(next), next) + break + } + } else { + if mapval, ok := next.(map[string]any); ok && mapval != nil { + configMap = mapval + } else { + out.Stringf("expected map[string]any at %d, found: %v", idx, mapval) + break + } + } + } + return "" } From f275e5b24dc20fbec934f4164fed05d08deb2d20 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 16 Dec 2024 20:38:10 -0800 Subject: [PATCH 03/19] Emitting useful logs and only reading AddonConfigFile if provided --- cmd/minikube/cmd/config/configure.go | 95 ++++++++++++++-------------- 1 file changed, 48 insertions(+), 47 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 1f60bb6791bb..12815d5bb1ae 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -20,7 +20,6 @@ import ( "encoding/json" "errors" "fmt" - "log" "net" "os" "reflect" @@ -57,8 +56,23 @@ var addonsConfigureCmd = &cobra.Command{ } profile := ClusterFlagValue() - addon := args[0] + + configFileData := make(map[string]any) + + if AddonConfigFile != "" { + out.Ln("Reading %s configs from %s", addon, AddonConfigFile) + if confData, err := os.ReadFile(AddonConfigFile); err != nil && errors.Is(err, os.ErrNotExist) { + exit.Message(reason.Usage, "config file does not exist") + } else if err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } else if err = json.Unmarshal(confData, &configFileData); err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } + } + // allows for additional prompting of information when enabling addons switch addon { case "registry-creds": @@ -79,21 +93,8 @@ var addonsConfigureCmd = &cobra.Command{ acrClientID := "changeme" acrPassword := "changeme" - regCredsConfig := make(map[string]any) - - out.Ln("Reading %s configs from %s", addon, AddonConfigFile) - if confData, err := os.ReadFile(AddonConfigFile); err != nil && errors.Is(err, os.ErrNotExist) { - exit.Message(reason.Usage, "config file does not exist") - } else if err != nil { - exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, - fmt.Sprintf("error opening config file: %v", err)) - } else if err = json.Unmarshal(confData, ®CredsConfig); err != nil { - exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, - fmt.Sprintf("error opening config file: %v", err)) - } - - awsEcrAction := getNestedJsonString(regCredsConfig, "enableAWSEcr") - if regCredsConfig == nil || awsEcrAction == "prompt" { + awsEcrAction := getNestedJsonString(configFileData, "enableAWSEcr") + if awsEcrAction == "prompt" || awsEcrAction == "" { enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) if enableAWSECR { awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") @@ -104,23 +105,23 @@ var addonsConfigureCmd = &cobra.Command{ awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") } } else if awsEcrAction == "enable" { - log.Println("Loading AWS ECR configs from: ", AddonConfigFile) + out.Ln("Loading AWS ECR configs from: ", AddonConfigFile) // Then read the configs - awsAccessID = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessID") - awsAccessKey = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccessKey") - awsSessionToken = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsSessionToken") - awsRegion = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsRegion") - awsAccount = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsAccount") - awsRole = getNestedJsonString(regCredsConfig, "awsEcrConfigs", "awsRole") + awsAccessID = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessID") + awsAccessKey = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessKey") + awsSessionToken = getNestedJsonString(configFileData, "awsEcrConfigs", "awsSessionToken") + awsRegion = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRegion") + awsAccount = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccount") + awsRole = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRole") } else if awsEcrAction == "disable" { - log.Println("Ignoring AWS ECR configs") + out.Ln("Ignoring AWS ECR configs") } else { out.Ln("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", awsEcrAction) } gcrPath := "" - gcrAction := getNestedJsonString(regCredsConfig, "enableGCR") - if regCredsConfig == nil || gcrAction == "prompt" { + gcrAction := getNestedJsonString(configFileData, "enableGCR") + if gcrAction == "prompt" || gcrAction == "" { enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) if enableGCR { gcrPath = AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") @@ -131,12 +132,12 @@ var addonsConfigureCmd = &cobra.Command{ } } } else if gcrAction == "enable" { - log.Println("Loading GCR configs from: ", AddonConfigFile) + out.Ln("Loading GCR configs from: ", AddonConfigFile) // Then read the configs - gcrPath = getNestedJsonString(regCredsConfig, "gcrConfigs", "gcrPath") - gcrURL = getNestedJsonString(regCredsConfig, "gcrConfigs", "gcrURL") + gcrPath = getNestedJsonString(configFileData, "gcrConfigs", "gcrPath") + gcrURL = getNestedJsonString(configFileData, "gcrConfigs", "gcrURL") } else if gcrAction == "disable" { - log.Println("Ignoring GCR configs") + out.Ln("Ignoring GCR configs") } else { out.Ln("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", gcrAction) } @@ -152,8 +153,8 @@ var addonsConfigureCmd = &cobra.Command{ } } - dockerRegistryAction := getNestedJsonString(regCredsConfig, "enableDockerRegistry") - if regCredsConfig == nil || dockerRegistryAction == "prompt" { + dockerRegistryAction := getNestedJsonString(configFileData, "enableDockerRegistry") + if dockerRegistryAction == "prompt" || dockerRegistryAction == "" { enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) if enableDR { dockerServer = AskForStaticValue("-- Enter docker registry server url: ") @@ -161,32 +162,32 @@ var addonsConfigureCmd = &cobra.Command{ dockerPass = AskForPasswordValue("-- Enter docker registry password: ") } } else if dockerRegistryAction == "enable" { - dockerServer = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerServer") - dockerUser = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerUser") - dockerPass = getNestedJsonString(regCredsConfig, "dockerConfigs", "dockerPass") + dockerServer = getNestedJsonString(configFileData, "dockerConfigs", "dockerServer") + dockerUser = getNestedJsonString(configFileData, "dockerConfigs", "dockerUser") + dockerPass = getNestedJsonString(configFileData, "dockerConfigs", "dockerPass") } else if dockerRegistryAction == "disable" { - log.Println("Ignoring Docker Registry configs") + out.Ln("Ignoring Docker Registry configs") } else { out.Ln("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", dockerRegistryAction) } - acrAction := getNestedJsonString(regCredsConfig, "enableACR") - if regCredsConfig == nil || acrAction == "prompt" { + acrAction := getNestedJsonString(configFileData, "enableACR") + if acrAction == "prompt" || acrAction == "" { enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) if enableACR { acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") } - } else if regCredsConfig == nil || acrAction == "enable" { - log.Println("Loading ACR configs from: ", AddonConfigFile) - acrURL = getNestedJsonString(regCredsConfig, "acrConfigs", "acrURL") - acrClientID = getNestedJsonString(regCredsConfig, "acrConfigs", "acrClientID") - acrPassword = getNestedJsonString(regCredsConfig, "acrConfigs", "acrPassword") + } else if configFileData == nil || acrAction == "enable" { + out.Ln("Loading ACR configs from: ", AddonConfigFile) + acrURL = getNestedJsonString(configFileData, "acrConfigs", "acrURL") + acrClientID = getNestedJsonString(configFileData, "acrConfigs", "acrClientID") + acrPassword = getNestedJsonString(configFileData, "acrConfigs", "acrPassword") } else if acrAction == "disable" { - log.Println("Ignoring ACR configs") + out.Ln("Ignoring ACR configs") } else { - out.Stringf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", regCredsConfig["enableACR"]) + out.Stringf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", configFileData["enableACR"]) } namespace := "kube-system" @@ -426,7 +427,7 @@ func getNestedJsonString(configMap map[string]any, keypath ...string) string { if strval, ok := next.(string); ok { return strval } else { - log.Println("Expected string at last key, found: ", reflect.TypeOf(next), next) + out.Ln("Expected string at last key, found: ", reflect.TypeOf(next), next) break } } else { From 8ea83bc3922c59ffece97ce88774032001706fdf Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 16 Dec 2024 23:48:33 -0800 Subject: [PATCH 04/19] fixing format string --- cmd/minikube/cmd/config/configure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 12815d5bb1ae..b0485436afc1 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -105,7 +105,7 @@ var addonsConfigureCmd = &cobra.Command{ awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") } } else if awsEcrAction == "enable" { - out.Ln("Loading AWS ECR configs from: ", AddonConfigFile) + out.Ln("Loading AWS ECR configs from: %s", AddonConfigFile) // Then read the configs awsAccessID = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessID") awsAccessKey = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessKey") From 58d369f4a6842a115446e721b37c911ced247b83 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Tue, 17 Dec 2024 11:26:02 -0800 Subject: [PATCH 05/19] Moving addon specific config input and parsing to its own function --- cmd/minikube/cmd/config/configure.go | 389 ++++++++++++++------------- 1 file changed, 196 insertions(+), 193 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index b0485436afc1..3ddd63023984 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -76,199 +76,7 @@ var addonsConfigureCmd = &cobra.Command{ // allows for additional prompting of information when enabling addons switch addon { case "registry-creds": - - // Default values - awsAccessID := "changeme" - awsAccessKey := "changeme" - awsSessionToken := "" - awsRegion := "changeme" - awsAccount := "changeme" - awsRole := "changeme" - gcrApplicationDefaultCredentials := "changeme" - dockerServer := "changeme" - dockerUser := "changeme" - dockerPass := "changeme" - gcrURL := "https://gcr.io" - acrURL := "changeme" - acrClientID := "changeme" - acrPassword := "changeme" - - awsEcrAction := getNestedJsonString(configFileData, "enableAWSEcr") - if awsEcrAction == "prompt" || awsEcrAction == "" { - enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) - if enableAWSECR { - awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") - awsAccessKey = AskForStaticValue("-- Enter AWS Secret Access Key: ") - awsSessionToken = AskForStaticValueOptional("-- (Optional) Enter AWS Session Token: ") - awsRegion = AskForStaticValue("-- Enter AWS Region: ") - awsAccount = AskForStaticValue("-- Enter 12 digit AWS Account ID (Comma separated list): ") - awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") - } - } else if awsEcrAction == "enable" { - out.Ln("Loading AWS ECR configs from: %s", AddonConfigFile) - // Then read the configs - awsAccessID = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessID") - awsAccessKey = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessKey") - awsSessionToken = getNestedJsonString(configFileData, "awsEcrConfigs", "awsSessionToken") - awsRegion = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRegion") - awsAccount = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccount") - awsRole = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRole") - } else if awsEcrAction == "disable" { - out.Ln("Ignoring AWS ECR configs") - } else { - out.Ln("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", awsEcrAction) - } - - gcrPath := "" - gcrAction := getNestedJsonString(configFileData, "enableGCR") - if gcrAction == "prompt" || gcrAction == "" { - enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) - if enableGCR { - gcrPath = AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") - gcrchangeURL := AskForYesNoConfirmation("-- Do you want to change the GCR URL (Default https://gcr.io)?", posResponses, negResponses) - - if gcrchangeURL { - gcrURL = AskForStaticValue("-- Enter GCR URL (e.g. https://asia.gcr.io):") - } - } - } else if gcrAction == "enable" { - out.Ln("Loading GCR configs from: ", AddonConfigFile) - // Then read the configs - gcrPath = getNestedJsonString(configFileData, "gcrConfigs", "gcrPath") - gcrURL = getNestedJsonString(configFileData, "gcrConfigs", "gcrURL") - } else if gcrAction == "disable" { - out.Ln("Ignoring GCR configs") - } else { - out.Ln("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", gcrAction) - } - - if gcrPath != "" { - // Read file from disk - dat, err := os.ReadFile(gcrPath) - - if err != nil { - out.FailureT("Error reading {{.path}}: {{.error}}", out.V{"path": gcrPath, "error": err}) - } else { - gcrApplicationDefaultCredentials = string(dat) - } - } - - dockerRegistryAction := getNestedJsonString(configFileData, "enableDockerRegistry") - if dockerRegistryAction == "prompt" || dockerRegistryAction == "" { - enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) - if enableDR { - dockerServer = AskForStaticValue("-- Enter docker registry server url: ") - dockerUser = AskForStaticValue("-- Enter docker registry username: ") - dockerPass = AskForPasswordValue("-- Enter docker registry password: ") - } - } else if dockerRegistryAction == "enable" { - dockerServer = getNestedJsonString(configFileData, "dockerConfigs", "dockerServer") - dockerUser = getNestedJsonString(configFileData, "dockerConfigs", "dockerUser") - dockerPass = getNestedJsonString(configFileData, "dockerConfigs", "dockerPass") - } else if dockerRegistryAction == "disable" { - out.Ln("Ignoring Docker Registry configs") - } else { - out.Ln("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", dockerRegistryAction) - } - - acrAction := getNestedJsonString(configFileData, "enableACR") - if acrAction == "prompt" || acrAction == "" { - enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) - if enableACR { - acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") - acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") - acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") - } - } else if configFileData == nil || acrAction == "enable" { - out.Ln("Loading ACR configs from: ", AddonConfigFile) - acrURL = getNestedJsonString(configFileData, "acrConfigs", "acrURL") - acrClientID = getNestedJsonString(configFileData, "acrConfigs", "acrClientID") - acrPassword = getNestedJsonString(configFileData, "acrConfigs", "acrPassword") - } else if acrAction == "disable" { - out.Ln("Ignoring ACR configs") - } else { - out.Stringf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", configFileData["enableACR"]) - } - - namespace := "kube-system" - - // Create ECR Secret - err := service.CreateSecret( - profile, - namespace, - "registry-creds-ecr", - map[string]string{ - "AWS_ACCESS_KEY_ID": awsAccessID, - "AWS_SECRET_ACCESS_KEY": awsAccessKey, - "AWS_SESSION_TOKEN": awsSessionToken, - "aws-account": awsAccount, - "aws-region": awsRegion, - "aws-assume-role": awsRole, - }, - map[string]string{ - "app": "registry-creds", - "cloud": "ecr", - "kubernetes.io/minikube-addons": "registry-creds", - }) - if err != nil { - out.FailureT("ERROR creating `registry-creds-ecr` secret: {{.error}}", out.V{"error": err}) - } - - // Create GCR Secret - err = service.CreateSecret( - profile, - namespace, - "registry-creds-gcr", - map[string]string{ - "application_default_credentials.json": gcrApplicationDefaultCredentials, - "gcrurl": gcrURL, - }, - map[string]string{ - "app": "registry-creds", - "cloud": "gcr", - "kubernetes.io/minikube-addons": "registry-creds", - }) - - if err != nil { - out.FailureT("ERROR creating `registry-creds-gcr` secret: {{.error}}", out.V{"error": err}) - } - - // Create Docker Secret - err = service.CreateSecret( - profile, - namespace, - "registry-creds-dpr", - map[string]string{ - "DOCKER_PRIVATE_REGISTRY_SERVER": dockerServer, - "DOCKER_PRIVATE_REGISTRY_USER": dockerUser, - "DOCKER_PRIVATE_REGISTRY_PASSWORD": dockerPass, - }, - map[string]string{ - "app": "registry-creds", - "cloud": "dpr", - "kubernetes.io/minikube-addons": "registry-creds", - }) - - if err != nil { - out.WarningT("ERROR creating `registry-creds-dpr` secret") - } - - // Create Azure Container Registry Secret - err = service.CreateSecret( - profile, - namespace, - "registry-creds-acr", - map[string]string{ - "ACR_URL": acrURL, - "ACR_CLIENT_ID": acrClientID, - "ACR_PASSWORD": acrPassword, - }, - map[string]string{ - "app": "registry-creds", - "cloud": "acr", - "kubernetes.io/minikube-addons": "registry-creds", - }) - + err := processRegistryCredsConfig(profile, configFileData) if err != nil { out.WarningT("ERROR creating `registry-creds-acr` secret") } @@ -441,3 +249,198 @@ func getNestedJsonString(configMap map[string]any, keypath ...string) string { } return "" } + +func processRegistryCredsConfig(profile string, configFileData map[string]any) (err error) { + // Default values + awsAccessID := "changeme" + awsAccessKey := "changeme" + awsSessionToken := "" + awsRegion := "changeme" + awsAccount := "changeme" + awsRole := "changeme" + gcrApplicationDefaultCredentials := "changeme" + dockerServer := "changeme" + dockerUser := "changeme" + dockerPass := "changeme" + gcrURL := "https://gcr.io" + acrURL := "changeme" + acrClientID := "changeme" + acrPassword := "changeme" + + awsEcrAction := getNestedJsonString(configFileData, "enableAWSEcr") + if awsEcrAction == "prompt" || awsEcrAction == "" { + enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) + if enableAWSECR { + awsAccessID = AskForStaticValue("-- Enter AWS Access Key ID: ") + awsAccessKey = AskForStaticValue("-- Enter AWS Secret Access Key: ") + awsSessionToken = AskForStaticValueOptional("-- (Optional) Enter AWS Session Token: ") + awsRegion = AskForStaticValue("-- Enter AWS Region: ") + awsAccount = AskForStaticValue("-- Enter 12 digit AWS Account ID (Comma separated list): ") + awsRole = AskForStaticValueOptional("-- (Optional) Enter ARN of AWS role to assume: ") + } + } else if awsEcrAction == "enable" { + out.Ln("Loading AWS ECR configs from: %s", AddonConfigFile) + // Then read the configs + awsAccessID = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessID") + awsAccessKey = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessKey") + awsSessionToken = getNestedJsonString(configFileData, "awsEcrConfigs", "awsSessionToken") + awsRegion = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRegion") + awsAccount = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccount") + awsRole = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRole") + } else if awsEcrAction == "disable" { + out.Ln("Ignoring AWS ECR configs") + } else { + out.Ln("Disabling AWS ECR. Invalid value for enableAWSEcr (%s). Must be one of 'disable', 'enable' or 'prompt'", awsEcrAction) + } + + gcrPath := "" + gcrAction := getNestedJsonString(configFileData, "enableGCR") + if gcrAction == "prompt" || gcrAction == "" { + enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) + if enableGCR { + gcrPath = AskForStaticValue("-- Enter path to credentials (e.g. /home/user/.config/gcloud/application_default_credentials.json):") + gcrchangeURL := AskForYesNoConfirmation("-- Do you want to change the GCR URL (Default https://gcr.io)?", posResponses, negResponses) + + if gcrchangeURL { + gcrURL = AskForStaticValue("-- Enter GCR URL (e.g. https://asia.gcr.io):") + } + } + } else if gcrAction == "enable" { + out.Ln("Loading GCR configs from: ", AddonConfigFile) + // Then read the configs + gcrPath = getNestedJsonString(configFileData, "gcrConfigs", "gcrPath") + gcrURL = getNestedJsonString(configFileData, "gcrConfigs", "gcrURL") + } else if gcrAction == "disable" { + out.Ln("Ignoring GCR configs") + } else { + out.Ln("Disabling GCR. Invalid value for enableGCR (%s). Must be one of 'disable', 'enable' or 'prompt'", gcrAction) + } + + if gcrPath != "" { + // Read file from disk + dat, err := os.ReadFile(gcrPath) + + if err != nil { + out.FailureT("Error reading {{.path}}: {{.error}}", out.V{"path": gcrPath, "error": err}) + } else { + gcrApplicationDefaultCredentials = string(dat) + } + } + + dockerRegistryAction := getNestedJsonString(configFileData, "enableDockerRegistry") + if dockerRegistryAction == "prompt" || dockerRegistryAction == "" { + enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) + if enableDR { + dockerServer = AskForStaticValue("-- Enter docker registry server url: ") + dockerUser = AskForStaticValue("-- Enter docker registry username: ") + dockerPass = AskForPasswordValue("-- Enter docker registry password: ") + } + } else if dockerRegistryAction == "enable" { + dockerServer = getNestedJsonString(configFileData, "dockerConfigs", "dockerServer") + dockerUser = getNestedJsonString(configFileData, "dockerConfigs", "dockerUser") + dockerPass = getNestedJsonString(configFileData, "dockerConfigs", "dockerPass") + } else if dockerRegistryAction == "disable" { + out.Ln("Ignoring Docker Registry configs") + } else { + out.Ln("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", dockerRegistryAction) + } + + acrAction := getNestedJsonString(configFileData, "enableACR") + if acrAction == "prompt" || acrAction == "" { + enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) + if enableACR { + acrURL = AskForStaticValue("-- Enter Azure Container Registry (ACR) URL: ") + acrClientID = AskForStaticValue("-- Enter client ID (service principal ID) to access ACR: ") + acrPassword = AskForPasswordValue("-- Enter service principal password to access Azure Container Registry: ") + } + } else if configFileData == nil || acrAction == "enable" { + out.Ln("Loading ACR configs from: ", AddonConfigFile) + acrURL = getNestedJsonString(configFileData, "acrConfigs", "acrURL") + acrClientID = getNestedJsonString(configFileData, "acrConfigs", "acrClientID") + acrPassword = getNestedJsonString(configFileData, "acrConfigs", "acrPassword") + } else if acrAction == "disable" { + out.Ln("Ignoring ACR configs") + } else { + out.Stringf("Disabling ACR. Invalid value for enableACR (%s). Must be one of 'disable', 'enable' or 'prompt'", configFileData["enableACR"]) + } + + namespace := "kube-system" + + // Create ECR Secret + err = service.CreateSecret( + profile, + namespace, + "registry-creds-ecr", + map[string]string{ + "AWS_ACCESS_KEY_ID": awsAccessID, + "AWS_SECRET_ACCESS_KEY": awsAccessKey, + "AWS_SESSION_TOKEN": awsSessionToken, + "aws-account": awsAccount, + "aws-region": awsRegion, + "aws-assume-role": awsRole, + }, + map[string]string{ + "app": "registry-creds", + "cloud": "ecr", + "kubernetes.io/minikube-addons": "registry-creds", + }) + if err != nil { + out.FailureT("ERROR creating `registry-creds-ecr` secret: {{.error}}", out.V{"error": err}) + } + + // Create GCR Secret + err = service.CreateSecret( + profile, + namespace, + "registry-creds-gcr", + map[string]string{ + "application_default_credentials.json": gcrApplicationDefaultCredentials, + "gcrurl": gcrURL, + }, + map[string]string{ + "app": "registry-creds", + "cloud": "gcr", + "kubernetes.io/minikube-addons": "registry-creds", + }) + + if err != nil { + out.FailureT("ERROR creating `registry-creds-gcr` secret: {{.error}}", out.V{"error": err}) + } + + // Create Docker Secret + err = service.CreateSecret( + profile, + namespace, + "registry-creds-dpr", + map[string]string{ + "DOCKER_PRIVATE_REGISTRY_SERVER": dockerServer, + "DOCKER_PRIVATE_REGISTRY_USER": dockerUser, + "DOCKER_PRIVATE_REGISTRY_PASSWORD": dockerPass, + }, + map[string]string{ + "app": "registry-creds", + "cloud": "dpr", + "kubernetes.io/minikube-addons": "registry-creds", + }) + + if err != nil { + out.WarningT("ERROR creating `registry-creds-dpr` secret") + } + + // Create Azure Container Registry Secret + err = service.CreateSecret( + profile, + namespace, + "registry-creds-acr", + map[string]string{ + "ACR_URL": acrURL, + "ACR_CLIENT_ID": acrClientID, + "ACR_PASSWORD": acrPassword, + }, + map[string]string{ + "app": "registry-creds", + "cloud": "acr", + "kubernetes.io/minikube-addons": "registry-creds", + }) + return +} From 73f32bec8515a09bfd804960dbff190c9a6de308 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 30 Dec 2024 14:50:05 -0800 Subject: [PATCH 06/19] Moving addon specific configuration to its own processAddon function. Allow multiple addons in a single config file. --- cmd/minikube/cmd/config/configure.go | 273 +++++++++++++++------------ 1 file changed, 154 insertions(+), 119 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 3ddd63023984..ee45dab3092b 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -58,9 +58,10 @@ var addonsConfigureCmd = &cobra.Command{ profile := ClusterFlagValue() addon := args[0] - configFileData := make(map[string]any) + var addonConfig map[string]any if AddonConfigFile != "" { + configFileData := make(map[string]any) out.Ln("Reading %s configs from %s", addon, AddonConfigFile) if confData, err := os.ReadFile(AddonConfigFile); err != nil && errors.Is(err, os.ErrNotExist) { exit.Message(reason.Usage, "config file does not exist") @@ -71,112 +72,32 @@ var addonsConfigureCmd = &cobra.Command{ exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, fmt.Sprintf("error opening config file: %v", err)) } + + // Make sure the addon specific config exists and it is a map + if addonSpecificConfig, ok := configFileData[addon]; ok && addonSpecificConfig != nil { + if casted, ok := addonSpecificConfig.(map[string]any); casted != nil && ok { + addonConfig = casted + } + } } // allows for additional prompting of information when enabling addons switch addon { case "registry-creds": - err := processRegistryCredsConfig(profile, configFileData) - if err != nil { - out.WarningT("ERROR creating `registry-creds-acr` secret") - } + processRegistryCredsConfig(profile, addonConfig) case "metallb": - _, cfg := mustload.Partial(profile) - - validator := func(s string) bool { - return net.ParseIP(s) != nil - } - - cfg.KubernetesConfig.LoadBalancerStartIP = AskForStaticValidatedValue("-- Enter Load Balancer Start IP: ", validator) - - cfg.KubernetesConfig.LoadBalancerEndIP = AskForStaticValidatedValue("-- Enter Load Balancer End IP: ", validator) - - if err := config.SaveProfile(profile, cfg); err != nil { - out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) - } + processMetalLBConfig(profile, addonConfig) - // Re-enable metallb addon in order to generate template manifest files with Load Balancer Start/End IP - if err := addons.EnableOrDisableAddon(cfg, "metallb", "true"); err != nil { - out.ErrT(style.Fatal, "Failed to configure metallb IP {{.profile}}", out.V{"profile": profile}) - } case "ingress": - _, cfg := mustload.Partial(profile) - - validator := func(s string) bool { - format := regexp.MustCompile("^.+/.+$") - return format.MatchString(s) - } - - customCert := AskForStaticValidatedValue("-- Enter custom cert (format is \"namespace/secret\"): ", validator) - if cfg.KubernetesConfig.CustomIngressCert != "" { - overwrite := AskForYesNoConfirmation("A custom cert for ingress has already been set. Do you want overwrite it?", posResponses, negResponses) - if !overwrite { - break - } - } - - cfg.KubernetesConfig.CustomIngressCert = customCert + processIngressConfig(profile, addonConfig) - if err := config.SaveProfile(profile, cfg); err != nil { - out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) - } case "registry-aliases": - _, cfg := mustload.Partial(profile) - validator := func(s string) bool { - format := regexp.MustCompile(`^([a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)+(\ [a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)*$`) - return format.MatchString(s) - } - registryAliases := AskForStaticValidatedValue("-- Enter registry aliases separated by space: ", validator) - cfg.KubernetesConfig.RegistryAliases = registryAliases + processRegistryAliasesConfig(profile, addonConfig) - if err := config.SaveProfile(profile, cfg); err != nil { - out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) - } - addon := assets.Addons["registry-aliases"] - if addon.IsEnabled(cfg) { - // Re-enable registry-aliases addon in order to generate template manifest files with custom hosts - if err := addons.EnableOrDisableAddon(cfg, "registry-aliases", "true"); err != nil { - out.ErrT(style.Fatal, "Failed to configure registry-aliases {{.profile}}", out.V{"profile": profile}) - } - } case "auto-pause": - lapi, cfg := mustload.Partial(profile) - intervalInput := AskForStaticValue("-- Enter interval time of auto-pause-interval (ex. 1m0s): ") - intervalTime, err := time.ParseDuration(intervalInput) - if err != nil { - out.ErrT(style.Fatal, "Interval is an invalid duration: {{.error}}", out.V{"error": err}) - } - if intervalTime != intervalTime.Abs() || intervalTime.String() == "0s" { - out.ErrT(style.Fatal, "Interval must be greater than 0s") - } - cfg.AutoPauseInterval = intervalTime - if err := config.SaveProfile(profile, cfg); err != nil { - out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) - } - addon := assets.Addons["auto-pause"] - if addon.IsEnabled(cfg) { + processAutoPauseConfig(profile, addonConfig) - // see #17945: restart auto-pause service - p, err := config.LoadProfile(profile) - if err != nil { - out.ErrT(style.Fatal, "failed to load profile: {{.error}}", out.V{"error": err}) - } - if profileStatus(p, lapi).StatusCode/100 == 2 { // 2xx code - co := mustload.Running(profile) - // first unpause all nodes cluster immediately - unpauseWholeCluster(co) - // Re-enable auto-pause addon in order to update interval time - if err := addons.EnableOrDisableAddon(cfg, "auto-pause", "true"); err != nil { - out.ErrT(style.Fatal, "Failed to configure auto-pause {{.profile}}", out.V{"profile": profile}) - } - // restart auto-pause service - if err := sysinit.New(co.CP.Runner).Restart("auto-pause"); err != nil { - out.ErrT(style.Fatal, "failed to restart auto-pause: {{.error}}", out.V{"error": err}) - } - - } - } default: out.FailureT("{{.name}} has no available configuration options", out.V{"name": addon}) return @@ -225,19 +146,19 @@ func init() { AddonsCmd.AddCommand(addonsConfigureCmd) } -func getNestedJsonString(configMap map[string]any, keypath ...string) string { +func getNestedJSONString(configMap map[string]any, keypath ...string) string { for idx, key := range keypath { next, ok := configMap[key] if !ok || next == nil { break } if idx == len(keypath)-1 { - if strval, ok := next.(string); ok { + strval, ok := next.(string) + + if ok { return strval - } else { - out.Ln("Expected string at last key, found: ", reflect.TypeOf(next), next) - break } + out.Ln("Expected string at last key, found: ", reflect.TypeOf(next), next) } else { if mapval, ok := next.(map[string]any); ok && mapval != nil { configMap = mapval @@ -250,7 +171,119 @@ func getNestedJsonString(configMap map[string]any, keypath ...string) string { return "" } -func processRegistryCredsConfig(profile string, configFileData map[string]any) (err error) { +// Processes metallb addon config from configFile if it exists otherwise resorts to default behavior +func processMetalLBConfig(profile string, _ map[string]any) { + _, cfg := mustload.Partial(profile) + + validator := func(s string) bool { + return net.ParseIP(s) != nil + } + + cfg.KubernetesConfig.LoadBalancerStartIP = AskForStaticValidatedValue("-- Enter Load Balancer Start IP: ", validator) + + cfg.KubernetesConfig.LoadBalancerEndIP = AskForStaticValidatedValue("-- Enter Load Balancer End IP: ", validator) + + if err := config.SaveProfile(profile, cfg); err != nil { + out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) + } + + // Re-enable metallb addon in order to generate template manifest files with Load Balancer Start/End IP + if err := addons.EnableOrDisableAddon(cfg, "metallb", "true"); err != nil { + out.ErrT(style.Fatal, "Failed to configure metallb IP {{.profile}}", out.V{"profile": profile}) + } +} + +// Processes ingress addon config from configFile if it exists otherwise resorts to default behavior +func processIngressConfig(profile string, _ map[string]any) { + _, cfg := mustload.Partial(profile) + + validator := func(s string) bool { + format := regexp.MustCompile("^.+/.+$") + return format.MatchString(s) + } + + customCert := AskForStaticValidatedValue("-- Enter custom cert (format is \"namespace/secret\"): ", validator) + if cfg.KubernetesConfig.CustomIngressCert != "" { + overwrite := AskForYesNoConfirmation("A custom cert for ingress has already been set. Do you want overwrite it?", posResponses, negResponses) + if !overwrite { + return + } + } + + cfg.KubernetesConfig.CustomIngressCert = customCert + + if err := config.SaveProfile(profile, cfg); err != nil { + out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) + } +} + +// Processes auto-pause addon config from configFile if it exists otherwise resorts to default behavior +func processAutoPauseConfig(profile string, _ map[string]any) { + lapi, cfg := mustload.Partial(profile) + intervalInput := AskForStaticValue("-- Enter interval time of auto-pause-interval (ex. 1m0s): ") + intervalTime, err := time.ParseDuration(intervalInput) + if err != nil { + out.ErrT(style.Fatal, "Interval is an invalid duration: {{.error}}", out.V{"error": err}) + } + + if intervalTime != intervalTime.Abs() || intervalTime.String() == "0s" { + out.ErrT(style.Fatal, "Interval must be greater than 0s") + } + + cfg.AutoPauseInterval = intervalTime + if err = config.SaveProfile(profile, cfg); err != nil { + out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) + } + + addon := assets.Addons["auto-pause"] + if addon.IsEnabled(cfg) { + + // see #17945: restart auto-pause service + p, err := config.LoadProfile(profile) + if err != nil { + out.ErrT(style.Fatal, "failed to load profile: {{.error}}", out.V{"error": err}) + } + if profileStatus(p, lapi).StatusCode/100 == 2 { // 2xx code + co := mustload.Running(profile) + // first unpause all nodes cluster immediately + unpauseWholeCluster(co) + // Re-enable auto-pause addon in order to update interval time + if err := addons.EnableOrDisableAddon(cfg, "auto-pause", "true"); err != nil { + out.ErrT(style.Fatal, "Failed to configure auto-pause {{.profile}}", out.V{"profile": profile}) + } + // restart auto-pause service + if err := sysinit.New(co.CP.Runner).Restart("auto-pause"); err != nil { + out.ErrT(style.Fatal, "failed to restart auto-pause: {{.error}}", out.V{"error": err}) + } + } + } +} + +// Processes registry-aliases addon config from configFile if it exists otherwise resorts to default behavior +func processRegistryAliasesConfig(profile string, _ map[string]any) { + _, cfg := mustload.Partial(profile) + validator := func(s string) bool { + format := regexp.MustCompile(`^([a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)+(\ [a-zA-Z0-9-_]+\.[a-zA-Z0-9-_]+)*$`) + return format.MatchString(s) + } + registryAliases := AskForStaticValidatedValue("-- Enter registry aliases separated by space: ", validator) + cfg.KubernetesConfig.RegistryAliases = registryAliases + + if err := config.SaveProfile(profile, cfg); err != nil { + out.ErrT(style.Fatal, "Failed to save config {{.profile}}", out.V{"profile": profile}) + } + + addon := assets.Addons["registry-aliases"] + if addon.IsEnabled(cfg) { + // Re-enable registry-aliases addon in order to generate template manifest files with custom hosts + if err := addons.EnableOrDisableAddon(cfg, "registry-aliases", "true"); err != nil { + out.ErrT(style.Fatal, "Failed to configure registry-aliases {{.profile}}", out.V{"profile": profile}) + } + } +} + +// Processes registry-creds addon config from configFile if it exists otherwise resorts to default behavior +func processRegistryCredsConfig(profile string, configFileData map[string]any) { // Default values awsAccessID := "changeme" awsAccessKey := "changeme" @@ -267,7 +300,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( acrClientID := "changeme" acrPassword := "changeme" - awsEcrAction := getNestedJsonString(configFileData, "enableAWSEcr") + awsEcrAction := getNestedJSONString(configFileData, "enableAWSEcr") if awsEcrAction == "prompt" || awsEcrAction == "" { enableAWSECR := AskForYesNoConfirmation("\nDo you want to enable AWS Elastic Container Registry?", posResponses, negResponses) if enableAWSECR { @@ -281,12 +314,12 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( } else if awsEcrAction == "enable" { out.Ln("Loading AWS ECR configs from: %s", AddonConfigFile) // Then read the configs - awsAccessID = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessID") - awsAccessKey = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccessKey") - awsSessionToken = getNestedJsonString(configFileData, "awsEcrConfigs", "awsSessionToken") - awsRegion = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRegion") - awsAccount = getNestedJsonString(configFileData, "awsEcrConfigs", "awsAccount") - awsRole = getNestedJsonString(configFileData, "awsEcrConfigs", "awsRole") + awsAccessID = getNestedJSONString(configFileData, "awsEcrConfigs", "awsAccessID") + awsAccessKey = getNestedJSONString(configFileData, "awsEcrConfigs", "awsAccessKey") + awsSessionToken = getNestedJSONString(configFileData, "awsEcrConfigs", "awsSessionToken") + awsRegion = getNestedJSONString(configFileData, "awsEcrConfigs", "awsRegion") + awsAccount = getNestedJSONString(configFileData, "awsEcrConfigs", "awsAccount") + awsRole = getNestedJSONString(configFileData, "awsEcrConfigs", "awsRole") } else if awsEcrAction == "disable" { out.Ln("Ignoring AWS ECR configs") } else { @@ -294,7 +327,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( } gcrPath := "" - gcrAction := getNestedJsonString(configFileData, "enableGCR") + gcrAction := getNestedJSONString(configFileData, "enableGCR") if gcrAction == "prompt" || gcrAction == "" { enableGCR := AskForYesNoConfirmation("\nDo you want to enable Google Container Registry?", posResponses, negResponses) if enableGCR { @@ -308,8 +341,8 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( } else if gcrAction == "enable" { out.Ln("Loading GCR configs from: ", AddonConfigFile) // Then read the configs - gcrPath = getNestedJsonString(configFileData, "gcrConfigs", "gcrPath") - gcrURL = getNestedJsonString(configFileData, "gcrConfigs", "gcrURL") + gcrPath = getNestedJSONString(configFileData, "gcrConfigs", "gcrPath") + gcrURL = getNestedJSONString(configFileData, "gcrConfigs", "gcrURL") } else if gcrAction == "disable" { out.Ln("Ignoring GCR configs") } else { @@ -327,7 +360,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( } } - dockerRegistryAction := getNestedJsonString(configFileData, "enableDockerRegistry") + dockerRegistryAction := getNestedJSONString(configFileData, "enableDockerRegistry") if dockerRegistryAction == "prompt" || dockerRegistryAction == "" { enableDR := AskForYesNoConfirmation("\nDo you want to enable Docker Registry?", posResponses, negResponses) if enableDR { @@ -336,16 +369,16 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( dockerPass = AskForPasswordValue("-- Enter docker registry password: ") } } else if dockerRegistryAction == "enable" { - dockerServer = getNestedJsonString(configFileData, "dockerConfigs", "dockerServer") - dockerUser = getNestedJsonString(configFileData, "dockerConfigs", "dockerUser") - dockerPass = getNestedJsonString(configFileData, "dockerConfigs", "dockerPass") + dockerServer = getNestedJSONString(configFileData, "dockerConfigs", "dockerServer") + dockerUser = getNestedJSONString(configFileData, "dockerConfigs", "dockerUser") + dockerPass = getNestedJSONString(configFileData, "dockerConfigs", "dockerPass") } else if dockerRegistryAction == "disable" { out.Ln("Ignoring Docker Registry configs") } else { out.Ln("Disabling Docker Registry. Invalid value for enableDockerRegistry (%s). Must be one of 'disable', 'enable' or 'prompt'", dockerRegistryAction) } - acrAction := getNestedJsonString(configFileData, "enableACR") + acrAction := getNestedJSONString(configFileData, "enableACR") if acrAction == "prompt" || acrAction == "" { enableACR := AskForYesNoConfirmation("\nDo you want to enable Azure Container Registry?", posResponses, negResponses) if enableACR { @@ -355,9 +388,9 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( } } else if configFileData == nil || acrAction == "enable" { out.Ln("Loading ACR configs from: ", AddonConfigFile) - acrURL = getNestedJsonString(configFileData, "acrConfigs", "acrURL") - acrClientID = getNestedJsonString(configFileData, "acrConfigs", "acrClientID") - acrPassword = getNestedJsonString(configFileData, "acrConfigs", "acrPassword") + acrURL = getNestedJSONString(configFileData, "acrConfigs", "acrURL") + acrClientID = getNestedJSONString(configFileData, "acrConfigs", "acrClientID") + acrPassword = getNestedJSONString(configFileData, "acrConfigs", "acrPassword") } else if acrAction == "disable" { out.Ln("Ignoring ACR configs") } else { @@ -367,7 +400,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( namespace := "kube-system" // Create ECR Secret - err = service.CreateSecret( + err := service.CreateSecret( profile, namespace, "registry-creds-ecr", @@ -442,5 +475,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) ( "cloud": "acr", "kubernetes.io/minikube-addons": "registry-creds", }) - return + if err != nil { + out.WarningT("ERROR creating `registry-creds-acr` secret") + } } From 87fa92b4694b4488855a893fd50859db94f63ae7 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 30 Dec 2024 14:51:42 -0800 Subject: [PATCH 07/19] using -f for addon config file flag instead of -c. --- cmd/minikube/cmd/config/configure.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index ee45dab3092b..749c7c17e3d0 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -142,7 +142,7 @@ func unpauseWholeCluster(co mustload.ClusterController) { } func init() { - addonsConfigureCmd.Flags().StringVarP(&AddonConfigFile, "config-file", "c", "", "An optional configuration file to read addon specific configs from instead of being prompted each time.") + addonsConfigureCmd.Flags().StringVarP(&AddonConfigFile, "config-file", "f", "", "An optional configuration file to read addon specific configs from instead of being prompted each time.") AddonsCmd.AddCommand(addonsConfigureCmd) } From bea313a041189d17344a1358bc168827b67cd641 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Tue, 31 Dec 2024 11:25:46 -0800 Subject: [PATCH 08/19] Moving config file loading to its own method. --- cmd/minikube/cmd/config/configure.go | 51 +++++++++++++++------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 749c7c17e3d0..87112c9ad3d2 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -57,29 +57,7 @@ var addonsConfigureCmd = &cobra.Command{ profile := ClusterFlagValue() addon := args[0] - - var addonConfig map[string]any - - if AddonConfigFile != "" { - configFileData := make(map[string]any) - out.Ln("Reading %s configs from %s", addon, AddonConfigFile) - if confData, err := os.ReadFile(AddonConfigFile); err != nil && errors.Is(err, os.ErrNotExist) { - exit.Message(reason.Usage, "config file does not exist") - } else if err != nil { - exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, - fmt.Sprintf("error opening config file: %v", err)) - } else if err = json.Unmarshal(confData, &configFileData); err != nil { - exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, - fmt.Sprintf("error opening config file: %v", err)) - } - - // Make sure the addon specific config exists and it is a map - if addonSpecificConfig, ok := configFileData[addon]; ok && addonSpecificConfig != nil { - if casted, ok := addonSpecificConfig.(map[string]any); casted != nil && ok { - addonConfig = casted - } - } - } + addonConfig := loadAddonConfigFile(addon, AddonConfigFile) // allows for additional prompting of information when enabling addons switch addon { @@ -146,6 +124,33 @@ func init() { AddonsCmd.AddCommand(addonsConfigureCmd) } +// Helper method to load a config file for addons +func loadAddonConfigFile(addon, configFilePath string) (addonConfig map[string]any) { + if configFilePath != "" { + configFileData := make(map[string]any) + out.Ln("Reading %s configs from %s", addon, configFilePath) + if confData, err := os.ReadFile(configFilePath); err != nil && errors.Is(err, os.ErrNotExist) { + exit.Message(reason.Usage, "config file does not exist") + } else if err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } else if err = json.Unmarshal(confData, &configFileData); err != nil { + exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, + fmt.Sprintf("error opening config file: %v", err)) + } + + // Make sure the addon specific config exists and it is a map + if addonSpecificConfig, ok := configFileData[addon]; ok && addonSpecificConfig != nil { + if casted, ok := addonSpecificConfig.(map[string]any); casted != nil && ok { + addonConfig = casted + } + } + } + return +} + +// Given a map, returns the (string) value of a key in a given path, equivalent of a["x]["y"]["z"]. +// In case of errors or type mismatches (eg missing key paths or invalid types) an empty string is returned. func getNestedJSONString(configMap map[string]any, keypath ...string) string { for idx, key := range keypath { next, ok := configMap[key] From 827713885040cd7b33441d984b8862b22f6e71c9 Mon Sep 17 00:00:00 2001 From: Hello World Date: Tue, 7 Jan 2025 00:28:37 +0800 Subject: [PATCH 09/19] fix(install): fix minikube-linux-amd64 download URL error (#20198) the linux amd64 download url error --- site/content/en/docs/start/_index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/content/en/docs/start/_index.md b/site/content/en/docs/start/_index.md index c4336d5e5d18..be553ecbe547 100644 --- a/site/content/en/docs/start/_index.md +++ b/site/content/en/docs/start/_index.md @@ -171,7 +171,7 @@ Click on the buttons that describe your target platform. For other architectures {{% quiz_instruction id="/Linux/x86-64/Stable/Binary download" %}} ```shell -curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64/ +curl -LO https://github.com/kubernetes/minikube/releases/latest/download/minikube-linux-amd64 sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64 ``` {{% /quiz_instruction %}} From 44386b1ff923ead4e1feba5b2feb756948e07d5a Mon Sep 17 00:00:00 2001 From: minikube-bot Date: Mon, 6 Jan 2025 10:11:06 -0800 Subject: [PATCH 10/19] Update yearly leaderboard (#20193) --- .../en/docs/contrib/leaderboard/2024.html | 94 +++++++++---------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/site/content/en/docs/contrib/leaderboard/2024.html b/site/content/en/docs/contrib/leaderboard/2024.html index 45740d1a3416..f65c9fb8bb49 100644 --- a/site/content/en/docs/contrib/leaderboard/2024.html +++ b/site/content/en/docs/contrib/leaderboard/2024.html @@ -87,7 +87,7 @@

kubernetes/minikube

-
2024-01-01 — 2024-11-30
+
2024-01-01 — 2024-12-31

Reviewers

@@ -103,21 +103,21 @@

Most Influential

function drawreviewCounts() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of Merged PRs reviewed', type: 'number'}, { role: 'annotation' }], - ["medyagh", 46, "46"], - ["spowelljr", 28, "28"], + ["medyagh", 50, "50"], + ["spowelljr", 29, "29"], ["afbjorklund", 4, "4"], ["liangyuanpeng", 3, "3"], ["ComradeProgrammer", 2, "2"], ["nirs", 2, "2"], ["prezha", 2, "2"], - ["Shubham82", 1, "1"], + ["allenhaozi", 1, "1"], ["llegolas", 1, "1"], + ["Shubham82", 1, "1"], ["Zhongyi-Lu", 1, "1"], - ["allenhaozi", 1, "1"], - ["Fenrur", 1, "1"], - ["bobsira", 1, "1"], + ["Dmarcotrigiano", 1, "1"], ["uos-ljtian", 1, "1"], ["eiffel-fl", 1, "1"], + ["bobsira", 1, "1"], ]); @@ -150,8 +150,8 @@

Most Helpful

function drawreviewWords() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of words written in merged PRs', type: 'number'}, { role: 'annotation' }], - ["spowelljr", 2863, "2863"], - ["medyagh", 1408, "1408"], + ["spowelljr", 2900, "2900"], + ["medyagh", 1428, "1428"], ["Dmarcotrigiano", 276, "276"], ["nirs", 252, "252"], ["ComradeProgrammer", 246, "246"], @@ -163,8 +163,8 @@

Most Helpful

["uos-ljtian", 21, "21"], ["Shubham82", 17, "17"], ["eiffel-fl", 15, "15"], - ["bobsira", 12, "12"], ["aojea", 12, "12"], + ["bobsira", 12, "12"], ]); @@ -197,21 +197,21 @@

Most Demanding

function drawreviewComments() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of Review Comments in merged PRs', type: 'number'}, { role: 'annotation' }], - ["spowelljr", 55, "55"], + ["spowelljr", 57, "57"], ["medyagh", 38, "38"], ["liangyuanpeng", 5, "5"], ["ComradeProgrammer", 2, "2"], - ["eiffel-fl", 1, "1"], ["aojea", 1, "1"], - ["Zhongyi-Lu", 0, "0"], + ["eiffel-fl", 1, "1"], + ["afbjorklund", 0, "0"], + ["bobsira", 0, "0"], ["Dmarcotrigiano", 0, "0"], - ["allenhaozi", 0, "0"], ["Shubham82", 0, "0"], - ["bobsira", 0, "0"], - ["llegolas", 0, "0"], - ["Fenrur", 0, "0"], - ["prezha", 0, "0"], + ["nirs", 0, "0"], ["uos-ljtian", 0, "0"], + ["Zhongyi-Lu", 0, "0"], + ["Fenrur", 0, "0"], + ["allenhaozi", 0, "0"], ]); @@ -249,20 +249,20 @@

Most Active

var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of Pull Requests Merged', type: 'number'}, { role: 'annotation' }], ["spowelljr", 116, "116"], - ["prezha", 14, "14"], - ["medyagh", 13, "13"], - ["ComradeProgrammer", 11, "11"], - ["jeffmaury", 8, "8"], + ["prezha", 18, "18"], + ["medyagh", 16, "16"], + ["ComradeProgrammer", 14, "14"], + ["uos-ljtian", 10, "10"], + ["jeffmaury", 9, "9"], ["joaquimrocha", 8, "8"], ["afbjorklund", 8, "8"], - ["uos-ljtian", 7, "7"], ["xcarolan", 6, "6"], ["nirs", 5, "5"], - ["syxunion", 4, "4"], ["zdxgs", 4, "4"], + ["syxunion", 4, "4"], ["sandipanpanda", 3, "3"], - ["thomasjm", 2, "2"], - ["radeksm", 2, "2"], + ["travier", 2, "2"], + ["Razorr1996", 2, "2"], ]); @@ -295,12 +295,12 @@

Big Movers

function drawprDeltas() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: 'Lines of code (delta)', type: 'number'}, { role: 'annotation' }], - ["ComradeProgrammer", 20842, "20842"], + ["ComradeProgrammer", 21000, "21000"], ["spowelljr", 6461, "6461"], - ["prezha", 4191, "4191"], + ["prezha", 4597, "4597"], ["fbyrne", 864, "864"], ["afbjorklund", 809, "809"], - ["medyagh", 680, "680"], + ["medyagh", 746, "746"], ["travier", 586, "586"], ["hritesh04", 496, "496"], ["tylerauerbeck", 309, "309"], @@ -342,9 +342,9 @@

Most difficult to review

function drawprSize() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: 'Average PR size (added+changed)', type: 'number'}, { role: 'annotation' }], - ["ComradeProgrammer", 1379, "1379"], + ["ComradeProgrammer", 1093, "1093"], ["fbyrne", 355, "355"], - ["prezha", 207, "207"], + ["prezha", 175, "175"], ["hritesh04", 162, "162"], ["travier", 123, "123"], ["afbjorklund", 95, "95"], @@ -352,8 +352,8 @@

Most difficult to review

["sandipanpanda", 50, "50"], ["mqasimsarfraz", 43, "43"], ["Sryther", 42, "42"], - ["gpelouze", 35, "35"], ["spowelljr", 35, "35"], + ["gpelouze", 35, "35"], ["Skalador", 33, "33"], ["thomasjm", 32, "32"], ["IC1101Virgo", 25, "25"], @@ -393,21 +393,21 @@

Most Active

function drawcomments() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of comments', type: 'number'}, { role: 'annotation' }], - ["afbjorklund", 117, "117"], - ["T-Lakshmi", 106, "106"], - ["kundan2707", 83, "83"], - ["medyagh", 79, "79"], + ["T-Lakshmi", 128, "128"], + ["Ritikaa96", 123, "123"], + ["afbjorklund", 120, "120"], + ["kundan2707", 100, "100"], + ["medyagh", 81, "81"], ["spowelljr", 56, "56"], ["caerulescens", 49, "49"], - ["Ritikaa96", 31, "31"], - ["xcarolan", 16, "16"], ["AmarNathChary", 16, "16"], + ["xcarolan", 16, "16"], ["liangyuanpeng", 15, "15"], ["ComradeProgrammer", 10, "10"], ["prezha", 8, "8"], ["wassafshahzad", 6, "6"], - ["nirs", 6, "6"], ["logopk", 6, "6"], + ["nirs", 6, "6"], ]); @@ -440,21 +440,21 @@

Most Helpful

function drawcommentWords() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of words (excludes authored)', type: 'number'}, { role: 'annotation' }], - ["afbjorklund", 4720, "4720"], + ["afbjorklund", 4981, "4981"], ["kuanyui", 4510, "4510"], - ["medyagh", 4030, "4030"], + ["medyagh", 4129, "4129"], + ["Ritikaa96", 2504, "2504"], + ["T-Lakshmi", 2270, "2270"], ["spowelljr", 2232, "2232"], ["caerulescens", 2011, "2011"], - ["T-Lakshmi", 1826, "1826"], ["adrian-moisa", 1688, "1688"], ["karthick-dkk", 1285, "1285"], - ["kundan2707", 1160, "1160"], + ["kundan2707", 1261, "1261"], ["xcarolan", 1119, "1119"], + ["akahunahi", 933, "933"], ["prezha", 738, "738"], ["viplifes", 684, "684"], ["cirix", 632, "632"], - ["Ritikaa96", 600, "600"], - ["ComradeProgrammer", 568, "568"], ]); @@ -487,8 +487,8 @@

Top Closers

function drawissueCloser() { var data = new google.visualization.arrayToDataTable([ [{label:'',type:'string'},{label: '# of issues closed (excludes authored)', type: 'number'}, { role: 'annotation' }], - ["spowelljr", 90, "90"], - ["medyagh", 27, "27"], + ["spowelljr", 91, "91"], + ["medyagh", 30, "30"], ["afbjorklund", 5, "5"], ["prezha", 2, "2"], ["ComradeProgrammer", 1, "1"], From 187b70f5f058d1ade9f6f2756ebc398b867dc3ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=8C=A6=E5=8D=97=E8=B7=AF=E4=B9=8B=E8=8A=B1?= <46831212+ComradeProgrammer@users.noreply.github.com> Date: Mon, 6 Jan 2025 22:26:06 +0100 Subject: [PATCH 11/19] feat: allow publish and download kicbase image in github release (#19464) --- hack/jenkins/release_build_and_upload.sh | 18 ++++++++++- pkg/minikube/download/download.go | 3 +- pkg/minikube/download/image.go | 33 ++++++++++++++++++++ pkg/minikube/node/cache.go | 39 ++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 5 deletions(-) diff --git a/hack/jenkins/release_build_and_upload.sh b/hack/jenkins/release_build_and_upload.sh index e0a18a439b15..2314e10860dd 100755 --- a/hack/jenkins/release_build_and_upload.sh +++ b/hack/jenkins/release_build_and_upload.sh @@ -39,7 +39,8 @@ grep -E "^VERSION_BUILD \\?=" Makefile | grep "${VERSION_BUILD}" # Force go packages to the Jekins home directory export GOPATH=$HOME/go - +# Make sure docker is installed and configured +./hack/jenkins/installers/check_install_docker.sh # Verify ISO exists echo "Verifying ISO exists ..." make verify-iso @@ -111,5 +112,20 @@ fi #echo "Updating Docker images ..." #make push-gvisor-addon-image push-storage-provisioner-manifest +echo "Generating tarballs for kicbase images" +# first get the correct tag of the kic base image +KIC_VERSION=$(grep -E "Version =" pkg/drivers/kic/types.go | cut -d \" -f 2 | cut -d "-" -f 1) +# then generate tarballs for all achitectures +for ARCH in "amd64" "arm64" "arm/v7" "ppc64le" "s390x" +do + SUFFIX=$(echo $ARCH | sed 's/\///g') + IMAGE_NAME=kicbase/stable:${KIC_VERSION} + TARBALL_NAME=out/kicbase-${KIC_VERSION}-${SUFFIX}.tar + docker pull ${IMAGE_NAME} --platform linux/${ARCH} + docker image save ${IMAGE_NAME} -o ${TARBALL_NAME} + openssl sha256 "${TARBALL_NAME}" | awk '{print $2}' > "${TARBALL_NAME}.sha256" + docker rmi -f ${IMAGE_NAME} +done + echo "Updating latest bucket for ${VERSION} release ..." gsutil cp -r "gs://${BUCKET}/releases/${TAGNAME}/*" "gs://${BUCKET}/releases/latest/" diff --git a/pkg/minikube/download/download.go b/pkg/minikube/download/download.go index a4404cbf458e..27289bfedce4 100644 --- a/pkg/minikube/download/download.go +++ b/pkg/minikube/download/download.go @@ -65,7 +65,7 @@ func CreateDstDownloadMock(_, dst string) error { } // download is a well-configured atomic download function -func download(src, dst string) error { +func download(src, dst string, options ...getter.ClientOption) error { var clientOptions []getter.ClientOption if out.IsTerminal(os.Stdout) && !detect.GithubActionRunner() { progress := getter.WithProgress(DefaultProgressBar) @@ -76,6 +76,7 @@ func download(src, dst string) error { } else { clientOptions = []getter.ClientOption{} } + clientOptions = append(clientOptions, options...) tmpDst := dst + ".download" client := &getter.Client{ Src: src, diff --git a/pkg/minikube/download/image.go b/pkg/minikube/download/image.go index 9f54470bf940..a87071ea6a3f 100644 --- a/pkg/minikube/download/image.go +++ b/pkg/minikube/download/image.go @@ -32,6 +32,7 @@ import ( "github.com/google/go-containerregistry/pkg/v1/daemon" "github.com/google/go-containerregistry/pkg/v1/remote" "github.com/google/go-containerregistry/pkg/v1/tarball" + "github.com/hashicorp/go-getter" "github.com/pkg/errors" "k8s.io/klog/v2" "k8s.io/minikube/pkg/minikube/detect" @@ -39,6 +40,7 @@ import ( "k8s.io/minikube/pkg/minikube/localpath" "k8s.io/minikube/pkg/minikube/out" "k8s.io/minikube/pkg/minikube/out/register" + "k8s.io/minikube/pkg/version" ) var ( @@ -224,6 +226,37 @@ func ImageToCache(img string) error { } } +// GHImageTarballToCache try to download the tarball of kicbase from github release. +// This is the last resort, in case of all docker registry is not available. +func GHImageTarballToCache(img, imgVersion string) (string, error) { + f := imagePathInCache(img) + fileLock := f + ".lock" + + kicbaseArch := runtime.GOARCH + if kicbaseArch == "arm" { + kicbaseArch = "armv7" + } + + releaser, err := lockDownload(fileLock) + if err != nil { + return "", err + } + if releaser != nil { + defer releaser.Release() + } + downloadURL := fmt.Sprintf("https://github.com/kubernetes/minikube/releases/download/%s/%s-%s-%s.tar", + version.GetVersion(), + img, imgVersion, kicbaseArch) + + // we don't want the tarball to be decompressed + // so we pass client options to suppress this behavior + if err := download(downloadURL, f, getter.WithDecompressors(map[string]getter.Decompressor{})); err != nil { + return "", err + } + return downloadURL, nil + +} + func parseImage(img string) (*name.Tag, name.Reference, error) { var ref name.Reference diff --git a/pkg/minikube/node/cache.go b/pkg/minikube/node/cache.go index 6feffc855763..d158c36b771e 100644 --- a/pkg/minikube/node/cache.go +++ b/pkg/minikube/node/cache.go @@ -133,12 +133,13 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down if finalImg != "" { cc.KicBaseImage = finalImg if image.Tag(finalImg) != image.Tag(baseImg) { - out.WarningT(fmt.Sprintf("minikube was unable to download %s, but successfully downloaded %s as a fallback image", image.Tag(baseImg), image.Tag(finalImg))) + out.WarningT(fmt.Sprintf("minikube was unable to download %s, but successfully downloaded %s as a fallback image", image.Tag(baseImg), finalImg)) } } }() + // first we try to download the kicbase image (and fall back images) from docker registry + var err error for _, img := range append([]string{baseImg}, kic.FallbackImages...) { - var err error if driver.IsDocker(cc.Driver) && download.ImageExistsInDaemon(img) && !downloadOnly { klog.Infof("%s exists in daemon, skipping load", img) @@ -167,7 +168,39 @@ func beginDownloadKicBaseImage(g *errgroup.Group, cc *config.ClusterConfig, down } klog.Infof("failed to download %s, will try fallback image if available: %v", img, err) } - return fmt.Errorf("failed to download kic base image or any fallback image") + // second if we failed to download any fallback image + // that means probably all registries are blocked by network issues + // we can try to download the image from minikube release page + + // if we reach here, that means the user cannot have access to any docker registry + // this means the user is very likely to have a network issue + // downloading from github via http is the last resort, and we should remind the user + // that he should at least get access to github + // print essential warnings + out.WarningT("minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.") + out.WarningT("It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:") + envs := []string{"HTTP_PROXY", "HTTPS_PROXY", "http_proxy", "https_proxy", "ALL_PROXY", "NO_PROXY"} + for _, env := range envs { + if v := os.Getenv(env); v != "" { + out.Infof("{{.env}}={{.value}}", out.V{"env": env, "value": v}) + } + } + out.Ln("") + + kicbaseVersion := strings.Split(kic.Version, "-")[0] + finalImg, err = download.GHImageTarballToCache("kicbase", kicbaseVersion) + if err != nil { + klog.Infof("failed to download %s", finalImg) + return fmt.Errorf("failed to download kic base image or any fallback image") + } + klog.Infof("successfully downloaded %s as fall back image", finalImg) + if !downloadOnly && driver.IsDocker(cc.Driver) { + if finalImg, err = download.CacheToDaemon("kicbase"); err == nil { + klog.Infof("successfully loaded and using kicbase from tarball on github") + } + } + return nil + }) } From 1aa7e322fcbe56cce2abd1c292e5ee1c47a6b441 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:36:44 -0800 Subject: [PATCH 12/19] Build(deps): Bump github.com/otiai10/copy from 1.14.0 to 1.14.1 (#20209) Bumps [github.com/otiai10/copy](https://github.com/otiai10/copy) from 1.14.0 to 1.14.1. - [Release notes](https://github.com/otiai10/copy/releases) - [Commits](https://github.com/otiai10/copy/compare/v1.14.0...v1.14.1) --- updated-dependencies: - dependency-name: github.com/otiai10/copy dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 3 ++- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index f58e1b1eddb8..3d46124afaf4 100644 --- a/go.mod +++ b/go.mod @@ -51,7 +51,7 @@ require ( github.com/olekukonko/tablewriter v0.0.5 github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/runc v1.2.3 - github.com/otiai10/copy v1.14.0 + github.com/otiai10/copy v1.14.1 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 github.com/pkg/errors v0.9.1 @@ -199,6 +199,7 @@ require ( github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect github.com/opencontainers/image-spec v1.1.0-rc3 // indirect github.com/opencontainers/runtime-spec v1.2.0 // indirect + github.com/otiai10/mint v1.6.3 // indirect github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect diff --git a/go.sum b/go.sum index 5734e3966475..fc66af0af227 100644 --- a/go.sum +++ b/go.sum @@ -1357,10 +1357,10 @@ github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xA github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= -github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= -github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks= -github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= +github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= +github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= +github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= +github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= From d1767ec95521bb5a1969e0b4ed178fb27e8e2245 Mon Sep 17 00:00:00 2001 From: minikube-bot Date: Mon, 6 Jan 2025 13:37:16 -0800 Subject: [PATCH 13/19] Update auto-generated docs and translations (#20210) --- translations/de.json | 3 +++ translations/es.json | 3 +++ translations/fr.json | 3 +++ translations/ja.json | 3 +++ translations/ko.json | 3 +++ translations/pl.json | 3 +++ translations/ru.json | 3 +++ translations/strings.txt | 3 +++ translations/zh-CN.json | 3 +++ 9 files changed, 27 insertions(+) diff --git a/translations/de.json b/translations/de.json index d5da35fe90f5..e033994f2631 100644 --- a/translations/de.json +++ b/translations/de.json @@ -412,6 +412,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "Istio benötigt {{.minCPUs}} CPUs -- Ihre Konfiguration reserviert nur {{.cpus}} CPUs", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "Istio benötigt {{.minMem}}MB Speicher -- Ihre Konfiguration reserviert nur {{.memory}}MB", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "Es scheint, dass Sie GCE verwenden, was bedeutet, dass Authentifizierung auch ohne die GCP Auth Addons funktionieren sollte. Wenn Sie dennoch mittels Credential-Datei authentifizieren möchten, verwenden Sie --force.", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "Die Kicbase Images wurden nicht gelöscht. Um sie zu löschen, starten Sie:", "Kill the mount process spawned by minikube start": "Töte den Mount-Prozess, der durch minikube start gestartet wurde", "Kubernetes requires at least 2 CPU's to start": "Kubernetes benötigt mindestens 2 CPU's um zu starten", @@ -1077,6 +1078,7 @@ "max time to wait per Kubernetes or host to be healthy.": "maximale Zeit die gewartet werden soll, bis Kubernetes oder der Host als funktional angesehen soll.", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "Minikube unterstützt den BTRFS Storage Treiber noch nicht, aber es existiert eine Workaround, fügen Sie folgenden Flag zu Ihrem Start-Befehl hinzu `--feature-gates=\"LocalStorageCapacityIsolation=false\"`", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\\\"LocalStorageCapacityIsolation=false\\\"`": "minikube unterstützt den BTRFS Storage Treiber nicht, es gibt einen Workaround, füge den folgenden Paramater zum Start-Befehl hinzu `--feature-gates=\\\"LocalStorageCapacityIsolation=false\\\"`", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "Minikube fehlen die Dateien, die für die Gast-Umgebung erforderlich sind. Dies kann durch Ausführen von 'minikube delete' repariert werden", @@ -1163,6 +1165,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "{{.driver_name}} verfügt über weniger als 2 CPUs, aber Kubernetes benötigt mindestens 2 verfügbare CPUs", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "{{.driver_name}} hat nur {{.container_limit}}MB Speicher aber spezifiziert wurden {{.specified_memory}}MB", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "{{.driver}} hat nur {{.size}}MiB verfügbar, weniger als die für Kubernetes notwendigen {{.req}}MiB", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "{{.name}} hat keine Images.", "{{.name}} has following images:": "{{.name}} hat die folgenden Images:", "{{.name}} has no available configuration options": "{{.name}} hat keine verfügbaren Konfigurations-Optionen", diff --git a/translations/es.json b/translations/es.json index a963b1614e97..e5eced38ad1a 100644 --- a/translations/es.json +++ b/translations/es.json @@ -409,6 +409,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "", "Kill the mount process spawned by minikube start": "", "Kubernetes requires at least 2 CPU's to start": "", @@ -1034,6 +1035,7 @@ "max time to wait per Kubernetes or host to be healthy.": "", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "", "minikube is not meant for production use. You are opening non-local traffic": "", @@ -1117,6 +1119,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "", "{{.name}} has no available configuration options": "", "{{.name}} has the following images:": "", diff --git a/translations/fr.json b/translations/fr.json index bfb4fabaf40b..d288d74af2ab 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -406,6 +406,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "Istio a besoin de {{.minCPUs}} processeurs -- votre configuration n'alloue que {{.cpus}} processeurs", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "Istio a besoin de {{.minMem}}Mo de mémoire -- votre configuration n'alloue que {{.memory}}Mo", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "Il semble que vous exécutiez GCE, ce qui signifie que l'authentification devrait fonctionner sans le module GCP Auth. Si vous souhaitez toujours vous authentifier à l'aide d'un fichier d'informations d'identification, utilisez l'indicateur --force.", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "Les images Kicbase n'ont pas été supprimées. Pour supprimer des images, exécutez :", "Kill the mount process spawned by minikube start": "Tuez le processus de montage généré par le démarrage de minikube", "Kubernetes requires at least 2 CPU's to start": "Kubernetes nécessite au moins 2 processeurs pour démarrer", @@ -1061,6 +1062,7 @@ "max time to wait per Kubernetes or host to be healthy.": "temps d'attente maximal par Kubernetes ou hôte pour être en bonne santé.", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "minikube ne prend pas encore en charge le pilote de stockage BTRFS, il existe une solution de contournement, ajoutez l'indicateur suivant à votre commande de démarrage `--feature-gates=\"LocalStorageCapacityIsolation=false\"`", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "minikube manque des fichiers relatifs à votre environnement invité. Cela peut être corrigé en exécutant 'minikube delete'", "minikube is not meant for production use. You are opening non-local traffic": "minikube n'est pas destiné à une utilisation en production. Vous ouvrez du trafic non local", @@ -1151,6 +1153,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "{{.driver_name}} dispose de moins de 2 processeurs disponibles, mais Kubernetes nécessite au moins 2 procésseurs pour fonctionner", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "{{.driver_name}} ne dispose que de {{.container_limit}}Mo de mémoire, mais vous avez spécifié {{.specified_memory}}Mo", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "{{.driver}} ne dispose que de {{.size}}Mio disponible, moins que les {{.req}}Mio requis pour Kubernetes", + "{{.env}}={{.value}}": "", "{{.err}}": "{{.err}}", "{{.extra_option_component_name}}.{{.key}}={{.value}}": "{{.extra_option_component_name}}.{{.key}}={{.value}}", "{{.name}} doesn't have images.": "{{.name}} n'a pas d'images.", diff --git a/translations/ja.json b/translations/ja.json index ddfaee886a8d..d6df2d75203b 100644 --- a/translations/ja.json +++ b/translations/ja.json @@ -388,6 +388,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "Istio は {{.minCPUs}} 個の CPU を必要とします -- あなたの設定では {{.cpus}} 個の CPU しか割り当てていません", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "Istio は {{.minMem}}MB のメモリーを必要とします -- あなたの設定では、{{.memory}}MB しか割り当てていません", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "GCE 上で実行しているようですが、これは GCP Auth アドオンなしに認証が機能すべきであることになります。それでもクレデンシャルファイルを使用した認証を希望するのであれば、--force フラグを使用してください。", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "Kicbase イメージが削除されていません。次のコマンドでイメージを削除します:", "Kill the mount process spawned by minikube start": "minikube start によって実行されたマウントプロセスを強制停止します", "Kubernetes requires at least 2 CPU's to start": "Kubernetes は起動に少なくとも 2 個の CPU が必要です", @@ -1011,6 +1012,7 @@ "max time to wait per Kubernetes or host to be healthy.": "Kubernetes またはホストが正常稼働するまでの最大待機時間", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "minikube addons list --output OUTPUT. json, list", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "minikube はまだ BTRFS ストレージドライバーに対応していませんが、回避策があります。次のフラグを start コマンドに追加してください: `--feature-gates=\"LocalStorageCapacityIsolation=false\"` ", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "minikube はあなたのゲスト環境に関連するファイルを見失いました。これは 'minikube delete' を実行することで修正できます", "minikube is not meant for production use. You are opening non-local traffic": "minikube は本番適用を意図されたものではありません。あなたは非ローカルのトラフィックを開こうとしています", @@ -1098,6 +1100,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "{{.driver_name}} で利用できる CPU が 2 個未満ですが、Kubernetes を使用するには 2 個以上の CPU が必要です", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "{{.driver_name}} は {{.container_limit}}MB のメモリーしか使用できませんが、{{.specified_memory}}MB のメモリー使用を指定されました", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "{{.driver}} は Kubernetes に必要な {{.req}}MiB 未満の {{.size}}MiB しか使用できません", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "{{.name}} はイメージがありません。", "{{.name}} has following images:": "{{.name}} は次のイメージがあります:", "{{.name}} has no available configuration options": "{{.name}} には利用可能な設定オプションがありません", diff --git a/translations/ko.json b/translations/ko.json index 7805aaa8d853..fc8ff9c4da3c 100644 --- a/translations/ko.json +++ b/translations/ko.json @@ -424,6 +424,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "", "Kill the mount process spawned by minikube start": "", "Kubernetes requires at least 2 CPU's to start": "", @@ -1049,6 +1050,7 @@ "max time to wait per Kubernetes or host to be healthy.": "", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "", "minikube is not meant for production use. You are opening non-local traffic": "", @@ -1134,6 +1136,7 @@ "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "", "{{.driver}} does not appear to be installed": "{{.driver}} 가 설치되지 않았습니다", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "", + "{{.env}}={{.value}}": "", "{{.name}} cluster does not exist": "{{.name}} 클러스터가 존재하지 않습니다", "{{.name}} doesn't have images.": "{{.name}} 이미지가 없습니다.", "{{.name}} has following images:": "{{.name}}에는 다음과 같은 이미지가 있습니다.", diff --git a/translations/pl.json b/translations/pl.json index 6f743b36b116..d000d68c2567 100644 --- a/translations/pl.json +++ b/translations/pl.json @@ -408,6 +408,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "", "Kill the mount process spawned by minikube start": "", "Kubernetes requires at least 2 CPU's to start": "", @@ -1045,6 +1046,7 @@ "max time to wait per Kubernetes or host to be healthy.": "", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "", "minikube is not meant for production use. You are opening non-local traffic": "minikube nie jest przeznaczony do użycia w środowisku produkcyjnym. Otwierasz klaster na ruch nielokalny", @@ -1129,6 +1131,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "sterownik {{.driver}} ma tylko {{.size}}MiB dostępnej przestrzeni dyskowej, to mniej niż wymagane {{.req}}MiB dla Kubernetesa", + "{{.env}}={{.value}}": "", "{{.name}} cluster does not exist": "Klaster {{.name}} nie istnieje", "{{.name}} doesn't have images.": "{{.name}} nie ma obrazów.", "{{.name}} has following images:": "{{.name}} ma następujące obrazy:", diff --git a/translations/ru.json b/translations/ru.json index 80b268d8435c..43fa39c54aa4 100644 --- a/translations/ru.json +++ b/translations/ru.json @@ -371,6 +371,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "", "Kill the mount process spawned by minikube start": "", "Kubernetes requires at least 2 CPU's to start": "", @@ -963,6 +964,7 @@ "max time to wait per Kubernetes or host to be healthy.": "", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "", "minikube is not meant for production use. You are opening non-local traffic": "", @@ -1045,6 +1047,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "", "{{.name}} has no available configuration options": "", "{{.name}} has the following images:": "", diff --git a/translations/strings.txt b/translations/strings.txt index 32b5e0e67edb..cd03cd32af80 100644 --- a/translations/strings.txt +++ b/translations/strings.txt @@ -371,6 +371,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "", "Kill the mount process spawned by minikube start": "", "Kubernetes requires at least 2 CPU's to start": "", @@ -961,6 +962,7 @@ "max time to wait per Kubernetes or host to be healthy.": "", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "", "minikube is not meant for production use. You are opening non-local traffic": "", @@ -1043,6 +1045,7 @@ "{{.driver_name}} has less than 2 CPUs available, but Kubernetes requires at least 2 to be available": "", "{{.driver_name}} has only {{.container_limit}}MB memory but you specified {{.specified_memory}}MB": "", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "", "{{.name}} has no available configuration options": "", "{{.name}} has the following images:": "", diff --git a/translations/zh-CN.json b/translations/zh-CN.json index 40d03afbc710..96600bfa3c71 100644 --- a/translations/zh-CN.json +++ b/translations/zh-CN.json @@ -494,6 +494,7 @@ "Istio needs {{.minCPUs}} CPUs -- your configuration only allocates {{.cpus}} CPUs": "Istio 需要 {{.minCPUs}} 个CPU核心,但您的配置只分配了 {{.cpus}} 个CPU核心。", "Istio needs {{.minMem}}MB of memory -- your configuration only allocates {{.memory}}MB": "Istio 需要 {{.minMem}}MB 内存,而你的配置只分配了 {{.memory}}MB", "It seems that you are running in GCE, which means authentication should work without the GCP Auth addon. If you would still like to authenticate using a credentials file, use the --force flag.": "看起来您正在 GCE 中运行,这意味着身份验证应该可以在没有 GCP Auth 插件的情况下工作。如果您仍然想使用凭据文件进行身份验证,请使用 --force 标志。", + "It's very likely that you have an internet issue. Please ensure that you can access the internet at least via HTTP, directly or with proxy. Currently your proxy configure is:": "", "Kicbase images have not been deleted. To delete images run:": "Kicbase 镜像未被删除。要删除镜像,请运行:", "Kill the mount process spawned by minikube start": "终止由 minikube start 生成的挂载进程", "Kubernetes requires at least 2 CPU's to start": "Kubernetes至少需要2个CPU才能启动", @@ -1184,6 +1185,7 @@ "max time to wait per Kubernetes or host to be healthy.": "Kubernetes 或主机正常运行前的最大等待时间。", "minikube addons images ADDON_NAME --output OUTPUT. table, json": "", "minikube addons list --output OUTPUT. json, list": "minikube addons list --output OUTPUT. json, list", + "minikube cannot pull kicbase image from any docker registry, and is trying to download kicbase tarball from github release page via HTTP.": "", "minikube does not support the BTRFS storage driver yet, there is a workaround, add the following flag to your start command `--feature-gates=\"LocalStorageCapacityIsolation=false\"`": "minikube 尚不支持 BTRFS 存储驱动程序,有一个解决方法,将以下标志添加到你的启动命令 `--feature-gates=\"LocalStorageCapacityIsolation=false\"`", "minikube is exiting due to an error. If the above message is not useful, open an issue:": "由于出错 minikube 正在退出。如果以上信息没有帮助,请提交问题反馈:", "minikube is missing files relating to your guest environment. This can be fixed by running 'minikube delete'": "Minikube 缺少与客户环境相关的文件。这可以通过运行 'minikube delete' 来修复。", @@ -1273,6 +1275,7 @@ "{{.driver}} does not appear to be installed": "似乎并未安装 {{.driver}}", "{{.driver}} does not appear to be installed, but is specified by an existing profile. Please run 'minikube delete' or install {{.driver}}": "似乎并未安装 {{.driver}},但已被当前的配置文件指定。请执行 'minikube delete' 或者安装 {{.driver}}", "{{.driver}} only has {{.size}}MiB available, less than the required {{.req}}MiB for Kubernetes": "{{.driver}} 仅有 {{.size}}MiB 可用,少于 Kubernetes 所需的 {{.req}}MiB", + "{{.env}}={{.value}}": "", "{{.name}} doesn't have images.": "{{.name}} 没有镜像", "{{.name}} has following images:": "{{.name}} 有以下镜像", "{{.name}} has no available configuration options": "{{.name}} 没有可用的配置选项", From 886cdf276a6039e8ef9d276ed67c8177d63a0036 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 13:38:06 -0800 Subject: [PATCH 14/19] Build(deps): Bump github.com/elazarl/goproxy (#20208) Bumps [github.com/elazarl/goproxy](https://github.com/elazarl/goproxy) from 0.0.0-20210110162100-a92cc753f88e to 1.2.6. - [Release notes](https://github.com/elazarl/goproxy/releases) - [Commits](https://github.com/elazarl/goproxy/commits/v1.2.6) --- updated-dependencies: - dependency-name: github.com/elazarl/goproxy dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 7 ++----- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 3d46124afaf4..f0057336f81e 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/docker/go-connections v0.5.0 github.com/docker/go-units v0.5.0 github.com/docker/machine v0.16.2 - github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e + github.com/elazarl/goproxy v1.2.6 github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.20.2 diff --git a/go.sum b/go.sum index fc66af0af227..aa1785004b08 100644 --- a/go.sum +++ b/go.sum @@ -608,10 +608,8 @@ github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:Htrtb github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= -github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e h1:/cwV7t2xezilMljIftb7WlFtzGANRCnoOhPjtl2ifcs= -github.com/elazarl/goproxy v0.0.0-20210110162100-a92cc753f88e/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= -github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2 h1:dWB6v3RcOy03t/bUadywsbyrQwCqZeNIEX6M1OtSZOM= -github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2/go.mod h1:gNh8nYJoAm43RfaxurUnxr+N1PwuFV3ZMl/efxlIlY8= +github.com/elazarl/goproxy v1.2.6 h1:jk1cwYYz96HhB985lQ1FFv7UcYVQHV84w8lWtpxW7WE= +github.com/elazarl/goproxy v1.2.6/go.mod h1:yBhqz1/IaNA5tCayHGVfFmuzyanF6YeDNGIwPhfvtp8= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= @@ -1452,7 +1450,6 @@ github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= From 8e9d5043aed0da67c8e74bd9a132c20c7b3bc9ae Mon Sep 17 00:00:00 2001 From: minikube-bot Date: Mon, 6 Jan 2025 19:20:51 -0800 Subject: [PATCH 15/19] Site: Update hugo from v0.140.1 to v0.140.2 (#20202) --- netlify.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/netlify.toml b/netlify.toml index 3d55dc413ed1..6b6b15b878d1 100644 --- a/netlify.toml +++ b/netlify.toml @@ -5,7 +5,7 @@ command = "pwd && cd themes/docsy && npm install && git submodule update -f --in [build.environment] NODE_VERSION = "20.18.1" -HUGO_VERSION = "v0.140.1" +HUGO_VERSION = "v0.140.2" [context.production.environment] HUGO_ENV = "production" From 9fe757ef00e44b985e90477623aae608f0b1b92b Mon Sep 17 00:00:00 2001 From: minikube-bot Date: Mon, 6 Jan 2025 19:21:45 -0800 Subject: [PATCH 16/19] Update auto-generated docs and translations (#20211) From a819dbfa99894657f9ba415b882e4c0e30857e00 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 13 Jan 2025 11:07:06 -0800 Subject: [PATCH 17/19] Errors will exit instead of continuing. Adding integ test that loads basic config. --- cmd/minikube/cmd/config/configure.go | 16 ++- test/integration/configure_test.go | 126 ++++++++++++++++++ .../testdata/addons_testconfig.json | 30 +++++ 3 files changed, 167 insertions(+), 5 deletions(-) create mode 100644 test/integration/configure_test.go create mode 100644 test/integration/testdata/addons_testconfig.json diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 87112c9ad3d2..831ad3676df7 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -57,7 +57,10 @@ var addonsConfigureCmd = &cobra.Command{ profile := ClusterFlagValue() addon := args[0] - addonConfig := loadAddonConfigFile(addon, AddonConfigFile) + addonConfig, err := loadAddonConfigFile(addon, AddonConfigFile) + if err != nil { + return + } // allows for additional prompting of information when enabling addons switch addon { @@ -125,18 +128,21 @@ func init() { } // Helper method to load a config file for addons -func loadAddonConfigFile(addon, configFilePath string) (addonConfig map[string]any) { +func loadAddonConfigFile(addon, configFilePath string) (addonConfig map[string]any, err error) { if configFilePath != "" { configFileData := make(map[string]any) out.Ln("Reading %s configs from %s", addon, configFilePath) if confData, err := os.ReadFile(configFilePath); err != nil && errors.Is(err, os.ErrNotExist) { exit.Message(reason.Usage, "config file does not exist") + return nil, err } else if err != nil { exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, fmt.Sprintf("error opening config file: %v", err)) + return nil, err } else if err = json.Unmarshal(confData, &configFileData); err != nil { exit.Message(reason.Kind{ExitCode: reason.ExProgramConfig, Advice: "provide a valid config file"}, fmt.Sprintf("error opening config file: %v", err)) + return nil, err } // Make sure the addon specific config exists and it is a map @@ -359,7 +365,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) { dat, err := os.ReadFile(gcrPath) if err != nil { - out.FailureT("Error reading {{.path}}: {{.error}}", out.V{"path": gcrPath, "error": err}) + exit.Message(reason.Usage, "Error reading {{.path}}: {{.error}}", out.V{"path": gcrPath, "error": err}) } else { gcrApplicationDefaultCredentials = string(dat) } @@ -423,7 +429,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) { "kubernetes.io/minikube-addons": "registry-creds", }) if err != nil { - out.FailureT("ERROR creating `registry-creds-ecr` secret: {{.error}}", out.V{"error": err}) + exit.Message(reason.InternalCommandRunner, "ERROR creating `registry-creds-ecr` secret: {{.error}}", out.V{"error": err}) } // Create GCR Secret @@ -442,7 +448,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) { }) if err != nil { - out.FailureT("ERROR creating `registry-creds-gcr` secret: {{.error}}", out.V{"error": err}) + exit.Message(reason.InternalCommandRunner, "ERROR creating `registry-creds-gcr` secret: {{.error}}", out.V{"error": err}) } // Create Docker Secret diff --git a/test/integration/configure_test.go b/test/integration/configure_test.go new file mode 100644 index 000000000000..ed00c16d0b31 --- /dev/null +++ b/test/integration/configure_test.go @@ -0,0 +1,126 @@ +//go:build integration + +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package integration + +import ( + "context" + "os" + "os/exec" + "path/filepath" + "testing" + "time" + + "k8s.io/minikube/pkg/kapi" + "k8s.io/minikube/pkg/minikube/constants" +) + +// TestConfigure tests addons configure command to ensure that configurations are loaded/set correctly +func TestAddonsConfigure(t *testing.T) { + profile := UniqueProfileName("addons-configure") + ctx, cancel := context.WithTimeout(context.Background(), Minutes(40)) + defer Cleanup(t, profile, cancel) + + setupSucceeded := t.Run("Setup", func(t *testing.T) { + // Set an env var to point to our dummy credentials file + // don't use t.Setenv because we sometimes manually unset the env var later manually + err := os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", filepath.Join(*testdataDir, "gcp-creds.json")) + t.Cleanup(func() { + os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS") + }) + if err != nil { + t.Fatalf("Failed setting GOOGLE_APPLICATION_CREDENTIALS env var: %v", err) + } + + err = os.Setenv("GOOGLE_CLOUD_PROJECT", "this_is_fake") + t.Cleanup(func() { + os.Unsetenv("GOOGLE_CLOUD_PROJECT") + }) + if err != nil { + t.Fatalf("Failed setting GOOGLE_CLOUD_PROJECT env var: %v", err) + } + + // MOCK_GOOGLE_TOKEN forces the gcp-auth webhook to use a mock token instead of trying to get a valid one from the credentials. + os.Setenv("MOCK_GOOGLE_TOKEN", "true") + + // for some reason, (Docker_Cloud_Shell) sets 'MINIKUBE_FORCE_SYSTEMD=true' while having cgroupfs set in docker (and probably os itself), which might make it unstable and occasionally fail: + // - I1226 15:05:24.834294 11286 out.go:177] - MINIKUBE_FORCE_SYSTEMD=true + // - I1226 15:05:25.070037 11286 info.go:266] docker info: {... CgroupDriver:cgroupfs ...} + // ref: https://storage.googleapis.com/minikube-builds/logs/15463/27154/Docker_Cloud_Shell.html + // so we override that here to let minikube auto-detect appropriate cgroup driver + os.Setenv(constants.MinikubeForceSystemdEnv, "") + + // Add more addons as tests are added + args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry-creds"}, StartArgs()...) + rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) + if err != nil { + t.Fatalf("%s failed: %v", rr.Command(), err) + } + + }) + + if !setupSucceeded { + t.Fatalf("Failed setup for addon configure tests") + } + + type TestCase = struct { + name string + validator validateFunc + } + // Run tests in serial to avoid collision + + // Parallelized tests + t.Run("parallel", func(t *testing.T) { + tests := []TestCase{ + {"RegistryCreds", validateRegistryCredsAddon}, + } + + for _, tc := range tests { + tc := tc + if ctx.Err() == context.DeadlineExceeded { + t.Fatalf("Unable to run more tests (deadline exceeded)") + } + t.Run(tc.name, func(t *testing.T) { + MaybeParallel(t) + tc.validator(ctx, t, profile) + }) + } + }) +} + +// validateRegistryCredsAddon tests the registry-creds addon +func validateRegistryCredsAddon(ctx context.Context, t *testing.T, profile string) { + defer disableAddon(t, "registry-creds", profile) + defer PostMortemLogs(t, profile) + + client, err := kapi.Client(profile) + if err != nil { + t.Fatalf("failed to get Kubernetes client for %s : %v", profile, err) + } + + start := time.Now() + if err := kapi.WaitForDeploymentToStabilize(client, "kube-system", "registry-creds", Minutes(6)); err != nil { + t.Errorf("failed waiting for registry-creds deployment to stabilize: %v", err) + } + t.Logf("registry-creds stabilized in %s", time.Since(start)) + + rr, err := Run(t, exec.CommandContext(ctx, Target(), "addons", "configure", "registry-creds", "-f", "./testdata/addons_testconfig.json", "-p", profile)) + if err != nil { + t.Errorf("failed to configure addon. args %q : %v", rr.Command(), err) + } +} diff --git a/test/integration/testdata/addons_testconfig.json b/test/integration/testdata/addons_testconfig.json new file mode 100644 index 000000000000..fb75e1a84908 --- /dev/null +++ b/test/integration/testdata/addons_testconfig.json @@ -0,0 +1,30 @@ + { + "registry-creds": { + "enableAWSEcr": "enable", + "awsEcrConfigs": { + "awsAccessID": "test_aws_accessid", + "awsAccessKey": "test_aws_accesskey", + "awsSessionToken": "test_aws_session_token", + "awsRegion": "test_aws_region", + "awsAccount": "test_aws_account", + "awsRole": "test_aws_role" + }, + "enableGCR": "enable", + "gcrConfigs": { + "gcrPath": "./testdata/gcp-creds.json", + "gcrURL": "https://gcr.io" + }, + "enableDockerRegistry": "enable", + "dockerConfigs": { + "dockerServer": "test_docker_server", + "dockerUser": "test_docker_user", + "dockerPass": "test_docker_password" + }, + "enableACR": "disable", + "acrConfigs": { + "acrURL": "test_acr_url", + "acrClientID": "test_acr_clientid", + "acrPassword": "test_acr_password" + } + } + } From 1f355fa819b32e9a71ef004bc2f4dd37726a15d8 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 13 Jan 2025 11:31:07 -0800 Subject: [PATCH 18/19] validation for registry-creds config test --- cmd/minikube/cmd/config/configure.go | 3 +- test/integration/configure_test.go | 39 +++++++++++++++++++ .../testdata/addons_testconfig.json | 2 +- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index 831ad3676df7..f0220a624178 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -350,7 +350,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) { } } } else if gcrAction == "enable" { - out.Ln("Loading GCR configs from: ", AddonConfigFile) + out.Ln("Loading GCR configs from: %s", AddonConfigFile) // Then read the configs gcrPath = getNestedJSONString(configFileData, "gcrConfigs", "gcrPath") gcrURL = getNestedJSONString(configFileData, "gcrConfigs", "gcrURL") @@ -380,6 +380,7 @@ func processRegistryCredsConfig(profile string, configFileData map[string]any) { dockerPass = AskForPasswordValue("-- Enter docker registry password: ") } } else if dockerRegistryAction == "enable" { + out.Ln("Loading Docker Registry configs from: %s", AddonConfigFile) dockerServer = getNestedJSONString(configFileData, "dockerConfigs", "dockerServer") dockerUser = getNestedJSONString(configFileData, "dockerConfigs", "dockerUser") dockerPass = getNestedJSONString(configFileData, "dockerConfigs", "dockerPass") diff --git a/test/integration/configure_test.go b/test/integration/configure_test.go index ed00c16d0b31..d935b0dd1c84 100644 --- a/test/integration/configure_test.go +++ b/test/integration/configure_test.go @@ -20,9 +20,12 @@ package integration import ( "context" + "fmt" "os" "os/exec" "path/filepath" + "regexp" + "strings" "testing" "time" @@ -123,4 +126,40 @@ func validateRegistryCredsAddon(ctx context.Context, t *testing.T, profile strin if err != nil { t.Errorf("failed to configure addon. args %q : %v", rr.Command(), err) } + + // Check a few secrets exists that match our test data + // In our test aws and gcp are set, docker and acr are disabled - so they will be set to "changeme" + rr, err = Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "-n", "kube-system", "get", "secret", "-o", "yaml")) + if err != nil { + t.Errorf("failed to get secrets. args %q : %v", rr.Command(), err) + } + + expected := []string{ + "DOCKER_PRIVATE_REGISTRY_PASSWORD: Y2hhbmdlbWU=", + "DOCKER_PRIVATE_REGISTRY_SERVER: Y2hhbmdlbWU=", + "DOCKER_PRIVATE_REGISTRY_USER: Y2hhbmdlbWU=", + + "ACR_CLIENT_ID: Y2hhbmdlbWU=", + "ACR_PASSWORD: Y2hhbmdlbWU=", + "ACR_URL: Y2hhbmdlbWU=", + + "AWS_ACCESS_KEY_ID: dGVzdF9hd3NfYWNjZXNzaWQ=", + "AWS_SECRET_ACCESS_KEY: dGVzdF9hd3NfYWNjZXNza2V5", + "AWS_SESSION_TOKEN: dGVzdF9hd3Nfc2Vzc2lvbl90b2tlbg==", + "aws-account: dGVzdF9hd3NfYWNjb3VudA==", + "aws-assume-role: dGVzdF9hd3Nfcm9sZQ==", + "aws-region: dGVzdF9hd3NfcmVnaW9u", + + "application_default_credentials.json: ewogICJjbGllbnRfaWQiOiAiaGFoYSIsCiAgImNsaWVudF9zZWNyZXQiOiAibmljZV90cnkiLAogICJxdW90YV9wcm9qZWN0X2lkIjogInRoaXNfaXNfZmFrZSIsCiAgInJlZnJlc2hfdG9rZW4iOiAibWF5YmVfbmV4dF90aW1lIiwKICAidHlwZSI6ICJhdXRob3JpemVkX3VzZXIiCn0K", + "gcrurl: aHR0cHM6Ly9nY3IuaW8=", + } + + rrout := strings.TrimSpace(rr.Stdout.String()) + for _, exp := range expected { + re := regexp.MustCompile(fmt.Sprintf(".*%s.*", exp)) + secret := re.FindString(rrout) + if secret == "" { + t.Errorf("Did not find expected secret: '%s'", secret) + } + } } diff --git a/test/integration/testdata/addons_testconfig.json b/test/integration/testdata/addons_testconfig.json index fb75e1a84908..9c13d248f858 100644 --- a/test/integration/testdata/addons_testconfig.json +++ b/test/integration/testdata/addons_testconfig.json @@ -14,7 +14,7 @@ "gcrPath": "./testdata/gcp-creds.json", "gcrURL": "https://gcr.io" }, - "enableDockerRegistry": "enable", + "enableDockerRegistry": "disable", "dockerConfigs": { "dockerServer": "test_docker_server", "dockerUser": "test_docker_user", From 567753bd9305d7348e35c86cf84784fa20bcac10 Mon Sep 17 00:00:00 2001 From: Sriram Panyam Date: Mon, 13 Jan 2025 11:58:02 -0800 Subject: [PATCH 19/19] moving registry creds test back to addons test, adding an extra top level 'addons' in config file --- cmd/minikube/cmd/config/configure.go | 10 +- test/integration/addons_test.go | 61 ++++++- test/integration/configure_test.go | 165 ------------------ .../testdata/addons_testconfig.json | 54 +++--- 4 files changed, 95 insertions(+), 195 deletions(-) delete mode 100644 test/integration/configure_test.go diff --git a/cmd/minikube/cmd/config/configure.go b/cmd/minikube/cmd/config/configure.go index f0220a624178..d5039df5e844 100644 --- a/cmd/minikube/cmd/config/configure.go +++ b/cmd/minikube/cmd/config/configure.go @@ -146,9 +146,13 @@ func loadAddonConfigFile(addon, configFilePath string) (addonConfig map[string]a } // Make sure the addon specific config exists and it is a map - if addonSpecificConfig, ok := configFileData[addon]; ok && addonSpecificConfig != nil { - if casted, ok := addonSpecificConfig.(map[string]any); casted != nil && ok { - addonConfig = casted + if addonSection, ok := configFileData["addons"]; ok && addonSection != nil { + if addonSectionMap, ok := addonSection.(map[string]any); ok && addonSectionMap != nil { + if addonSpecificConfig, ok := addonSectionMap[addon]; ok && addonSpecificConfig != nil { + if casted, ok := addonSpecificConfig.(map[string]any); casted != nil && ok { + addonConfig = casted + } + } } } } diff --git a/test/integration/addons_test.go b/test/integration/addons_test.go index f060af61d3c4..d3d3b79b53a0 100644 --- a/test/integration/addons_test.go +++ b/test/integration/addons_test.go @@ -100,7 +100,7 @@ func TestAddons(t *testing.T) { // so we override that here to let minikube auto-detect appropriate cgroup driver os.Setenv(constants.MinikubeForceSystemdEnv, "") - args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry", "--addons=metrics-server", "--addons=volumesnapshots", "--addons=csi-hostpath-driver", "--addons=gcp-auth", "--addons=cloud-spanner", "--addons=inspektor-gadget", "--addons=nvidia-device-plugin", "--addons=yakd", "--addons=volcano", "--addons=amd-gpu-device-plugin"}, StartArgs()...) + args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry", "--addons=registry-creds", "--addons=metrics-server", "--addons=volumesnapshots", "--addons=csi-hostpath-driver", "--addons=gcp-auth", "--addons=cloud-spanner", "--addons=inspektor-gadget", "--addons=nvidia-device-plugin", "--addons=yakd", "--addons=volcano", "--addons=amd-gpu-device-plugin"}, StartArgs()...) if !NoneDriver() { args = append(args, "--addons=ingress", "--addons=ingress-dns", "--addons=storage-provisioner-rancher") } @@ -140,6 +140,7 @@ func TestAddons(t *testing.T) { t.Run("parallel", func(t *testing.T) { tests := []TestCase{ {"Registry", validateRegistryAddon}, + {"RegistryCreds", validateRegistryCredsAddon}, {"Ingress", validateIngressAddon}, {"InspektorGadget", validateInspektorGadgetAddon}, {"MetricsServer", validateMetricsServerAddon}, @@ -304,6 +305,64 @@ func validateIngressAddon(ctx context.Context, t *testing.T, profile string) { } } +// validateRegistryCredsAddon tests the registry-creds addon by trying to load its configs +func validateRegistryCredsAddon(ctx context.Context, t *testing.T, profile string) { + defer disableAddon(t, "registry-creds", profile) + defer PostMortemLogs(t, profile) + + client, err := kapi.Client(profile) + if err != nil { + t.Fatalf("failed to get Kubernetes client for %s : %v", profile, err) + } + + start := time.Now() + if err := kapi.WaitForDeploymentToStabilize(client, "kube-system", "registry-creds", Minutes(6)); err != nil { + t.Errorf("failed waiting for registry-creds deployment to stabilize: %v", err) + } + t.Logf("registry-creds stabilized in %s", time.Since(start)) + + rr, err := Run(t, exec.CommandContext(ctx, Target(), "addons", "configure", "registry-creds", "-f", "./testdata/addons_testconfig.json", "-p", profile)) + if err != nil { + t.Errorf("failed to configure addon. args %q : %v", rr.Command(), err) + } + + // Check a few secrets exists that match our test data + // In our test aws and gcp are set, docker and acr are disabled - so they will be set to "changeme" + rr, err = Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "-n", "kube-system", "get", "secret", "-o", "yaml")) + if err != nil { + t.Errorf("failed to get secrets. args %q : %v", rr.Command(), err) + } + + expected := []string{ + "DOCKER_PRIVATE_REGISTRY_PASSWORD: Y2hhbmdlbWU=", + "DOCKER_PRIVATE_REGISTRY_SERVER: Y2hhbmdlbWU=", + "DOCKER_PRIVATE_REGISTRY_USER: Y2hhbmdlbWU=", + + "ACR_CLIENT_ID: Y2hhbmdlbWU=", + "ACR_PASSWORD: Y2hhbmdlbWU=", + "ACR_URL: Y2hhbmdlbWU=", + + "AWS_ACCESS_KEY_ID: dGVzdF9hd3NfYWNjZXNzaWQ=", + "AWS_SECRET_ACCESS_KEY: dGVzdF9hd3NfYWNjZXNza2V5", + "AWS_SESSION_TOKEN: dGVzdF9hd3Nfc2Vzc2lvbl90b2tlbg==", + "aws-account: dGVzdF9hd3NfYWNjb3VudA==", + "aws-assume-role: dGVzdF9hd3Nfcm9sZQ==", + "aws-region: dGVzdF9hd3NfcmVnaW9u", + + "application_default_credentials.json: ewogICJjbGllbnRfaWQiOiAiaGFoYSIsCiAgImNsaWVudF9zZWNyZXQiOiAibmljZV90cnkiLAogICJxdW90YV9wcm9qZWN0X2lkIjogInRoaXNfaXNfZmFrZSIsCiAgInJlZnJlc2hfdG9rZW4iOiAibWF5YmVfbmV4dF90aW1lIiwKICAidHlwZSI6ICJhdXRob3JpemVkX3VzZXIiCn0K", + "gcrurl: aHR0cHM6Ly9nY3IuaW8=", + } + + rrout := strings.TrimSpace(rr.Stdout.String()) + for _, exp := range expected { + re := regexp.MustCompile(fmt.Sprintf(".*%s.*", exp)) + secret := re.FindString(rrout) + if secret == "" { + t.Errorf("Did not find expected secret: '%s'", secret) + } + } +} + // validateRegistryAddon tests the registry addon func validateRegistryAddon(ctx context.Context, t *testing.T, profile string) { defer disableAddon(t, "registry", profile) diff --git a/test/integration/configure_test.go b/test/integration/configure_test.go deleted file mode 100644 index d935b0dd1c84..000000000000 --- a/test/integration/configure_test.go +++ /dev/null @@ -1,165 +0,0 @@ -//go:build integration - -/* -Copyright 2016 The Kubernetes Authors All rights reserved. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package integration - -import ( - "context" - "fmt" - "os" - "os/exec" - "path/filepath" - "regexp" - "strings" - "testing" - "time" - - "k8s.io/minikube/pkg/kapi" - "k8s.io/minikube/pkg/minikube/constants" -) - -// TestConfigure tests addons configure command to ensure that configurations are loaded/set correctly -func TestAddonsConfigure(t *testing.T) { - profile := UniqueProfileName("addons-configure") - ctx, cancel := context.WithTimeout(context.Background(), Minutes(40)) - defer Cleanup(t, profile, cancel) - - setupSucceeded := t.Run("Setup", func(t *testing.T) { - // Set an env var to point to our dummy credentials file - // don't use t.Setenv because we sometimes manually unset the env var later manually - err := os.Setenv("GOOGLE_APPLICATION_CREDENTIALS", filepath.Join(*testdataDir, "gcp-creds.json")) - t.Cleanup(func() { - os.Unsetenv("GOOGLE_APPLICATION_CREDENTIALS") - }) - if err != nil { - t.Fatalf("Failed setting GOOGLE_APPLICATION_CREDENTIALS env var: %v", err) - } - - err = os.Setenv("GOOGLE_CLOUD_PROJECT", "this_is_fake") - t.Cleanup(func() { - os.Unsetenv("GOOGLE_CLOUD_PROJECT") - }) - if err != nil { - t.Fatalf("Failed setting GOOGLE_CLOUD_PROJECT env var: %v", err) - } - - // MOCK_GOOGLE_TOKEN forces the gcp-auth webhook to use a mock token instead of trying to get a valid one from the credentials. - os.Setenv("MOCK_GOOGLE_TOKEN", "true") - - // for some reason, (Docker_Cloud_Shell) sets 'MINIKUBE_FORCE_SYSTEMD=true' while having cgroupfs set in docker (and probably os itself), which might make it unstable and occasionally fail: - // - I1226 15:05:24.834294 11286 out.go:177] - MINIKUBE_FORCE_SYSTEMD=true - // - I1226 15:05:25.070037 11286 info.go:266] docker info: {... CgroupDriver:cgroupfs ...} - // ref: https://storage.googleapis.com/minikube-builds/logs/15463/27154/Docker_Cloud_Shell.html - // so we override that here to let minikube auto-detect appropriate cgroup driver - os.Setenv(constants.MinikubeForceSystemdEnv, "") - - // Add more addons as tests are added - args := append([]string{"start", "-p", profile, "--wait=true", "--memory=4000", "--alsologtostderr", "--addons=registry-creds"}, StartArgs()...) - rr, err := Run(t, exec.CommandContext(ctx, Target(), args...)) - if err != nil { - t.Fatalf("%s failed: %v", rr.Command(), err) - } - - }) - - if !setupSucceeded { - t.Fatalf("Failed setup for addon configure tests") - } - - type TestCase = struct { - name string - validator validateFunc - } - // Run tests in serial to avoid collision - - // Parallelized tests - t.Run("parallel", func(t *testing.T) { - tests := []TestCase{ - {"RegistryCreds", validateRegistryCredsAddon}, - } - - for _, tc := range tests { - tc := tc - if ctx.Err() == context.DeadlineExceeded { - t.Fatalf("Unable to run more tests (deadline exceeded)") - } - t.Run(tc.name, func(t *testing.T) { - MaybeParallel(t) - tc.validator(ctx, t, profile) - }) - } - }) -} - -// validateRegistryCredsAddon tests the registry-creds addon -func validateRegistryCredsAddon(ctx context.Context, t *testing.T, profile string) { - defer disableAddon(t, "registry-creds", profile) - defer PostMortemLogs(t, profile) - - client, err := kapi.Client(profile) - if err != nil { - t.Fatalf("failed to get Kubernetes client for %s : %v", profile, err) - } - - start := time.Now() - if err := kapi.WaitForDeploymentToStabilize(client, "kube-system", "registry-creds", Minutes(6)); err != nil { - t.Errorf("failed waiting for registry-creds deployment to stabilize: %v", err) - } - t.Logf("registry-creds stabilized in %s", time.Since(start)) - - rr, err := Run(t, exec.CommandContext(ctx, Target(), "addons", "configure", "registry-creds", "-f", "./testdata/addons_testconfig.json", "-p", profile)) - if err != nil { - t.Errorf("failed to configure addon. args %q : %v", rr.Command(), err) - } - - // Check a few secrets exists that match our test data - // In our test aws and gcp are set, docker and acr are disabled - so they will be set to "changeme" - rr, err = Run(t, exec.CommandContext(ctx, "kubectl", "--context", profile, "-n", "kube-system", "get", "secret", "-o", "yaml")) - if err != nil { - t.Errorf("failed to get secrets. args %q : %v", rr.Command(), err) - } - - expected := []string{ - "DOCKER_PRIVATE_REGISTRY_PASSWORD: Y2hhbmdlbWU=", - "DOCKER_PRIVATE_REGISTRY_SERVER: Y2hhbmdlbWU=", - "DOCKER_PRIVATE_REGISTRY_USER: Y2hhbmdlbWU=", - - "ACR_CLIENT_ID: Y2hhbmdlbWU=", - "ACR_PASSWORD: Y2hhbmdlbWU=", - "ACR_URL: Y2hhbmdlbWU=", - - "AWS_ACCESS_KEY_ID: dGVzdF9hd3NfYWNjZXNzaWQ=", - "AWS_SECRET_ACCESS_KEY: dGVzdF9hd3NfYWNjZXNza2V5", - "AWS_SESSION_TOKEN: dGVzdF9hd3Nfc2Vzc2lvbl90b2tlbg==", - "aws-account: dGVzdF9hd3NfYWNjb3VudA==", - "aws-assume-role: dGVzdF9hd3Nfcm9sZQ==", - "aws-region: dGVzdF9hd3NfcmVnaW9u", - - "application_default_credentials.json: ewogICJjbGllbnRfaWQiOiAiaGFoYSIsCiAgImNsaWVudF9zZWNyZXQiOiAibmljZV90cnkiLAogICJxdW90YV9wcm9qZWN0X2lkIjogInRoaXNfaXNfZmFrZSIsCiAgInJlZnJlc2hfdG9rZW4iOiAibWF5YmVfbmV4dF90aW1lIiwKICAidHlwZSI6ICJhdXRob3JpemVkX3VzZXIiCn0K", - "gcrurl: aHR0cHM6Ly9nY3IuaW8=", - } - - rrout := strings.TrimSpace(rr.Stdout.String()) - for _, exp := range expected { - re := regexp.MustCompile(fmt.Sprintf(".*%s.*", exp)) - secret := re.FindString(rrout) - if secret == "" { - t.Errorf("Did not find expected secret: '%s'", secret) - } - } -} diff --git a/test/integration/testdata/addons_testconfig.json b/test/integration/testdata/addons_testconfig.json index 9c13d248f858..3805b5737b2b 100644 --- a/test/integration/testdata/addons_testconfig.json +++ b/test/integration/testdata/addons_testconfig.json @@ -1,30 +1,32 @@ { - "registry-creds": { - "enableAWSEcr": "enable", - "awsEcrConfigs": { - "awsAccessID": "test_aws_accessid", - "awsAccessKey": "test_aws_accesskey", - "awsSessionToken": "test_aws_session_token", - "awsRegion": "test_aws_region", - "awsAccount": "test_aws_account", - "awsRole": "test_aws_role" - }, - "enableGCR": "enable", - "gcrConfigs": { - "gcrPath": "./testdata/gcp-creds.json", - "gcrURL": "https://gcr.io" - }, - "enableDockerRegistry": "disable", - "dockerConfigs": { - "dockerServer": "test_docker_server", - "dockerUser": "test_docker_user", - "dockerPass": "test_docker_password" - }, - "enableACR": "disable", - "acrConfigs": { - "acrURL": "test_acr_url", - "acrClientID": "test_acr_clientid", - "acrPassword": "test_acr_password" + "addons": { + "registry-creds": { + "enableAWSEcr": "enable", + "awsEcrConfigs": { + "awsAccessID": "test_aws_accessid", + "awsAccessKey": "test_aws_accesskey", + "awsSessionToken": "test_aws_session_token", + "awsRegion": "test_aws_region", + "awsAccount": "test_aws_account", + "awsRole": "test_aws_role" + }, + "enableGCR": "enable", + "gcrConfigs": { + "gcrPath": "./testdata/gcp-creds.json", + "gcrURL": "https://gcr.io" + }, + "enableDockerRegistry": "disable", + "dockerConfigs": { + "dockerServer": "test_docker_server", + "dockerUser": "test_docker_user", + "dockerPass": "test_docker_password" + }, + "enableACR": "disable", + "acrConfigs": { + "acrURL": "test_acr_url", + "acrClientID": "test_acr_clientid", + "acrPassword": "test_acr_password" + } } } }