diff --git a/cyclops-ctrl/api/v1alpha1/client/modules.go b/cyclops-ctrl/api/v1alpha1/client/modules.go index aea5788c..502cb3d5 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 247b2173..1ce32adf 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 9ec83434..b6605b6b 100644 --- a/cyclops-ctrl/internal/cluster/k8sclient/modules.go +++ b/cyclops-ctrl/internal/cluster/k8sclient/modules.go @@ -32,28 +32,28 @@ 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) apiResources, err := k.clientset.Discovery().ServerPreferredResources() diff --git a/cyclops-ctrl/internal/controller/modules.go b/cyclops-ctrl/internal/controller/modules.go index e4398a22..d05cad41 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 862d15aa..eaf2fec5 100644 --- a/cyclops-ctrl/internal/handler/handler.go +++ b/cyclops-ctrl/internal/handler/handler.go @@ -63,18 +63,19 @@ func (h *Handler) Start() error { h.router.DELETE("/templates/store/:name", templatesController.DeleteTemplatesStore) // 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 c6c3e804..6dcae2cc 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 89ec1108..9ce81d73 100644 --- a/cyclops-ctrl/internal/modulecontroller/module_controller.go +++ b/cyclops-ctrl/internal/modulecontroller/module_controller.go @@ -92,7 +92,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 @@ -139,7 +139,7 @@ func (r *ModuleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr return ctrl.Result{}, err } - installErrors, err := r.moduleToResources(req.Name, template) + installErrors, err := r.moduleToResources(req.Name, req.Namespace, template) if err != nil { r.logger.Error(err, "error on upsert module", "namespaced name", req.NamespacedName) @@ -172,13 +172,13 @@ func (r *ModuleReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -func (r *ModuleReconciler) moduleToResources(name string, template *models.Template) ([]string, error) { - module, err := r.kubernetesClient.GetModule(name) +func (r *ModuleReconciler) moduleToResources(name, namespace string, template *models.Template) ([]string, error) { + module, err := r.kubernetesClient.GetModule(name, namespace) if err != nil { return nil, err } - installErrors, err := r.generateResources(r.kubernetesClient, *module, template) + installErrors, err := r.generateResources(r.kubernetesClient, *module, template, namespace) if err != nil { return nil, err } @@ -186,7 +186,7 @@ func (r *ModuleReconciler) moduleToResources(name string, template *models.Templ return installErrors, nil } -func (r *ModuleReconciler) generateResources(kClient *k8sclient.KubernetesClient, module cyclopsv1alpha1.Module, moduleTemplate *models.Template) ([]string, error) { +func (r *ModuleReconciler) generateResources(kClient *k8sclient.KubernetesClient, module cyclopsv1alpha1.Module, moduleTemplate *models.Template, namespace string) ([]string, error) { out, err := r.renderer.HelmTemplate(module, moduleTemplate) if err != nil { return nil, err @@ -233,6 +233,9 @@ func (r *ModuleReconciler) generateResources(kClient *k8sclient.KubernetesClient if labels == nil { labels = make(map[string]string) } + if obj.GetNamespace() == "" { + obj.SetNamespace(namespace) + } labels["app.kubernetes.io/managed-by"] = "cyclops" labels["cyclops.module"] = module.Name diff --git a/cyclops-ui/src/components/pages/EditModule.tsx b/cyclops-ui/src/components/pages/EditModule.tsx index 4801cabf..7bc90b75 100644 --- a/cyclops-ui/src/components/pages/EditModule.tsx +++ b/cyclops-ui/src/components/pages/EditModule.tsx @@ -66,13 +66,14 @@ const layout = { interface module { name: string; + namespace: string; values: any; template: templateRef; } - const EditModule = () => { const [module, setModule] = useState({ name: "", + namespace: "", values: {}, template: { repo: "", @@ -137,6 +138,7 @@ const EditModule = () => { const history = useNavigate(); let { moduleName } = useParams(); + let { moduleNamespace } = useParams(); const mapsToArray = (fields: any[], values: any): any => { let out: any = {}; @@ -207,7 +209,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, @@ -238,6 +240,7 @@ const EditModule = () => { setModule({ name: res.data.name, + namespace: res.data.namespace, values: values, template: res.data.template, }); @@ -384,10 +387,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)); @@ -957,7 +961,9 @@ const EditModule = () => { {" "} diff --git a/cyclops-ui/src/components/pages/History.tsx b/cyclops-ui/src/components/pages/History.tsx index d1a19971..a42cfcd1 100644 --- a/cyclops-ui/src/components/pages/History.tsx +++ b/cyclops-ui/src/components/pages/History.tsx @@ -33,18 +33,30 @@ 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); - setHistoryEntries(res.data); - }); + axios + .get(`/api/modules/` + moduleNamespace + "/" + moduleName + `/history`) + .then((res) => { + console.log(res.data); + setHistoryEntries(res.data); + }); - axios.get(`/api/modules/` + moduleName + `/currentManifest`).then((res) => { - setDiff({ - curr: res.data, - previous: diff.previous, + axios + .get( + `/api/modules/` + + moduleNamespace + + "/" + + moduleName + + `/currentManifest`, + ) + .then((res) => { + setDiff({ + curr: res.data, + previous: diff.previous, + }); }); - }); }, []); const handleOk = () => { @@ -64,10 +76,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); @@ -105,10 +118,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, @@ -134,10 +150,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); }) @@ -267,7 +286,9 @@ const ModuleHistory = () => { diff --git a/cyclops-ui/src/components/pages/ModuleDetails.tsx b/cyclops-ui/src/components/pages/ModuleDetails.tsx index b339e565..b59110bd 100644 --- a/cyclops-ui/src/components/pages/ModuleDetails.tsx +++ b/cyclops-ui/src/components/pages/ModuleDetails.tsx @@ -139,6 +139,7 @@ const ModuleDetails = () => { }); let { moduleName } = useParams(); + let { moduleNamespace } = useParams(); function fetchManifest( group: string, @@ -172,7 +173,7 @@ const ModuleDetails = () => { function fetchModule() { axios - .get(`/api/modules/` + moduleName) + .get(`/api/modules/` + moduleNamespace + "/" + moduleName) .then((res) => { setModule(res.data); setLoadModule(true); @@ -186,7 +187,7 @@ const ModuleDetails = () => { function fetchModuleResources() { axios - .get(`/api/modules/` + moduleName + `/resources`) + .get(`/api/modules/` + moduleNamespace + `/` + moduleName + `/resources`) .then((res) => { setResources(res.data); setLoadResources(true); @@ -261,7 +262,7 @@ const ModuleDetails = () => { const deleteDeployment = () => { axios - .delete(`/api/modules/` + moduleName) + .delete(`/api/modules/` + moduleNamespace + "/" + moduleName) .then(() => { window.location.href = "/modules"; }) @@ -639,15 +640,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); @@ -731,7 +735,8 @@ const ModuleDetails = () => {