diff --git a/config/orchestrations/stack-controller/0.1/stack-controller-kabanero-triggers.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-kabanero-triggers.yaml new file mode 100644 index 00000000..3269be7c --- /dev/null +++ b/config/orchestrations/stack-controller/0.1/stack-controller-kabanero-triggers.yaml @@ -0,0 +1,42 @@ +# This role lets the stack controller create triggerbindings, +# triggertemplates and eventlisteners in the tekton-pipelines +# namespace, as required by the tekton dashboard webhooks +# extension. The Role was created during Kabanero install. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kabanero-trigger-role + namespace: tekton-pipelines +rules: +- apiGroups: + - tekton.dev + resources: + - triggerbindings + - triggertemplates + - eventlisteners + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +--- +# This rolebinding lets the stack controller create triggerbindings, +# triggertemplates and eventlisteners in the tekton-pipelines +# namespace, as required by the tekton dashboard webhooks +# extension. The Role was created during Kabanero install. +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .name }} + namespace: tekton-pipelines +subjects: +- kind: ServiceAccount + name: kabanero-operator-stack-controller + namespace: {{ .kabaneroNamespace }} +roleRef: + kind: Role + name: kabanero-trigger-role + apiGroup: rbac.authorization.k8s.io diff --git a/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace-manifests.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace-manifests.yaml new file mode 100644 index 00000000..963847fe --- /dev/null +++ b/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace-manifests.yaml @@ -0,0 +1,228 @@ +# ServiceAccount, Role & RoleBinding for stack-controller to create & piplines to be run +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kabanero-pipeline + namespace: {{ .pipelinesNamespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kabanero-pipeline-role + namespace: {{ .pipelinesNamespace }} +rules: +- apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - use +- apiGroups: + - "" + resources: + - serviceaccounts + verbs: + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - pods + - services + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - "" + resources: + - pods/log + - namespaces + - events + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - create + - delete + - update + - watch +- apiGroups: + - extensions + - apps + resources: + - deployments + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - tekton.dev + resources: + - tasks + - clustertasks + - taskruns + - pipelines + - pipelineruns + - pipelineresources + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - tekton.dev + resources: + - taskruns/finalizers + - pipelineruns/finalizers + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - tekton.dev + resources: + - tasks/status + - clustertasks/status + - taskruns/status + - pipelines/status + - pipelineruns/status + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - kabanero.io + resources: + - stacks + verbs: + - get + - list + - create + - update + - delete + - patch + - watch +- apiGroups: + - "" + - image.openshift.io + resources: + - imagestreams/layers + verbs: + - get + - update +- apiGroups: + - "" + - image.openshift.io + resources: + - imagestreams + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kabanero-pipeline-get-stack-role + namespace: {{ .kabaneroNamespace }} +rules: +- apiGroups: + - kabanero.io + resources: + - stacks + verbs: + - get + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kabanero-pipeline-role-binding + namespace: {{ .pipelinesNamespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kabanero-pipeline-role +subjects: +- kind: ServiceAccount + name: kabanero-pipeline + namespace: {{ .pipelinesNamespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: kabanero-pipeline-get-stack-role-binding + namespace: {{ .kabaneroNamespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: kabanero-pipeline-get-stack-role +subjects: +- kind: ServiceAccount + name: kabanero-pipeline + namespace: {{ .pipelinesNamespace }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: kabanero-operator-stack-controller-tekton + namespace: {{ .pipelinesNamespace }} +rules: +- apiGroups: + - tekton.dev + resources: + - conditions + - pipelines + - tasks + - triggerbindings + - triggertemplates + verbs: + - delete + - get + - create + - list + - update + - watch +--- +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kabanero-operator-stack-controller-tekton + namespace: {{ .pipelinesNamespace }} +subjects: +- kind: ServiceAccount + name: kabanero-operator-stack-controller + namespace: {{ .kabaneroNamespace }} +roleRef: + kind: Role + name: kabanero-operator-stack-controller + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace.yaml new file mode 100644 index 00000000..a860921e --- /dev/null +++ b/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace.yaml @@ -0,0 +1,5 @@ +# This namespace is created for tekton pipelineruns +apiVersion: v1 +kind: Namespace +metadata: + name: {{ .pipelinesNamespace }} diff --git a/config/orchestrations/stack-controller/0.1/stack-controller-tekton.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-tekton.yaml deleted file mode 100644 index 0325fc0f..00000000 --- a/config/orchestrations/stack-controller/0.1/stack-controller-tekton.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# This role lets the stack controller create triggerbindings, -# triggertemplates and eventlisteners in the tekton-pipelines -# namespace, as required by the tekton dashboard webhooks -# extension. The Role was created during Kabanero install. -kind: RoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: {{ .name }} - namespace: tekton-pipelines -subjects: -- kind: ServiceAccount - name: kabanero-operator-stack-controller - namespace: {{ .kabaneroNamespace }} -roleRef: - kind: Role - name: kabanero-trigger-role - apiGroup: rbac.authorization.k8s.io diff --git a/config/samples/full.yaml b/config/samples/full.yaml index a749dca2..e435018e 100644 --- a/config/samples/full.yaml +++ b/config/samples/full.yaml @@ -125,6 +125,9 @@ spec: https: url: https://github.com/kabanero-io/kabanero-pipelines/releases/download/0.8.0-rc.1/default-kabanero-pipelines.tar.gz + # The namespace pipelines will be created in + pipelinesNamespace: kabanero-pipeliness + governancePolicy: # Provide governance configuration for all stacks managed by Kabanero. The allowed configuration policies are: # strictDigest, activeDigest, ignoreDigest, and none. If a stack policy is not specified, activeDigest is used. diff --git a/pkg/apis/kabanero/v1alpha2/kabanero_types.go b/pkg/apis/kabanero/v1alpha2/kabanero_types.go index c678dbf8..a4a001ac 100644 --- a/pkg/apis/kabanero/v1alpha2/kabanero_types.go +++ b/pkg/apis/kabanero/v1alpha2/kabanero_types.go @@ -46,6 +46,8 @@ type KabaneroSpec struct { AdmissionControllerWebhook AdmissionControllerWebhookCustomizationSpec `json:"admissionControllerWebhook,omitempty"` Sso SsoCustomizationSpec `json:"sso,omitempty"` + + PipelinesNamespace string `json:"pipelinesNamespace,omitempty"` } // InstanceStackConfig defines the customization entries for a set of stacks. @@ -241,6 +243,9 @@ type KabaneroStatus struct { // SSO server status Sso SsoStatus `json:"sso,omitempty"` + + // Namespace of deployed Pipelines + PipelinesNamespace string `json:"pipelinesNamespace,omitempty"` } // KabaneroInstanceStatus defines the observed status details of Kabanero operator instance diff --git a/pkg/apis/kabanero/v1alpha2/stack_types.go b/pkg/apis/kabanero/v1alpha2/stack_types.go index aed20f81..3a0ef681 100644 --- a/pkg/apis/kabanero/v1alpha2/stack_types.go +++ b/pkg/apis/kabanero/v1alpha2/stack_types.go @@ -35,6 +35,7 @@ type StackSpec struct { Name string `json:"name,omitempty"` // +listType=set Versions []StackVersion `json:"versions,omitempty"` + PipelinesNamespace string `json:"pipelinesNamespace,omitempty"` } // StackVersion defines the desired composition of a specific stack version. @@ -79,6 +80,7 @@ type StackStatus struct { // +listType=set Versions []StackVersionStatus `json:"versions,omitempty"` Summary string `json:"summary,omitempty"` + PipelinesNamespace string `json:"pipelinesNamespace,omitempty"` } // StackVersionStatus defines the observed state of a specific stack version. diff --git a/pkg/controller/kabaneroplatform/featured_stacks.go b/pkg/controller/kabaneroplatform/featured_stacks.go index d670aa16..494064f1 100644 --- a/pkg/controller/kabaneroplatform/featured_stacks.go +++ b/pkg/controller/kabaneroplatform/featured_stacks.go @@ -46,7 +46,13 @@ func reconcileFeaturedStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, alreadyDeployed := true stackResource := &kabanerov1alpha2.Stack{} err := cl.Get(ctx, name, stackResource) - if err != nil { + + pipelinesNamespace := pipelinesNamespace(k) + + if err == nil { + // Ensure the featured stack pipelinesNamespace = Kabanero pipelinesNamespace + stackResource.Spec.PipelinesNamespace = pipelinesNamespace + } else { if errors.IsNotFound(err) { alreadyDeployed = false // Not found. Need to create it. @@ -68,6 +74,7 @@ func reconcileFeaturedStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, }, Spec: kabanerov1alpha2.StackSpec{ Name: key, + PipelinesNamespace: pipelinesNamespace, }, } } else { @@ -168,8 +175,26 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } + // Only keep the FeaturedStack if the Kabanero pipelinesNamespace did not change, otherwise delete & recreate + pipelinesNamespace := pipelinesNamespace(k) + for _, deployedStack := range deployedStacks.Items { + if deployedStack.Spec.PipelinesNamespace != pipelinesNamespace { + err := cl.Delete(ctx, &deployedStack) + if err != nil { + return err + } + } + } + + deployedStacks = &kabanerov1alpha2.StackList{} + err = cl.List(ctx, deployedStacks, client.InNamespace(k.GetNamespace())) + if err != nil { + return err + } + // Compare the list of currently deployed stacks and the stacks in the index. for _, deployedStack := range deployedStacks.Items { + iStackList, _ := indexStackMap[deployedStack.GetName()] newStackVersions := []kabanerov1alpha2.StackVersion{} for _, dStackVersion := range deployedStack.Spec.Versions { diff --git a/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go b/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go index 4d6232aa..c85c8449 100644 --- a/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go +++ b/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go @@ -394,6 +394,14 @@ func (r *ReconcileKabanero) Reconcile(request reconcile.Request) (reconcile.Resu return r.determineHowToRequeue(ctx, request, instance, err.Error(), r.requeueDelayMap, reqLogger) } + // Reconcile the cleanup of old pipelinesNamespace SA/Role/Rolebinding after processing FeaturedStacks + err = reconcilePipelinesNamespace(ctx, instance, r.client, reqLogger) + if err != nil { + reqLogger.Error(err, "Error reconciling pipelinesNamespace") + processStatus(ctx, request, instance, r.client, reqLogger) + return reconcile.Result{}, err + } + // things worked reset requeue data r.requeueDelayMap[request.Namespace] = RequeueData{0, time.Now()} diff --git a/pkg/controller/kabaneroplatform/stack-controller.go b/pkg/controller/kabaneroplatform/stack-controller.go index 3f9a236e..fb168fe4 100644 --- a/pkg/controller/kabaneroplatform/stack-controller.go +++ b/pkg/controller/kabaneroplatform/stack-controller.go @@ -21,6 +21,11 @@ const ( scOrchestrationFileName = "stack-controller.yaml" scDeploymentResourceName = "kabanero-operator-stack-controller" + + scKabaneroTriggersFileName = "stack-controller-kabanero-triggers.yaml" + + scPipelinesNamespaceFileName = "stack-controller-pipelines-namespace.yaml" + scPipelinesNamespaceManifestsFileName = "stack-controller-pipelines-namespace-manifests.yaml" ) // Installs the Kabanero stack controller. @@ -28,42 +33,57 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, logger := sclog.WithValues("Kabanero instance namespace", k.Namespace, "Kabanero instance Name", k.Name) logger.Info("Reconciling Kabanero stack controller installation.") - // Deploy the Kabanero stack operator. + // Setup context rev, err := resolveSoftwareRevision(k, scVersionSoftCompName, k.Spec.StackController.Version) if err != nil { logger.Error(err, "Kabanero stack controller deployment failed. Unable to resolve software revision.") return err } - templateCtx := rev.Identifiers - image, err := imageUriWithOverrides(k.Spec.StackController.Repository, k.Spec.StackController.Tag, k.Spec.StackController.Image, rev) + templateCtx["kabaneroNamespace"] = k.GetNamespace() + + // Create a Role & RoleBinding in the tekton-pipelines namespace that will allow + // the stack controller to create triggerbinding and triggertemplate + // objects in the tekton-pipelines namespace. + templateCtx["name"] = "kabanero-" + k.GetNamespace() + "-trigger-rolebinding" + + f, err := rev.OpenOrchestration(scKabaneroTriggersFileName) if err != nil { - logger.Error(err, "Kabanero stack controller deployment failed. Unable to process image overrides.") return err } - templateCtx["image"] = image - f, err := rev.OpenOrchestration(scOrchestrationFileName) + s, err := renderOrchestration(f, templateCtx) if err != nil { return err } - s, err := renderOrchestration(f, templateCtx) + m, err := mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) if err != nil { return err } - mOrig, err := mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + err = m.Apply() if err != nil { return err } - transforms := []mf.Transformer{ - mf.InjectOwner(k), - mf.InjectNamespace(k.GetNamespace()), + // Create the Namespace, ServiceAccount, Roles, & Bindings for the pipelinesNamespace + pipelinesNamespace := pipelinesNamespace(k) + templateCtx["pipelinesNamespace"] = pipelinesNamespace + + + // Namespace + f, err = rev.OpenOrchestration(scPipelinesNamespaceFileName) + if err != nil { + return err } - m, err := mOrig.Transform(transforms...) + s, err = renderOrchestration(f, templateCtx) + if err != nil { + return err + } + + m, err = mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) if err != nil { return err } @@ -73,13 +93,38 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } - // Create a RoleBinding in the tekton-pipelines namespace that will allow - // the stack controller to create triggerbinding and triggertemplate - // objects in the tekton-pipelines namespace. - templateCtx["name"] = "kabanero-" + k.GetNamespace() + "-trigger-rolebinding" - templateCtx["kabaneroNamespace"] = k.GetNamespace() + // ServiceAccount, Role, Rolebinding + f, err = rev.OpenOrchestration(scPipelinesNamespaceManifestsFileName) + if err != nil { + return err + } + + templateCtx["pipelinesNamespace"] = pipelinesNamespace + + s, err = renderOrchestration(f, templateCtx) + if err != nil { + return err + } + + m, err = mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + if err != nil { + return err + } + + err = m.Apply() + if err != nil { + return err + } + + // Deploy the Kabanero stack operator. + image, err := imageUriWithOverrides(k.Spec.StackController.Repository, k.Spec.StackController.Tag, k.Spec.StackController.Image, rev) + if err != nil { + logger.Error(err, "Kabanero stack controller deployment failed. Unable to process image overrides.") + return err + } + templateCtx["image"] = image - f, err = rev.OpenOrchestration("stack-controller-tekton.yaml") + f, err = rev.OpenOrchestration(scOrchestrationFileName) if err != nil { return err } @@ -89,12 +134,22 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } - mOrig, err = mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + m, err = mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) if err != nil { return err } - err = mOrig.Apply() + transforms := []mf.Transformer{ + mf.InjectOwner(k), + mf.InjectNamespace(k.GetNamespace()), + } + + mt, err := m.Transform(transforms...) + if err != nil { + return err + } + + err = mt.Apply() if err != nil { return err } @@ -151,7 +206,7 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c templateCtx["name"] = "kabanero-" + k.GetNamespace() + "-trigger-rolebinding" templateCtx["kabaneroNamespace"] = k.GetNamespace() - f, err := rev.OpenOrchestration("stack-controller-tekton.yaml") + f, err := rev.OpenOrchestration(scKabaneroTriggersFileName) if err != nil { return err } @@ -171,6 +226,30 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c return err } + + // Delete the ServiceAccount, Roles, & Bindings for the pipelinesNamespace (leave Namespace) + templateCtx["pipelinesNamespace"] = k.Status.PipelinesNamespace + + f, err = rev.OpenOrchestration(scPipelinesNamespaceManifestsFileName) + if err != nil { + return err + } + + s, err = renderOrchestration(f, templateCtx) + if err != nil { + return err + } + + m, err = mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + if err != nil { + return err + } + + err = m.Delete() + if err != nil { + return err + } + return nil } @@ -219,3 +298,75 @@ func getStackControllerStatus(ctx context.Context, k *kabanerov1alpha2.Kabanero, return ready, err } + + +func pipelinesNamespace(k *kabanerov1alpha2.Kabanero) string { + var pipelinesNamespace string + if len(k.Spec.PipelinesNamespace) != 0 { + pipelinesNamespace = k.Spec.PipelinesNamespace + } else { + pipelinesNamespace = k.GetNamespace() + } + return pipelinesNamespace +} + + +// Clean up the old namespace SA/Role/Bindings +func reconcilePipelinesNamespace(ctx context.Context, k *kabanerov1alpha2.Kabanero, c client.Client, _ logr.Logger) error { + logger := sclog.WithValues("Kabanero instance namespace", k.Namespace, "Kabanero instance Name", k.Name) + logger.Info("Reconciling Kabanero pipelinesNamespace.") + + pipelinesNamespace := pipelinesNamespace(k) + + deployedStacks := &kabanerov1alpha2.StackList{} + err := c.List(ctx, deployedStacks, client.InNamespace(k.GetNamespace())) + if err != nil { + return err + } + + // Remove the old SA/Role/Bindings once all the Featured Stacks are re-created in the new pipelinesNamespace + canCleanup := true + for _, deployedStack := range deployedStacks.Items { + if k.Spec.PipelinesNamespace != deployedStack.Status.PipelinesNamespace { + canCleanup = false + } + } + + if canCleanup == true { + // Setup context + rev, err := resolveSoftwareRevision(k, scVersionSoftCompName, k.Spec.StackController.Version) + if err != nil { + logger.Error(err, "Unable to resolve software revision.") + return err + } + templateCtx := rev.Identifiers + templateCtx["kabaneroNamespace"] = k.GetNamespace() + templateCtx["pipelinesNamespace"] = pipelinesNamespace + + f, err := rev.OpenOrchestration(scPipelinesNamespaceManifestsFileName) + if err != nil { + return err + } + + s, err := renderOrchestration(f, templateCtx) + if err != nil { + return err + } + + m, err := mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + if err != nil { + return err + } + + err = m.Delete() + if err != nil { + return err + } + + k.Status.PipelinesNamespace = pipelinesNamespace + } + + + + return nil +} \ No newline at end of file diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index 21641477..a43bc2a4 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -302,9 +302,10 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli // Gather the known stack asset (*-tasks, *-pipeline) substitution data. renderingContext := make(map[string]interface{}) - + + pipelinesNamespace := pipelinesNamespace(stackResource) // The stack id is the name of the Appsody stack directory ("the stack name from the stack path"). - // Appsody stack creation namimg constrains the length to 68 characters: + // Appsody stack creation naming constrains the length to 68 characters: // "The name must start with a lowercase letter, contain only lowercase letters, numbers, or dashes, // and cannot end in a dash." cID := stackResource.Spec.Name @@ -398,7 +399,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli for _, asset := range value.ActiveAssets { // Old assets may not have a namespace set - correct that now. if len(asset.Namespace) == 0 { - asset.Namespace = stackResource.GetNamespace() + asset.Namespace = pipelinesNamespace } deleteAsset(c, asset, assetOwner) @@ -423,7 +424,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli } // Retrieve manifests as unstructured. If we could not get them, skip. - manifests, err := GetManifests(c, stackResource.GetNamespace(), value.PipelineStatus, renderingContext, log) + manifests, err := GetManifests(c, pipelinesNamespace, value.PipelineStatus, renderingContext, log) if err != nil { log.Error(err, fmt.Sprintf("Error retrieving archive manifests: %v", value)) value.manifestError = err @@ -438,7 +439,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli // Figure out what namespace we should create the object in. value.ActiveAssets = append(value.ActiveAssets, kabanerov1alpha2.RepositoryAssetStatus{ Name: asset.Name, - Namespace: getNamespaceForObject(&asset.Yaml, stackResource.GetNamespace()), + Namespace: getNamespaceForObject(&asset.Yaml, pipelinesNamespace), Group: asset.Group, Version: asset.Version, Kind: asset.Kind, @@ -453,7 +454,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli for index, asset := range value.ActiveAssets { // Old assets may not have a namespace set - correct that now. if len(asset.Namespace) == 0 { - asset.Namespace = stackResource.GetNamespace() + asset.Namespace = pipelinesNamespace value.ActiveAssets[index].Namespace = asset.Namespace } @@ -485,7 +486,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli } // Retrieve manifests as unstructured - manifests, err := GetManifests(c, stackResource.GetNamespace(), value.PipelineStatus, renderingContext, log) + manifests, err := GetManifests(c, pipelinesNamespace, value.PipelineStatus, renderingContext, log) if err != nil { log.Error(err, fmt.Sprintf("Object %v not found and manifests not available: %v", asset.Name, value)) value.ActiveAssets[index].Status = assetStatusFailed @@ -575,6 +576,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli // Now update the StackStatus to reflect the current state of things. newStackStatus := kabanerov1alpha2.StackStatus{} + newStackStatus.PipelinesNamespace = pipelinesNamespace for i, curSpec := range stackResource.Spec.Versions { newStackVersionStatus := kabanerov1alpha2.StackVersionStatus{Version: curSpec.Version} if !strings.EqualFold(curSpec.DesiredState, kabanerov1alpha2.StackDesiredStateInactive) { @@ -880,3 +882,14 @@ func deleteAsset(c client.Client, asset kabanerov1alpha2.RepositoryAssetStatus, return nil } + + +func pipelinesNamespace(s *kabanerov1alpha2.Stack) string { + var pipelinesNamespace string + if len(s.Spec.PipelinesNamespace) != 0 { + pipelinesNamespace = s.Spec.PipelinesNamespace + } else { + pipelinesNamespace = s.GetNamespace() + } + return pipelinesNamespace +}