From db95630c256d91b21685a8e38821ce5cdf6b117e Mon Sep 17 00:00:00 2001 From: Hanshal Mehta <122217807+hanshal101@users.noreply.github.com> Date: Mon, 8 Jul 2024 23:42:47 +0530 Subject: [PATCH] feat: deploy modules to different namespaces Signed-off-by: hanshal101 <82961842+hanshal101@users.noreply.github.com> --- cyclops-ctrl/api/v1alpha1/client/modules.go | 1 - .../samples/cyclops_v1alpha1_module.yaml | 1 + .../internal/cluster/k8sclient/modules.go | 18 +++---- cyclops-ctrl/internal/controller/modules.go | 18 +++---- cyclops-ctrl/internal/handler/handler.go | 20 ++++---- cyclops-ctrl/internal/mapper/modules.go | 3 +- .../modulecontroller/module_controller.go | 15 ++++-- .../src/components/pages/EditModule.tsx | 13 +++-- cyclops-ui/src/components/pages/History.tsx | 31 +++++++---- .../src/components/pages/ModuleDetails.tsx | 30 ++++++----- .../src/components/pages/Modules/Modules.tsx | 2 +- cyclops-ui/src/components/pages/NewModule.tsx | 51 ++++++++++++++++++- cyclops-ui/src/routes/PathConstants.tsx | 6 +-- 13 files changed, 143 insertions(+), 66 deletions(-) diff --git a/cyclops-ctrl/api/v1alpha1/client/modules.go b/cyclops-ctrl/api/v1alpha1/client/modules.go index aea5788cf..502cb3d59 100644 --- a/cyclops-ctrl/api/v1alpha1/client/modules.go +++ b/cyclops-ctrl/api/v1alpha1/client/modules.go @@ -30,7 +30,6 @@ func (c *moduleClient) List(opts metav1.ListOptions) ([]cyclopsv1alpha1.Module, result := cyclopsv1alpha1.ModuleList{} err := c.restClient. Get(). - Namespace(c.ns). Resource("modules"). Do(context.Background()). Into(&result) diff --git a/cyclops-ctrl/config/samples/cyclops_v1alpha1_module.yaml b/cyclops-ctrl/config/samples/cyclops_v1alpha1_module.yaml index 247b2173a..1ce32adf2 100644 --- a/cyclops-ctrl/config/samples/cyclops_v1alpha1_module.yaml +++ b/cyclops-ctrl/config/samples/cyclops_v1alpha1_module.yaml @@ -8,5 +8,6 @@ metadata: app.kubernetes.io/managed-by: kustomize app.kubernetes.io/created-by: kubebuilder name: module-sample + namespace: desired-namespace # else it will be default spec: # TODO(user): Add fields here diff --git a/cyclops-ctrl/internal/cluster/k8sclient/modules.go b/cyclops-ctrl/internal/cluster/k8sclient/modules.go index d160b161d..83a06ddff 100644 --- a/cyclops-ctrl/internal/cluster/k8sclient/modules.go +++ b/cyclops-ctrl/internal/cluster/k8sclient/modules.go @@ -32,31 +32,31 @@ func (k *KubernetesClient) ListModules() ([]cyclopsv1alpha1.Module, error) { } func (k *KubernetesClient) CreateModule(module cyclopsv1alpha1.Module) error { - _, err := k.moduleset.Modules(cyclopsNamespace).Create(&module) + _, err := k.moduleset.Modules(module.Namespace).Create(&module) return err } func (k *KubernetesClient) UpdateModule(module *cyclopsv1alpha1.Module) error { - _, err := k.moduleset.Modules(cyclopsNamespace).Update(module) + _, err := k.moduleset.Modules(module.Namespace).Update(module) return err } func (k *KubernetesClient) UpdateModuleStatus(module *cyclopsv1alpha1.Module) (*cyclopsv1alpha1.Module, error) { - return k.moduleset.Modules(cyclopsNamespace).UpdateSubresource(module, "status") + return k.moduleset.Modules(module.Namespace).UpdateSubresource(module, "status") } -func (k *KubernetesClient) DeleteModule(name string) error { - return k.moduleset.Modules(cyclopsNamespace).Delete(name) +func (k *KubernetesClient) DeleteModule(name, namespace string) error { + return k.moduleset.Modules(namespace).Delete(name) } -func (k *KubernetesClient) GetModule(name string) (*cyclopsv1alpha1.Module, error) { - return k.moduleset.Modules(cyclopsNamespace).Get(name) +func (k *KubernetesClient) GetModule(name, namespace string) (*cyclopsv1alpha1.Module, error) { + return k.moduleset.Modules(namespace).Get(name) } -func (k *KubernetesClient) GetResourcesForModule(name string) ([]dto.Resource, error) { +func (k *KubernetesClient) GetResourcesForModule(name, namespace string) ([]dto.Resource, error) { out := make([]dto.Resource, 0, 0) - module, err := k.GetModule(name) + module, err := k.GetModule(name, namespace) if err != nil { return nil, err } diff --git a/cyclops-ctrl/internal/controller/modules.go b/cyclops-ctrl/internal/controller/modules.go index e4398a229..d05cad419 100644 --- a/cyclops-ctrl/internal/controller/modules.go +++ b/cyclops-ctrl/internal/controller/modules.go @@ -45,7 +45,7 @@ func NewModulesController( func (m *Modules) GetModule(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.Status(http.StatusInternalServerError) @@ -91,7 +91,7 @@ func (m *Modules) ListModules(ctx *gin.Context) { func (m *Modules) DeleteModule(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - err := m.kubernetesClient.DeleteModule(ctx.Param("name")) + err := m.kubernetesClient.DeleteModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.JSON(http.StatusInternalServerError, dto.NewError("Error deleting module", err.Error())) @@ -105,7 +105,7 @@ func (m *Modules) DeleteModule(ctx *gin.Context) { func (m *Modules) GetModuleHistory(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.Status(http.StatusInternalServerError) @@ -161,7 +161,7 @@ func (m *Modules) Manifest(ctx *gin.Context) { func (m *Modules) CurrentManifest(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.Status(http.StatusInternalServerError) @@ -252,7 +252,7 @@ func (m *Modules) UpdateModule(ctx *gin.Context) { return } - curr, err := m.kubernetesClient.GetModule(request.Name) + curr, err := m.kubernetesClient.GetModule(request.Name, request.Namespace) if err != nil { fmt.Println(err) ctx.JSON(http.StatusInternalServerError, dto.NewError("Error fetching module", err.Error())) @@ -309,7 +309,7 @@ func (m *Modules) UpdateModule(ctx *gin.Context) { func (m *Modules) ResourcesForModule(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { ctx.JSON(http.StatusBadRequest, dto.NewError("Error mapping module request", err.Error())) return @@ -330,7 +330,7 @@ func (m *Modules) ResourcesForModule(ctx *gin.Context) { return } - resources, err := m.kubernetesClient.GetResourcesForModule(ctx.Param("name")) + resources, err := m.kubernetesClient.GetResourcesForModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.JSON(http.StatusInternalServerError, dto.NewError("Error fetching module resources", err.Error())) @@ -357,7 +357,7 @@ func (m *Modules) ResourcesForModule(ctx *gin.Context) { func (m *Modules) Template(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.JSON(http.StatusInternalServerError, dto.NewError("Error fetching module", err.Error())) @@ -411,7 +411,7 @@ func (m *Modules) Template(ctx *gin.Context) { func (m *Modules) HelmTemplate(ctx *gin.Context) { ctx.Header("Access-Control-Allow-Origin", "*") - module, err := m.kubernetesClient.GetModule(ctx.Param("name")) + module, err := m.kubernetesClient.GetModule(ctx.Param("name"), ctx.Param("namespace")) if err != nil { fmt.Println(err) ctx.JSON(http.StatusInternalServerError, dto.NewError("Error fetching module", err.Error())) diff --git a/cyclops-ctrl/internal/handler/handler.go b/cyclops-ctrl/internal/handler/handler.go index 862d15aa7..5c0ff5cfe 100644 --- a/cyclops-ctrl/internal/handler/handler.go +++ b/cyclops-ctrl/internal/handler/handler.go @@ -65,16 +65,16 @@ func (h *Handler) Start() error { // modules h.router.GET("/modules/:name", modulesController.GetModule) h.router.GET("/modules/list", modulesController.ListModules) - h.router.DELETE("/modules/:name", modulesController.DeleteModule) - h.router.POST("/modules/new", modulesController.CreateModule) - h.router.POST("/modules/update", modulesController.UpdateModule) - h.router.GET("/modules/:name/history", modulesController.GetModuleHistory) - h.router.POST("/modules/:name/manifest", modulesController.Manifest) - h.router.GET("/modules/:name/currentManifest", modulesController.CurrentManifest) - h.router.GET("/modules/:name/resources", modulesController.ResourcesForModule) - h.router.DELETE("/modules/:name/resources", modulesController.DeleteModuleResource) - h.router.GET("/modules/:name/template", modulesController.Template) - h.router.GET("/modules/:name/helm-template", modulesController.HelmTemplate) + h.router.GET("/modules/:namespace/:name", modulesController.GetModule) + h.router.GET("/modules/:namespace/:name/history", modulesController.GetModuleHistory) + h.router.POST("/modules/:namespace/:name/manifest", modulesController.Manifest) + h.router.GET("/modules/:namespace/:name/currentManifest", modulesController.CurrentManifest) + h.router.GET("/modules/:namespace/:name/resources", modulesController.ResourcesForModule) + h.router.DELETE("/modules/:namespace/:name", modulesController.DeleteModule) + h.router.DELETE("/modules/:namespace/:name/resources", modulesController.DeleteModuleResource) + h.router.GET("/modules/:namespace/:name/template", modulesController.Template) + h.router.GET("/modules/:namespace/:name/helm-template", modulesController.HelmTemplate) + //h.router.POST("/modules/resources", modulesController.ModuleToResources) h.router.GET("/resources/pods/:namespace/:name/:container/logs", modulesController.GetLogs) diff --git a/cyclops-ctrl/internal/mapper/modules.go b/cyclops-ctrl/internal/mapper/modules.go index a567cf211..61741598b 100644 --- a/cyclops-ctrl/internal/mapper/modules.go +++ b/cyclops-ctrl/internal/mapper/modules.go @@ -24,7 +24,8 @@ func RequestToModule(req dto.Module) (cyclopsv1alpha1.Module, error) { APIVersion: "cyclops-ui.com/v1alpha1", }, ObjectMeta: metav1.ObjectMeta{ - Name: req.Name, + Name: req.Name, + Namespace: req.Namespace, }, Spec: cyclopsv1alpha1.ModuleSpec{ TemplateRef: DtoTemplateRefToK8s(req.Template), diff --git a/cyclops-ctrl/internal/modulecontroller/module_controller.go b/cyclops-ctrl/internal/modulecontroller/module_controller.go index 3cbf70bc6..f4489a253 100644 --- a/cyclops-ctrl/internal/modulecontroller/module_controller.go +++ b/cyclops-ctrl/internal/modulecontroller/module_controller.go @@ -93,7 +93,7 @@ func (r *ModuleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr err := r.Get(ctx, req.NamespacedName, &module) if apierrors.IsNotFound(err) { r.logger.Info("delete module", "namespaced name", req.NamespacedName) - resources, err := r.kubernetesClient.GetResourcesForModule(req.Name) + resources, err := r.kubernetesClient.GetResourcesForModule(req.Name, req.Namespace) if err != nil { r.logger.Error(err, "error on get module resources", "namespaced name", req.NamespacedName) return ctrl.Result{}, err @@ -140,7 +140,7 @@ func (r *ModuleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr return ctrl.Result{}, err } - installErrors, childrenResources, err := r.moduleToResources(req.Name, template) + installErrors, childrenResources, err := r.moduleToResources(req.Name, req.Namespace, template) if err != nil { r.logger.Error(err, "error on upsert module", "namespaced name", req.NamespacedName) @@ -185,15 +185,15 @@ func (r *ModuleReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -func (r *ModuleReconciler) moduleToResources(name string, template *models.Template) ([]string, []cyclopsv1alpha1.GroupVersionResource, error) { - module, err := r.kubernetesClient.GetModule(name) +func (r *ModuleReconciler) moduleToResources(name, namespace string, template *models.Template) ([]string, []cyclopsv1alpha1.GroupVersionResource, error) { + module, err := r.kubernetesClient.GetModule(name, namespace) if err != nil { return nil, nil, err } crdInstallErrors := r.applyCRDs(template) - installErrors, childrenGVRs, err := r.generateResources(r.kubernetesClient, *module, template) + installErrors, childrenGVRs, err := r.generateResources(r.kubernetesClient, *module, template, namespace) if err != nil { return nil, nil, err } @@ -205,6 +205,7 @@ func (r *ModuleReconciler) generateResources( kClient *k8sclient.KubernetesClient, module cyclopsv1alpha1.Module, moduleTemplate *models.Template, + namespace string, ) ([]string, []cyclopsv1alpha1.GroupVersionResource, error) { out, err := r.renderer.HelmTemplate(module, moduleTemplate) if err != nil { @@ -232,6 +233,10 @@ func (r *ModuleReconciler) generateResources( fmt.Sprintf("%s/%s", obj.GetNamespace(), obj.GetName()), ) + if obj.GetNamespace() == "" { + obj.SetNamespace(namespace) + } + installErrors = append(installErrors, fmt.Sprintf( "%v%v/%v %v/%v failed to decode: %v", obj.GroupVersionKind().Group, diff --git a/cyclops-ui/src/components/pages/EditModule.tsx b/cyclops-ui/src/components/pages/EditModule.tsx index 289fa0419..1918c10d6 100644 --- a/cyclops-ui/src/components/pages/EditModule.tsx +++ b/cyclops-ui/src/components/pages/EditModule.tsx @@ -60,6 +60,7 @@ const layout = { interface module { name: string; + namespace: string, values: any; template: templateRef; } @@ -67,6 +68,7 @@ interface module { const EditModule = () => { const [module, setModule] = useState({ name: "", + namespace: "", values: {}, template: { repo: "", @@ -130,6 +132,7 @@ const EditModule = () => { const history = useNavigate(); let { moduleName } = useParams(); + let { moduleNamespace } = useParams(); const mapsToArray = useCallback((fields: any[], values: any): any => { let out: any = {}; @@ -216,7 +219,7 @@ const EditModule = () => { useEffect(() => { const fetchModuleData = async () => { axios - .get("/api/modules/" + moduleName) + .get("/api/modules/" + moduleNamespace + "/" + moduleName) .then(async (res) => { editTemplateForm.setFieldsValue({ repo: res.data.template.repo, @@ -247,6 +250,7 @@ const EditModule = () => { setModule({ name: res.data.name, + namespace: res.data.namespace, values: values, template: res.data.template, }); @@ -388,10 +392,11 @@ const EditModule = () => { .post(`/api/modules/update`, { values: values, name: module.name, + namespace: module.namespace, template: templateRef, }) .then((res) => { - window.location.href = "/modules/" + moduleName; + window.location.href = "/modules/" + moduleNamespace + "/" + moduleName; }) .catch((error) => { setError(mapResponseError(error)); @@ -1002,7 +1007,9 @@ const EditModule = () => { {" "} diff --git a/cyclops-ui/src/components/pages/History.tsx b/cyclops-ui/src/components/pages/History.tsx index 558915667..d4d011a08 100644 --- a/cyclops-ui/src/components/pages/History.tsx +++ b/cyclops-ui/src/components/pages/History.tsx @@ -32,6 +32,8 @@ const ModuleHistory = () => { const [historyEntries, setHistoryEntries] = useState([]); let { moduleName } = useParams(); + let { moduleNamespace } = useParams(); + useEffect(() => { axios.get(`/api/modules/` + moduleName + `/history`).then((res) => { console.log(res.data); @@ -63,10 +65,11 @@ const ModuleHistory = () => { .post(`/api/modules/update`, { values: target.values, name: moduleName, + namespace: moduleNamespace, template: target.template, }) .then((res) => { - window.location.href = "/modules/" + moduleName; + window.location.href = "/modules/" + moduleNamespace + "/" + moduleName; }) .catch((error) => { // setLoading(false); @@ -104,10 +107,13 @@ const ModuleHistory = () => { }); axios - .post("/api/modules/" + moduleName + "/manifest", { - template: target.template, - values: target.values, - }) + .post( + "/api/modules/" + moduleNamespace + "/" + moduleName + "/manifest", + { + template: target.template, + values: target.values, + }, + ) .then(function (res) { setDiff({ curr: diff.curr, @@ -133,10 +139,13 @@ const ModuleHistory = () => { }); axios - .post("/api/modules/" + moduleName + "/manifest", { - template: target.template, - values: target.values, - }) + .post( + "/api/modules/" + moduleNamespace + "/" + moduleName + "/manifest", + { + template: target.template, + values: target.values, + }, + ) .then(function (res) { setManifest(res.data); }) @@ -266,7 +275,9 @@ const ModuleHistory = () => { diff --git a/cyclops-ui/src/components/pages/ModuleDetails.tsx b/cyclops-ui/src/components/pages/ModuleDetails.tsx index e9efb258f..097ea520c 100644 --- a/cyclops-ui/src/components/pages/ModuleDetails.tsx +++ b/cyclops-ui/src/components/pages/ModuleDetails.tsx @@ -143,6 +143,7 @@ const ModuleDetails = () => { }); let { moduleName } = useParams(); + let { moduleNamespace } = useParams(); function fetchManifest( group: string, @@ -176,7 +177,7 @@ const ModuleDetails = () => { const fetchModuleResources = useCallback(() => { axios - .get(`/api/modules/` + moduleName + `/resources`) + .get(`/api/modules/` + moduleNamespace + `/` + moduleName + `/resources`) .then((res) => { setResources(res.data); setLoadResources(true); @@ -191,7 +192,7 @@ const ModuleDetails = () => { useEffect(() => { function fetchModule() { axios - .get(`/api/modules/` + moduleName) + .get(`/api/modules/` + moduleNamespace + "/" + moduleName) .then((res) => { setModule(res.data); setLoadModule(true); @@ -265,7 +266,7 @@ const ModuleDetails = () => { const deleteDeployment = () => { axios - .delete(`/api/modules/` + moduleName) + .delete(`/api/modules/` + moduleNamespace + "/" + moduleName) .then(() => { window.location.href = "/modules"; }) @@ -686,15 +687,18 @@ const ModuleDetails = () => { const deleteResource = () => { axios - .delete(`/api/modules/` + moduleName + `/resources`, { - data: { - group: deleteResourceRef.group, - version: deleteResourceRef.version, - kind: deleteResourceRef.kind, - name: deleteResourceRef.name, - namespace: deleteResourceRef.namespace, + .delete( + `/api/modules/` + moduleNamespace + "/" + moduleName + `/resources`, + { + data: { + group: deleteResourceRef.group, + version: deleteResourceRef.version, + kind: deleteResourceRef.kind, + name: deleteResourceRef.name, + namespace: deleteResourceRef.namespace, + }, }, - }) + ) .then(() => { setLoadResources(false); setDeleteResourceModal(false); @@ -778,7 +782,7 @@ const ModuleDetails = () => {