diff --git a/utils/error.go b/utils/error.go index b1e50625..5716fc8a 100644 --- a/utils/error.go +++ b/utils/error.go @@ -46,7 +46,11 @@ var ( ErrCopyFileCode = "replace_me" ErrCloseFileCode = "replace_me" ErrCompressToTarGZCode = "meshkit-11248" + + ErrConvertToByteCode = "meshkit-11187" + ErrOpenFileCode = "replace_me" + ) var ( ErrExtractType = errors.New( @@ -151,6 +155,10 @@ func ErrCreateDir(err error, filepath string) error { return errors.New(ErrCreateDirCode, errors.Alert, []string{fmt.Sprintf("error creating directory at %s", filepath)}, []string{err.Error()}, []string{"invalid path provided", "insufficient permissions"}, []string{"provide a valid path", "retry by using an absolute path", "check for sufficient permissions for the user"}) } +func ErrConvertToByte(err error) error { + return errors.New(ErrConvertToByteCode, errors.Alert, []string{("error converting data to []byte")}, []string{err.Error()}, []string{"Unsupported data types", "invalid configuration data", "failed serialization of data"}, []string{"check for any custom types in the data that might not be serializable", "Verify that the data type being passed is valid for conversion to []byte"}) +} + func ErrGettingLatestReleaseTag(err error) error { return errors.New( ErrGettingLatestReleaseTagCode, diff --git a/utils/kubernetes/apply-helm-chart.go b/utils/kubernetes/apply-helm-chart.go index 7dcc61e9..c633c40f 100644 --- a/utils/kubernetes/apply-helm-chart.go +++ b/utils/kubernetes/apply-helm-chart.go @@ -454,7 +454,7 @@ func generateAction(actionConfig *action.Configuration, cfg ApplyHelmChartConfig case UNINSTALL: return func(c *chart.Chart) error { act := action.NewUninstall(actionConfig) - + act.DryRun = cfg.DryRun if _, err := act.Run(cfg.ReleaseName); err != nil { return ErrApplyHelmChart(err) diff --git a/utils/kubernetes/client.go b/utils/kubernetes/client.go index 146da142..6570fefe 100644 --- a/utils/kubernetes/client.go +++ b/utils/kubernetes/client.go @@ -14,58 +14,90 @@ import ( func DetectKubeConfig(configfile []byte) (config *rest.Config, err error) { if len(configfile) > 0 { var cfgFile []byte - cfgFile, err = processConfig(configfile) + + _, cfgFile, err = ProcessConfig(configfile, "") if err != nil { return nil, err } if config, err = clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil { - return config, err + return config, ErrRestConfigFromKubeConfig(err) } } // If deployed within the cluster if config, err = rest.InClusterConfig(); err == nil { - return config, err + return config, ErrRestConfigFromKubeConfig(err) } // Look for kubeconfig from the path mentioned in $KUBECONFIG kubeconfig := os.Getenv("KUBECONFIG") if kubeconfig != "" { - if config, err = clientcmd.BuildConfigFromFlags("", kubeconfig); err == nil { - return config, err + _, cfgFile, err := ProcessConfig(kubeconfig, "") + if err != nil { + return nil, err + } + if config, err = clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil { + return config, ErrRestConfigFromKubeConfig(err) } } // Look for kubeconfig at the default path path := filepath.Join(utils.GetHome(), ".kube", "config") - if config, err = clientcmd.BuildConfigFromFlags("", path); err == nil { - return config, err + _, cfgFile, err := ProcessConfig(path, "") + if err != nil { + return nil, err + } + if config, err = clientcmd.RESTConfigFromKubeConfig(cfgFile); err == nil { + return config, ErrRestConfigFromKubeConfig(err) } return } -func processConfig(configFile []byte) ([]byte, error) { - cfg, err := clientcmd.Load(configFile) +// ProcessConfig handles loading, validating, and optionally saving or returning a kubeconfig +func ProcessConfig(kubeConfig interface{}, outputPath string) (*clientcmdapi.Config, []byte, error) { + var config *clientcmdapi.Config + var err error + + // Load the Kubeconfig + switch v := kubeConfig.(type) { + case string: + config, err = clientcmd.LoadFromFile(v) + case []byte: + config, err = clientcmd.Load(v) + default: + return nil, nil, ErrLoadConfig(err) + } if err != nil { - return nil, ErrLoadConfig(err) + return nil, nil, ErrLoadConfig(err) } - err = clientcmdapi.MinifyConfig(cfg) - if err != nil { - return nil, ErrValidateConfig(err) + // Validate and Process the Config + if err := clientcmdapi.MinifyConfig(config); err != nil { + return nil, nil, ErrValidateConfig(err) } - err = clientcmdapi.FlattenConfig(cfg) - if err != nil { - return nil, ErrValidateConfig(err) + if err := clientcmdapi.FlattenConfig(config); err != nil { + return nil, nil, ErrValidateConfig(err) + } + + if err := clientcmd.Validate(*config); err != nil { + return nil, nil, ErrValidateConfig(err) } - err = clientcmd.Validate(*cfg) + // Convert the config to []byte + configBytes, err := clientcmd.Write(*config) if err != nil { - return nil, ErrValidateConfig(err) + return nil, nil, utils.ErrConvertToByte(err) + } + + //Save the Processed config to a file + if outputPath != "" { + if err := clientcmd.WriteToFile(*config, outputPath); err != nil { + return nil, nil, utils.ErrWriteFile(err, outputPath) + } } - return clientcmd.Write(*cfg) + return config, configBytes, nil } diff --git a/utils/kubernetes/error.go b/utils/kubernetes/error.go index 10b2d6ea..7d94bfa4 100644 --- a/utils/kubernetes/error.go +++ b/utils/kubernetes/error.go @@ -35,6 +35,7 @@ var ( ErrEntryWithChartVersionNotExistsCode = "meshkit-11204" ErrEndpointNotFound = errors.New(ErrEndpointNotFoundCode, errors.Alert, []string{"Unable to discover an endpoint"}, []string{}, []string{}, []string{}) ErrInvalidAPIServer = errors.New(ErrInvalidAPIServerCode, errors.Alert, []string{"Invalid API Server URL"}, []string{}, []string{}, []string{}) + ErrRestConfigFromKubeConfigCode = "meshkit-11205" ) func ErrApplyManifest(err error) error { @@ -51,22 +52,22 @@ func ErrApplyHelmChart(err error) error { return errors.New(ErrApplyHelmChartCode, errors.Alert, []string{"Error applying helm chart"}, []string{err.Error()}, []string{"Chart could be invalid"}, []string{"Make sure to apply valid chart"}) } -// ErrApplyHelmChart is the error which occurs in the process of applying helm chart +// ErrNewKubeClient is the error which occurs when creating a new Kubernetes clientset func ErrNewKubeClient(err error) error { return errors.New(ErrNewKubeClientCode, errors.Alert, []string{"Error creating kubernetes clientset"}, []string{err.Error()}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"}) } -// ErrApplyHelmChart is the error which occurs in the process of applying helm chart +// ErrNewDynClient is the error which occurs when creating a new dynamic client func ErrNewDynClient(err error) error { return errors.New(ErrNewDynClientCode, errors.Alert, []string{"Error creating dynamic client"}, []string{err.Error()}, []string{"Kubernetes config is not accessible to meshery or not valid"}, []string{"Upload your kubernetes config via the settings dashboard. If uploaded, wait for a minute for it to get initialized"}) } -// ErrApplyHelmChart is the error which occurs in the process of applying helm chart +// ErrNewDiscovery is the error which occurs when creating a new discovery client func ErrNewDiscovery(err error) error { return errors.New(ErrNewDiscoveryCode, errors.Alert, []string{"Error creating discovery client"}, []string{err.Error()}, []string{"Discovery resource is invalid or doesnt exist"}, []string{"Makes sure the you input valid resource for discovery"}) } -// ErrApplyHelmChart is the error which occurs in the process of applying helm chart +// ErrNewInformer is the error which occurs when creating a new informer func ErrNewInformer(err error) error { return errors.New(ErrNewInformerCode, errors.Alert, []string{"Error creating informer client"}, []string{err.Error()}, []string{"Informer is invalid or doesnt exist"}, []string{"Makes sure the you input valid resource for the informer"}) } @@ -100,3 +101,19 @@ func ErrEntryWithChartVersionNotExists(entry, appVersion string) error { func ErrHelmRepositoryNotFound(repo string, err error) error { return errors.New(ErrHelmRepositoryNotFoundCode, errors.Alert, []string{"Helm repo not found"}, []string{fmt.Sprintf("either the repo %s does not exists or is corrupt: %v", repo, err)}, []string{}, []string{}) } + +// ErrRestConfigFromKubeConfig returns an error when failing to create a REST config from a kubeconfig file. +func ErrRestConfigFromKubeConfig(err error) error { + return errors.New(ErrRestConfigFromKubeConfigCode, + errors.Alert, + []string{"Failed to create REST config from kubeconfig."}, + []string{fmt.Sprintf("Error occured while creating REST config from kubeconfig: %s", err.Error())}, + []string{ + "The provided kubeconfig data might be invalid or corrupted.", + "The kubeconfig might be incomplete or missing required fields."}, + []string{ + "Verify that the kubeconfig data is valid.", + "Ensure the kubeconfig contains all necessary cluster, user, and context information.", + "Check if the kubeconfig data was properly read and passed to the function."}, + ) +}