diff --git a/controllers/acc_controller.go b/controllers/acc_controller.go index fd0e64f08..9afccf874 100644 --- a/controllers/acc_controller.go +++ b/controllers/acc_controller.go @@ -438,6 +438,7 @@ func applyAccConfigVersionAnnotations(ctx context.Context, instance *csmv1.ApexC // DeployApexConnectivityClient - perform deployment func DeployApexConnectivityClient(ctx context.Context, isDeleting bool, operatorConfig utils.OperatorConfig, cr csmv1.ApexConnectivityClient, ctrlClient crclient.Client) error { + log := logger.GetLogger(ctx) YamlString := "" ModifiedYamlString := "" deploymentPath := fmt.Sprintf("%s/clientconfig/%s/%s/%s", operatorConfig.ConfigDirectory, csmv1.DreadnoughtClient, cr.Spec.Client.ConfigVersion, AccManifest) @@ -465,6 +466,24 @@ func DeployApexConnectivityClient(ctx context.Context, isDeleting bool, operator } } + //If existing csm-installations are found, proceed to get those namespaces and create roles/rolebindings + csmList := &csmv1.ContainerStorageModuleList{} + err = ctrlClient.List(ctx, csmList) + if err == nil && len(csmList.Items) > 0 { + log.Info("Found existing csm installations. Proceeding to onboard them to Apex Navigator for Kubernetes") + BrownfieldCR := "brownfield-onboard.yaml" + + brownfieldManifestFilePath := fmt.Sprintf("%s/clientconfig/%s/%s/%s", operatorConfig.ConfigDirectory, csmv1.DreadnoughtClient, cr.Spec.Client.ConfigVersion, BrownfieldCR) + if isDeleting { + if err = utils.BrownfieldOnboard(ctx, brownfieldManifestFilePath, cr, ctrlClient, true); err != nil { + log.Error(err, "brownfield cluster onboarding failed") + } + } else { + if err = utils.BrownfieldOnboard(ctx, brownfieldManifestFilePath, cr, ctrlClient, false); err != nil { + log.Error(err, "brownfield cluster onboarding failed") + } + } + } return nil } diff --git a/controllers/csm_controller.go b/controllers/csm_controller.go index dd2f76010..8b8628a1d 100644 --- a/controllers/csm_controller.go +++ b/controllers/csm_controller.go @@ -272,6 +272,14 @@ func (r *ContainerStorageModuleReconciler) Reconcile(ctx context.Context, req ct if csm.IsBeingDeleted() { log.Infow("Delete request", "csm", req.Namespace, "Name", req.Name) + //remove role/rolebinding from the csm object namespace + err := r.SyncRbac(ctx, *csm, *operatorConfig, r.Client) + if err != nil { + r.EventRecorder.Event(csm, corev1.EventTypeWarning, csmv1.EventDeleted, fmt.Sprintf("Failed to sync rbac: %s", err)) + log.Errorw("sync rbac", "error", err.Error()) + return ctrl.Result{}, fmt.Errorf("error when syncing rbac: %v", err) + } + // check for force cleanup if csm.Spec.Driver.ForceRemoveDriver { // remove all resources deployed from CR by operator @@ -879,6 +887,26 @@ func (r *ContainerStorageModuleReconciler) SyncCSM(ctx context.Context, cr csmv1 } } + //If dell connectivity client is deployed, create role/rolebindings in the csm namespaces + list := &csmv1.ApexConnectivityClientList{} + if err := ctrlClient.List(ctx, list); err != nil { + log.Info("dell connectivity client not found") + return nil + } else if len(list.Items) <= 0 { + log.Info("dell connectivity client not found") + return nil + } else { + log.Info("dell connectivity client found") + cr := new(csmv1.ApexConnectivityClient) + BrownfieldCR := "brownfield-onboard.yaml" + configVersion1 := list.Items[0].Spec.Client.ConfigVersion + brownfieldManifestFilePath := fmt.Sprintf("%s/clientconfig/%s/%s/%s", operatorConfig.ConfigDirectory, csmv1.DreadnoughtClient, configVersion1, BrownfieldCR) + + if err = utils.BrownfieldOnboard(ctx, brownfieldManifestFilePath, *cr, ctrlClient, false); err != nil { + log.Error(err, "error creating role/rolebindings to newly discovered csm namespace") + return err + } + } return nil } @@ -1419,6 +1447,32 @@ func applyConfigVersionAnnotations(ctx context.Context, instance *csmv1.Containe return false } +// SyncRbac - Delete the role/rolebindings in the csm namespaces +func (r *ContainerStorageModuleReconciler) SyncRbac(ctx context.Context, cr csmv1.ContainerStorageModule, operatorConfig utils.OperatorConfig, ctrlClient client.Client) error { + log := logger.GetLogger(ctx) + //If dell connectivity client is deployed, create role/rolebindings in the csm namespaces + list := &csmv1.ApexConnectivityClientList{} + if err := ctrlClient.List(ctx, list); err != nil { + log.Info("dell connectivity client not found") + return nil + } else if len(list.Items) <= 0 { + log.Info("dell connectivity client not found") + return nil + } else { + log.Info("dell connectivity client found") + cr := new(csmv1.ApexConnectivityClient) + BrownfieldCR := "brownfield-onboard.yaml" + configVersion1 := list.Items[0].Spec.Client.ConfigVersion + brownfieldManifestFilePath := fmt.Sprintf("%s/clientconfig/%s/%s/%s", operatorConfig.ConfigDirectory, csmv1.DreadnoughtClient, configVersion1, BrownfieldCR) + + if err = utils.BrownfieldOnboard(ctx, brownfieldManifestFilePath, *cr, ctrlClient, true); err != nil { + log.Error(err, "error deleting role/rolebindings to newly discovered csm namespace") + return err + } + } + return nil +} + // GetClient - returns the split client func (r *ContainerStorageModuleReconciler) GetClient() client.Client { return r.Client diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1cfbeb70e..fdfe0ae43 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -139,6 +139,10 @@ const ( PodmonNodeComponent = "podmon-node" // ApplicationMobilityNamespace - application-mobility ApplicationMobilityNamespace = "application-mobility" + // ExistingNamespace - BrownfieldNamespace + ExistingNamespace = "" + // ClientNamespace - acc-client-namespace + ClientNamespace = "" ) // SplitYaml divides a big bytes of yaml files in individual yaml files. @@ -1202,7 +1206,8 @@ func getUpgradeInfo[T csmv1.CSMComponentType](ctx context.Context, operatorConfi return upgradePath.MinUpgradePath, nil } -func getNamespaces(ctx context.Context, ctrlClient crclient.Client) ([]string, error) { +// GetNamespaces - get all namespaces +func GetNamespaces(ctx context.Context, ctrlClient crclient.Client) ([]string, error) { // Set to store unique namespaces namespaceMap := make(map[string]struct{}) @@ -1223,3 +1228,48 @@ func getNamespaces(ctx context.Context, ctrlClient crclient.Client) ([]string, e return namespaces, nil } + +// BrownfieldOnboard - brownfield onboarding +func BrownfieldOnboard(ctx context.Context, path string, cr csmv1.ApexConnectivityClient, ctrlClient crclient.Client, isDeleting bool) error { + log := logger.GetLogger(ctx) + + namespace, err := GetNamespaces(ctx, ctrlClient) + if err != nil { + log.Error(err, "Failed to get namespaces") + return err + } + + buf, err := os.ReadFile(filepath.Clean(path)) + if err != nil { + log.Error(err, "Failed to read manifest file") + return err + } + + yamlFile := string(buf) + + for _, ns := range namespace { + + yamlFile := strings.ReplaceAll(yamlFile, ExistingNamespace, ns) + yamlFile = strings.ReplaceAll(yamlFile, ClientNamespace, cr.Namespace) + + deployObjects, err := GetModuleComponentObj([]byte(yamlFile)) + if err != nil { + return err + } + + for _, ctrlObj := range deployObjects { + if isDeleting { + err := DeleteObject(ctx, ctrlObj, ctrlClient) + if err != nil { + return err + } + } else { + err := ApplyObject(ctx, ctrlObj, ctrlClient) + if err != nil { + return err + } + } + } + } + return nil +} \ No newline at end of file