diff --git a/capten/agent/internal/crossplane/cluster_claims.go b/capten/agent/internal/crossplane/cluster_claims.go index 54123f5d4..3e79117aa 100644 --- a/capten/agent/internal/crossplane/cluster_claims.go +++ b/capten/agent/internal/crossplane/cluster_claims.go @@ -22,9 +22,7 @@ import ( ) var ( - readyStatusType = "ready" - nodePoolStatusType = "nodepool" - controlPlaneStatusType = "controlplane" + readyStatusType = "ready" clusterNotReadyStatus = "NotReady" clusterReadyStatus = "Ready" @@ -167,10 +165,12 @@ func (h *ClusterClaimSyncHandler) updateManagedClusters(clusterCliams []model.Cl for _, clusterCliam := range clusterCliams { h.log.Infof("processing cluster claim %s", clusterCliam.Metadata.Name) - nodePoolStatus, controlPlaneStatus, readyStatus := getClusterClaimStatus(clusterCliam.Status.Conditions) - h.log.Infof("cluster claim %s status: %s-%s-%s", clusterCliam.Metadata.Name, nodePoolStatus, controlPlaneStatus, readyStatus) + readyStatus := h.getClusterClaimStatus(clusterCliam.Status.Conditions) + h.log.Infof("cluster claim %s status: %s-%s-%s", clusterCliam.Metadata.Name, + clusterCliam.Status.NodePoolStatus, clusterCliam.Status.ControlPlaneStatus, readyStatus) - if !(strings.EqualFold(nodePoolStatus, "active") && strings.EqualFold(controlPlaneStatus, "active")) { + if !(strings.EqualFold(clusterCliam.Status.NodePoolStatus, "active") && + strings.EqualFold(clusterCliam.Status.ControlPlaneStatus, "active")) { h.log.Infof("cluster %s is not created", clusterCliam.Metadata.Name) return nil } @@ -221,7 +221,6 @@ func (h *ClusterClaimSyncHandler) updateManagedClusters(clusterCliams []model.Cl h.log.Infof("updated the cluster claim %s with status %s", managedCluster.ClusterName, managedCluster.ClusterDeployStatus) if managedCluster.ClusterDeployStatus == clusterReadyStatus { - // call config-worker. err = h.triggerClusterUpdates(clusterCliam.Spec.Id, managedCluster.Id) if err != nil { h.log.Info("failed to trigger cluster update workflow, %v", err) @@ -252,21 +251,18 @@ func (h *ClusterClaimSyncHandler) triggerClusterUpdates(clusterName, managedClus return err } - ci := model.CrossplaneClusterUpdate{RepoURL: proj.GitProjectUrl, GitProjectId: proj.GitProjectId, Name: clusterName, ManagedClusterId: managedClusterID} + ci := model.CrossplaneClusterUpdate{RepoURL: proj.GitProjectUrl, GitProjectId: proj.GitProjectId, + ManagedClusterName: clusterName, ManagedClusterId: managedClusterID} wd := workers.NewConfig(h.tc, h.log) _, err = wd.SendEvent(context.TODO(), &model.ConfigureParameters{Resource: model.CrossPlaneResource, Action: model.CrossPlaneClusterUpdate}, ci) return err } -func getClusterClaimStatus(conditions []model.ClusterClaimCondition) (nodePoolStatus, controlPlaneStatus, readyStatus string) { +func (h *ClusterClaimSyncHandler) getClusterClaimStatus(conditions []model.ClusterClaimCondition) (readyStatus string) { for _, condition := range conditions { switch strings.ToLower(condition.Type) { case readyStatusType: readyStatus = condition.Status - case nodePoolStatusType: - nodePoolStatus = condition.Status - case controlPlaneStatusType: - controlPlaneStatus = condition.Status } } return diff --git a/capten/common-pkg/plugins/argocd/clusters.go b/capten/common-pkg/plugins/argocd/clusters.go index bd904a9e1..b5c0aac4f 100644 --- a/capten/common-pkg/plugins/argocd/clusters.go +++ b/capten/common-pkg/plugins/argocd/clusters.go @@ -2,14 +2,13 @@ package argocd import ( "context" - "encoding/base64" "fmt" "strings" "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/argoproj/argo-cd/v2/util/io" - "gopkg.in/yaml.v2" + "k8s.io/client-go/tools/clientcmd" k8sapi "k8s.io/client-go/tools/clientcmd/api" ) @@ -18,29 +17,17 @@ const ( CredIdentifier = "kubeconfig" ) -func parseKubeconfigString(kubeconfigString string) (*k8sapi.Config, error) { - config := &k8sapi.Config{} - err := yaml.Unmarshal([]byte(kubeconfigString), config) - if err != nil { - return nil, err - } - return config, nil -} - func (a *ArgoCDClient) CreateOrUpdateCluster(ctx context.Context, clusterName, kubeconfigData string) error { - kubeConfig, err := parseKubeconfigString(kubeconfigData) + a.logger.Infof("Cluster create or update request for cluster %s", clusterName) + kubeConfig, err := clientcmd.Load([]byte(kubeconfigData)) if err != nil { - return err + return fmt.Errorf("kubeconfig parse failed, %v", err) } clusterData, ok := kubeConfig.Clusters[clusterName] if !ok { return fmt.Errorf("cluster %s not found in kubeconfig", clusterName) } - caData, err := base64.StdEncoding.DecodeString(string(clusterData.CertificateAuthorityData)) - if err != nil { - return err - } var clusterCAuthInfo *k8sapi.AuthInfo for _, authInfo := range kubeConfig.AuthInfos { @@ -52,23 +39,6 @@ func (a *ArgoCDClient) CreateOrUpdateCluster(ctx context.Context, clusterName, k return fmt.Errorf("auth info not found for cluster") } - var clientCertData []byte - if len(clusterCAuthInfo.ClientCertificateData) != 0 { - clientCertData, err = base64.StdEncoding.DecodeString(string(clusterCAuthInfo.ClientCertificateData)) - if err != nil { - return err - } - } - - a.logger.Infof("Cluster create or update request for cluster %s", clusterName) - var clientKeyData []byte - if len(clusterCAuthInfo.ClientKeyData) != 0 { - clientKeyData, err = base64.StdEncoding.DecodeString(string(clusterCAuthInfo.ClientKeyData)) - if err != nil { - return err - } - } - conn, appClient, err := a.client.NewClusterClient() if err != nil { return fmt.Errorf("failed to create argocd cluster client, %v", err) @@ -85,16 +55,16 @@ func (a *ArgoCDClient) CreateOrUpdateCluster(ctx context.Context, clusterName, k Username: clusterCAuthInfo.Username, Password: clusterCAuthInfo.Password, TLSClientConfig: v1alpha1.TLSClientConfig{ - ServerName: clusterData.Server, - CAData: caData, - CertData: clientCertData, - KeyData: clientKeyData, + ServerName: "kubernetes", + CAData: clusterData.CertificateAuthorityData, + CertData: clusterCAuthInfo.ClientCertificateData, + KeyData: clusterCAuthInfo.ClientKeyData, }, }, }, }) if err != nil { - if strings.Contains(err.Error(), "already exists") { + if strings.Contains(err.Error(), "already exists") || strings.Contains(err.Error(), "use upsert flag to force update") { update = true } return fmt.Errorf("failed to create cluster %s, %v", clusterName, err) @@ -110,10 +80,10 @@ func (a *ArgoCDClient) CreateOrUpdateCluster(ctx context.Context, clusterName, k Username: clusterCAuthInfo.Username, Password: clusterCAuthInfo.Password, TLSClientConfig: v1alpha1.TLSClientConfig{ - ServerName: clusterData.Server, - CAData: caData, - CertData: clientCertData, - KeyData: clientKeyData, + ServerName: "kubernetes", + CAData: clusterData.CertificateAuthorityData, + CertData: clusterCAuthInfo.ClientCertificateData, + KeyData: clusterCAuthInfo.ClientKeyData, }, }, }, diff --git a/capten/config-worker/internal/crossplane/config_cluster_updates.go b/capten/config-worker/internal/crossplane/config_cluster_updates.go index dc9dcfc1a..37c10d46d 100644 --- a/capten/config-worker/internal/crossplane/config_cluster_updates.go +++ b/capten/config-worker/internal/crossplane/config_cluster_updates.go @@ -43,7 +43,7 @@ func getAppNameNamespace(ctx context.Context, fileName string) (string, string, func (cp *CrossPlaneApp) configureClusterUpdate(ctx context.Context, req *model.CrossplaneClusterUpdate) (status string, err error) { logger.Infof("configuring the cluster endpoint for %s", req.RepoURL) - endpoint, err := cp.helper.CreateCluster(ctx, req.ManagedClusterId, req.Name) + endpoint, err := cp.helper.CreateCluster(ctx, req.ManagedClusterId, req.ManagedClusterName) if err != nil { return string(agentmodel.WorkFlowStatusFailed), errors.WithMessage(err, "failed to CreateCluster in argocd app") } @@ -64,9 +64,8 @@ func (cp *CrossPlaneApp) configureClusterUpdate(ctx context.Context, req *model. defer os.RemoveAll(templateRepo) defer os.RemoveAll(customerRepo) - fileName := filepath.Join(customerRepo, cp.pluginConfig.ClusterEndpointUpdates.File) - // replace cluster endpoint - err = updateClusterEndpointDetials(fileName, req.Name, endpoint, cp.cfg.ClusterDefaultAppsFile) + clusterValuesFile := filepath.Join(customerRepo, cp.pluginConfig.ClusterEndpointUpdates.ClusterValuesFile) + err = updateClusterEndpointDetials(clusterValuesFile, req.ManagedClusterName, endpoint, cp.cfg.ClusterDefaultAppsFile) if err != nil { return string(agentmodel.WorkFlowStatusFailed), errors.WithMessage(err, "failed to replace the file") } @@ -96,8 +95,8 @@ func (cp *CrossPlaneApp) configureClusterUpdate(ctx context.Context, req *model. return string(agentmodel.WorkFlowStatusCompleted), nil } -func updateClusterEndpointDetials(filename, clusterName, clusterEndpoint, defaultAppFile string) error { - data, err := os.ReadFile(filename) +func updateClusterEndpointDetials(valuesFileName, clusterName, clusterEndpoint, defaultAppFile string) error { + data, err := os.ReadFile(valuesFileName) if err != nil { return err } @@ -108,35 +107,31 @@ func updateClusterEndpointDetials(filename, clusterName, clusterEndpoint, defaul } var argoCDAppValue ArgoCDAppValue - err = json.Unmarshal(jsonData, &argoCDAppValue) if err != nil { return err } + defaultApps, err := readClusterDefaultApps(defaultAppFile) + if err != nil { + return err + } + + var found bool clusters := *argoCDAppValue.Clusters for index := range clusters { - cluster := &clusters[index] - if cluster.Name == clusterName { - defaultApps, err := readClusterDefaultApps(defaultAppFile) - if err != nil { - return err - } - - for index := range defaultApps { - localObj := &defaultApps[index] - strings.ReplaceAll(localObj.ValuesPath, clusterNameSub, clusterName) - } - - logger.Infof("udpated the req endpoint details to %s for name %s ", clusterEndpoint, clusterName) - cluster.Server = clusterEndpoint - + if clusters[index].Name == clusterName { + clusters[index] = prepareClusterData(clusterName, clusterEndpoint, defaultApps) + found = true break } } - argoCDAppValue.Clusters = &clusters + if !found { + clusters = append(clusters, prepareClusterData(clusterName, clusterEndpoint, defaultApps)) + } + argoCDAppValue.Clusters = &clusters jsonBytes, err := json.Marshal(argoCDAppValue) if err != nil { return err @@ -147,7 +142,33 @@ func updateClusterEndpointDetials(filename, clusterName, clusterEndpoint, defaul return err } - err = os.WriteFile(filename, yamlBytes, os.ModeAppend) - + err = os.WriteFile(valuesFileName, yamlBytes, os.ModeAppend) return err } + +func prepareClusterData(clusterName, endpoint string, defaultApps []DefaultApps) Cluster { + for index := range defaultApps { + localObj := &defaultApps[index] + strings.ReplaceAll(localObj.ValuesPath, clusterNameSub, clusterName) + } + + return Cluster{ + Name: clusterName, + Server: endpoint, + DefApps: defaultApps, + } +} + +func readClusterDefaultApps(clusterDefaultApp string) ([]DefaultApps, error) { + data, err := os.ReadFile(filepath.Clean(clusterDefaultApp)) + if err != nil { + return nil, fmt.Errorf("failed to read clusterDefaultApp File: %s, err: %w", clusterDefaultApp, err) + } + + var defaultApps []DefaultApps + err = json.Unmarshal(data, &defaultApps) + if err != nil { + return nil, fmt.Errorf("%w", err) + } + return defaultApps, nil +} diff --git a/capten/config-worker/internal/crossplane/config_crossplane_app.go b/capten/config-worker/internal/crossplane/config_crossplane_app.go index 054f0e84e..6abbf2fc1 100644 --- a/capten/config-worker/internal/crossplane/config_crossplane_app.go +++ b/capten/config-worker/internal/crossplane/config_crossplane_app.go @@ -65,20 +65,6 @@ func readCrossPlanePluginConfig(pluginFile string) (*crossplanePluginConfig, err return &pluginData, nil } -func readClusterDefaultApps(clusterDefaultApp string) ([]DefaultApps, error) { - data, err := os.ReadFile(filepath.Clean(clusterDefaultApp)) - if err != nil { - return nil, fmt.Errorf("failed to read clusterDefaultApp File: %s, err: %w", clusterDefaultApp, err) - } - - var defaultApps []DefaultApps - err = json.Unmarshal(data, &defaultApps) - if err != nil { - return nil, fmt.Errorf("%w", err) - } - return defaultApps, nil -} - func (cp *CrossPlaneApp) configureProjectAndApps(ctx context.Context, req *model.CrossplaneUseCase) (status string, err error) { accessToken, err := cp.helper.GetAccessToken(ctx, req.VaultCredIdentifier) if err != nil { diff --git a/capten/config-worker/internal/crossplane/types.go b/capten/config-worker/internal/crossplane/types.go index de2fae36b..60dbdaf73 100644 --- a/capten/config-worker/internal/crossplane/types.go +++ b/capten/config-worker/internal/crossplane/types.go @@ -6,18 +6,18 @@ type appConfig struct { SynchApp bool `json:"synchApp"` } -type clusterConfig struct { - MainAppGitPath string `json:"mainAppGitPath"` - File string `json:"file"` +type clusterUpdateConfig struct { + MainAppGitPath string `json:"mainAppGitPath"` + ClusterValuesFile string `json:"clusterValuesFile"` } type crossplanePluginConfig struct { - TemplateGitRepo string `json:"templateGitRepo"` - CrossplaneConfigSyncPath string `json:"crossplaneConfigSyncPath"` - ProviderConfigSyncPath string `json:"providerConfigSyncPath"` - ProviderPackages map[string]string `json:"providerPackages"` - ArgoCDApps []appConfig `json:"argoCDApps"` - ClusterEndpointUpdates clusterConfig `json:"clusterEndpointUpdates"` + TemplateGitRepo string `json:"templateGitRepo"` + CrossplaneConfigSyncPath string `json:"crossplaneConfigSyncPath"` + ProviderConfigSyncPath string `json:"providerConfigSyncPath"` + ProviderPackages map[string]string `json:"providerPackages"` + ArgoCDApps []appConfig `json:"argoCDApps"` + ClusterEndpointUpdates clusterUpdateConfig `json:"clusterUpdateConfig"` } const ( diff --git a/capten/model/config_workflow_types.go b/capten/model/config_workflow_types.go index c45a2d12d..604121f93 100644 --- a/capten/model/config_workflow_types.go +++ b/capten/model/config_workflow_types.go @@ -31,8 +31,8 @@ type CrossplaneUseCase struct { } type CrossplaneClusterUpdate struct { - Name string `json:"name,omitempty"` - GitProjectId string `json:"gitProjectId,omitempty"` - ManagedClusterId string `json:"managedClusterId,omitempty"` - RepoURL string `json:"repoURL,omitempty"` + ManagedClusterName string `json:"managedClusterName,omitempty"` + ManagedClusterId string `json:"managedClusterId,omitempty"` + GitProjectId string `json:"gitProjectId,omitempty"` + RepoURL string `json:"repoURL,omitempty"` } diff --git a/capten/model/crossplane_types.go b/capten/model/crossplane_types.go index abf33c27a..b6a519f53 100644 --- a/capten/model/crossplane_types.go +++ b/capten/model/crossplane_types.go @@ -97,7 +97,9 @@ type ClusterClaimCondition struct { } type ClusterClaimStatus struct { - Conditions []ClusterClaimCondition `json:"conditions,omitempty" protobuf:"bytes,1,opt,name=conditions"` + Conditions []ClusterClaimCondition `json:"conditions,omitempty" protobuf:"bytes,1,opt,name=conditions"` + ControlPlaneStatus string `json:"controlPlaneStatus,omitempty"` + NodePoolStatus string `json:"nodePoolStatus,omitempty"` } type ClusterClaim struct { diff --git a/charts/kad/crossplane_plugin_config.json b/charts/kad/crossplane_plugin_config.json index e7c7276b5..dbfddab2c 100644 --- a/charts/kad/crossplane_plugin_config.json +++ b/charts/kad/crossplane_plugin_config.json @@ -6,9 +6,9 @@ "aws": "xpkg.upbound.io/crossplane-contrib/provider-aws:v0.33.0", "gcp": "xpkg.upbound.io/crossplane-contrib/provider-gcp:v0.22.0" }, - "clusterEndpointUpdates":{ + "clusterUpdateConfig":{ "mainAppGitPath": "infra/crossplane/crossplane-main-app.yaml", - "file": "infra/clusters/argocd-apps/values.yaml" + "clusterValuesFile": "infra/clusters/argocd-apps/values.yaml" }, "argoCDApps": [ {