From c575381d438db217c81011b5049df2708e164f29 Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Thu, 2 Apr 2020 09:19:40 -0400 Subject: [PATCH 1/8] pipelinesNamespace --- config/samples/full.yaml | 3 ++ pkg/apis/kabanero/v1alpha2/kabanero_types.go | 2 ++ pkg/apis/kabanero/v1alpha2/stack_types.go | 1 + .../kabaneroplatform/featured_stacks.go | 1 + pkg/controller/stack/stack_controller.go | 34 +++++++++++++++---- 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/config/samples/full.yaml b/config/samples/full.yaml index 168a5fe1..bb59fafd 100644 --- a/config/samples/full.yaml +++ b/config/samples/full.yaml @@ -124,6 +124,9 @@ spec: sha256: e6ebc6aeaf21540f0d0dac8caf0a2d805e8d90f174cb912a31831f700d049bb1 https: url: https://github.com/kabanero-io/kabanero-pipelines/releases/download/0.7.0/default-kabanero-pipelines.tar.gz + + # The namespace pipelines will be created in + pipelinesNamespace: kabanero-pipelines governancePolicy: # Provide governance configuration for all stacks managed by Kabanero. The allowed configuration policies are: diff --git a/pkg/apis/kabanero/v1alpha2/kabanero_types.go b/pkg/apis/kabanero/v1alpha2/kabanero_types.go index c410a63f..b7879d87 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. diff --git a/pkg/apis/kabanero/v1alpha2/stack_types.go b/pkg/apis/kabanero/v1alpha2/stack_types.go index d8567550..67cae9a7 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. diff --git a/pkg/controller/kabaneroplatform/featured_stacks.go b/pkg/controller/kabaneroplatform/featured_stacks.go index ee37132b..f00c1f8e 100644 --- a/pkg/controller/kabaneroplatform/featured_stacks.go +++ b/pkg/controller/kabaneroplatform/featured_stacks.go @@ -68,6 +68,7 @@ func reconcileFeaturedStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, }, Spec: kabanerov1alpha2.StackSpec{ Name: key, + PipelinesNamespace: k.Spec.PipelinesNamespace, }, } } else { diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index 17e1e7c3..f6a58a13 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -246,9 +246,29 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re } r_log = r_log.WithValues("Stack.Name", stackName) + + ctx := context.Background() + + // Ensure PipelinesNamespace exists + namespace := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": c.Spec.PipelinesNamespace, + }, + }, + } + + err := r.client.Get(ctx, client.ObjectKey{Namespace: c.Spec.PipelinesNamespace, Name: c.Spec.PipelinesNamespace,}, namespace) + if err == nil { + if errors.IsNotFound(err) { + r.client.Create(ctx, namespace) + } + } // Process the versions array and activate (or deactivate) the desired versions. - err := reconcileActiveVersions(c, r.client, r_log) + err = reconcileActiveVersions(c, r.client, r_log) if err != nil { // TODO - what is useful to print? log.Error(err, fmt.Sprintf("Error during reconcileActiveVersions")) @@ -396,7 +416,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 = stackResource.Spec.PipelinesNamespace } deleteAsset(c, asset, assetOwner) @@ -417,7 +437,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext["Digest"] = value.Digest[0:8] // 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, stackResource.Spec.PipelinesNamespace, value.PipelineStatus, renderingContext, log) if err != nil { log.Error(err, fmt.Sprintf("Error retrieving archive manifests: %v", value)) value.manifestError = err @@ -432,7 +452,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, stackResource.Spec.PipelinesNamespace), Group: asset.Group, Version: asset.Version, Kind: asset.Kind, @@ -447,7 +467,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 = stackResource.Spec.PipelinesNamespace value.ActiveAssets[index].Namespace = asset.Namespace } @@ -475,7 +495,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext["Digest"] = value.Digest[0:8] // Retrieve manifests as unstructured - manifests, err := GetManifests(c, stackResource.GetNamespace(), value.PipelineStatus, renderingContext, log) + manifests, err := GetManifests(c, stackResource.Spec.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 @@ -607,7 +627,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli if err != nil { image.Digest.Message = fmt.Sprintf("Unable to parse registry from image: %v associated with stack: %v %v. Error: %v", img, stackResource.Spec.Name, curSpec.Version, err) } else { - digest, err := retrieveImageDigest(c, stackResource.GetNamespace(), registry, logger, img) + digest, err := retrieveImageDigest(c, stackResource.Spec.PipelinesNamespace, registry, logger, img) if err != nil { image.Digest.Message = fmt.Sprintf("Unable to retrieve stack activation digest for image: %v associated with stack: %v %v. Error: %v", img, stackResource.Spec.Name, curSpec.Version, err) } else { From 0e810dd4c8a907d5c4d5aa27073bb813c404984c Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Thu, 2 Apr 2020 16:39:38 -0400 Subject: [PATCH 2/8] pipelinesNamespace --- .../0.1/stack-controller.yaml | 62 ++++++++++++---- pkg/controller/stack/stack_controller.go | 72 +++++++++++++------ 2 files changed, 97 insertions(+), 37 deletions(-) diff --git a/config/orchestrations/stack-controller/0.1/stack-controller.yaml b/config/orchestrations/stack-controller/0.1/stack-controller.yaml index a856c60c..3014a59b 100644 --- a/config/orchestrations/stack-controller/0.1/stack-controller.yaml +++ b/config/orchestrations/stack-controller/0.1/stack-controller.yaml @@ -60,27 +60,19 @@ rules: verbs: - get - apiGroups: - - apps + - "" resources: - - replicasets - - deployments + - namespaces verbs: + - create - get - apiGroups: - - tekton.dev + - apps resources: - - conditions - - pipelines - - tasks - - triggerbindings - - triggertemplates + - replicasets + - deployments verbs: - - delete - get - - create - - list - - update - - watch - apiGroups: - kabanero.io resources: @@ -129,3 +121,45 @@ spec: valueFrom: fieldRef: fieldPath: metadata.namespace +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: kabanero-operator-stack-controller +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - create + - get +- apiGroups: + - tekton.dev + resources: + - conditions + - pipelines + - tasks + - triggerbindings + - triggertemplates + verbs: + - delete + - get + - create + - list + - update + - watch +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: kabanero-operator-stack-controller +subjects: +- kind: ServiceAccount + name: kabanero-operator-stack-controller + namespace: kabanero +roleRef: + kind: ClusterRole + name: kabanero-operator-stack-controller + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index f6a58a13..13eacd69 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -247,24 +247,10 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re r_log = r_log.WithValues("Stack.Name", stackName) - ctx := context.Background() - // Ensure PipelinesNamespace exists - namespace := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "Namespace", - "metadata": map[string]interface{}{ - "name": c.Spec.PipelinesNamespace, - }, - }, - } - - err := r.client.Get(ctx, client.ObjectKey{Namespace: c.Spec.PipelinesNamespace, Name: c.Spec.PipelinesNamespace,}, namespace) - if err == nil { - if errors.IsNotFound(err) { - r.client.Create(ctx, namespace) - } + err := reconcilePipelinesNamespace(c, r.client, r_log) + if err != nil { + log.Error(err, fmt.Sprintf("Error during reconcilePipelinesNamespace")) } // Process the versions array and activate (or deactivate) the desired versions. @@ -320,6 +306,8 @@ 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: @@ -416,7 +404,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.Spec.PipelinesNamespace + asset.Namespace = pipelinesNamespace } deleteAsset(c, asset, assetOwner) @@ -437,7 +425,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext["Digest"] = value.Digest[0:8] // Retrieve manifests as unstructured. If we could not get them, skip. - manifests, err := GetManifests(c, stackResource.Spec.PipelinesNamespace, 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 @@ -452,7 +440,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.Spec.PipelinesNamespace), + Namespace: getNamespaceForObject(&asset.Yaml, pipelinesNamespace), Group: asset.Group, Version: asset.Version, Kind: asset.Kind, @@ -467,7 +455,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.Spec.PipelinesNamespace + asset.Namespace = pipelinesNamespace value.ActiveAssets[index].Namespace = asset.Namespace } @@ -495,7 +483,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext["Digest"] = value.Digest[0:8] // Retrieve manifests as unstructured - manifests, err := GetManifests(c, stackResource.Spec.PipelinesNamespace, 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 @@ -627,7 +615,7 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli if err != nil { image.Digest.Message = fmt.Sprintf("Unable to parse registry from image: %v associated with stack: %v %v. Error: %v", img, stackResource.Spec.Name, curSpec.Version, err) } else { - digest, err := retrieveImageDigest(c, stackResource.Spec.PipelinesNamespace, registry, logger, img) + digest, err := retrieveImageDigest(c, pipelinesNamespace, registry, logger, img) if err != nil { image.Digest.Message = fmt.Sprintf("Unable to retrieve stack activation digest for image: %v associated with stack: %v %v. Error: %v", img, stackResource.Spec.Name, curSpec.Version, err) } else { @@ -871,3 +859,41 @@ func deleteAsset(c client.Client, asset kabanerov1alpha2.RepositoryAssetStatus, return nil } + + +func reconcilePipelinesNamespace(stackResource *kabanerov1alpha2.Stack, c client.Client, logger logr.Logger) error { + // Ensure PipelinesNamespace exists + + pipelinesNamespace := pipelinesNamespace(stackResource) + + namespace := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "Namespace", + "metadata": map[string]interface{}{ + "name": pipelinesNamespace, + }, + }, + } + + err := c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: pipelinesNamespace,}, namespace) + if err != nil { + if errors.IsNotFound(err) { + err = c.Create(context.TODO(), namespace) + if err != nil { + return err + } + } else { + return err + } + } + return nil +} + +func pipelinesNamespace(stackResource *kabanerov1alpha2.Stack) string { + pipelinesNamespace := "kabanero-pipelines" + if len(stackResource.Spec.PipelinesNamespace) != 0 { + pipelinesNamespace = stackResource.Spec.PipelinesNamespace + } + return pipelinesNamespace +} \ No newline at end of file From 3e25ec0be16cd54ac444e61561e3af83938f6436 Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Tue, 7 Apr 2020 09:28:10 -0400 Subject: [PATCH 3/8] pipelinesNamespace --- pkg/controller/stack/stack_controller.go | 79 +++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index 13eacd69..91eb46f0 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -253,6 +253,12 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re log.Error(err, fmt.Sprintf("Error during reconcilePipelinesNamespace")) } + // Ensure Pipelines ServeAccount, Role & Rolebinding exists + err = reconcilePipelinesServiceAccount(c, r.client, r_log) + if err != nil { + log.Error(err, fmt.Sprintf("Error during reconcilePipelinesServiceAccount")) + } + // Process the versions array and activate (or deactivate) the desired versions. err = reconcileActiveVersions(c, r.client, r_log) if err != nil { @@ -891,9 +897,80 @@ func reconcilePipelinesNamespace(stackResource *kabanerov1alpha2.Stack, c client } func pipelinesNamespace(stackResource *kabanerov1alpha2.Stack) string { - pipelinesNamespace := "kabanero-pipelines" + pipelinesNamespace := "kabanero" if len(stackResource.Spec.PipelinesNamespace) != 0 { pipelinesNamespace = stackResource.Spec.PipelinesNamespace } return pipelinesNamespace +} + +func reconcilePipelinesServiceAccount(stackResource *kabanerov1alpha2.Stack, c client.Client, logger logr.Logger) error { + // Ensure PipelinesNamespace exists + + pipelinesNamespace := pipelinesNamespace(stackResource) + serviceAccountName := "kabanero-pipeline" + + serviceAccount := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": map[string]interface{}{ + "name": serviceAccountName, + "namespace": pipelinesNamespace, + }, + }, + } + + err := c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: serviceAccountName,}, serviceAccount) + if err != nil { + if errors.IsNotFound(err) { + err = c.Create(context.TODO(), serviceAccount) + if err != nil { + return err + } + } else { + return err + } + } + + roleName := "kabanero-pipeline-role " + + role := &unstructured.Unstructured{} + + serviceAccount.SetGroupVersionKind(schema.GroupVersionKind{ + Kind: "ServiceAccount", + Version: "v1", + }) + + role.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "rbac.authorization.k8s.io", + Kind: "Role", + Version: "v1", + }) + + role.Object = map[string]interface{}{ + "name": roleName, + "namespace": pipelinesNamespace, + "rules": []map[string]interface{}{ + { + "apiGroups": []string{"security.openshift.io",}, + "resources": []string{"securitycontextconstraints",}, + "verbs": []string{"use",}, + }, + }, + } + + err = c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: roleName,}, role) + if err != nil { + if errors.IsNotFound(err) { + err = c.Create(context.TODO(), role) + if err != nil { + return err + } + } else { + return err + } + } + + return nil } \ No newline at end of file From 3e3bc9465071033b73396e11531aef1ec8561ee4 Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Wed, 8 Apr 2020 09:15:09 -0400 Subject: [PATCH 4/8] 230-2 --- ...ler-pipelinesnamespace-serviceaccount.yaml | 6 + pkg/apis/kabanero/v1alpha2/kabanero_types.go | 3 + .../kabaneroplatform/stack-controller.go | 95 +++++++++++++++ pkg/controller/stack/stack_controller.go | 114 ++---------------- 4 files changed, 113 insertions(+), 105 deletions(-) create mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml diff --git a/config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml new file mode 100644 index 00000000..cbc84595 --- /dev/null +++ b/config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml @@ -0,0 +1,6 @@ +# This serviceaccount is created for tekton pipelineruns +apiVersion: v1 +kind: ServiceAccount +metadata: + name: kabanero-pipeline + namespace: {{ .pipelinesNamespace }} diff --git a/pkg/apis/kabanero/v1alpha2/kabanero_types.go b/pkg/apis/kabanero/v1alpha2/kabanero_types.go index b7879d87..8d73336d 100644 --- a/pkg/apis/kabanero/v1alpha2/kabanero_types.go +++ b/pkg/apis/kabanero/v1alpha2/kabanero_types.go @@ -241,6 +241,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/controller/kabaneroplatform/stack-controller.go b/pkg/controller/kabaneroplatform/stack-controller.go index 3f9a236e..cfd6ab4d 100644 --- a/pkg/controller/kabaneroplatform/stack-controller.go +++ b/pkg/controller/kabaneroplatform/stack-controller.go @@ -21,6 +21,9 @@ const ( scOrchestrationFileName = "stack-controller.yaml" scDeploymentResourceName = "kabanero-operator-stack-controller" + + scPipelinesNamespaceServiceAccount = "stack-controller-pipelinesnamespace-serviceaccount.yaml" + ) // Installs the Kabanero stack controller. @@ -99,6 +102,62 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } + + // Create the Namespace, ServiceAccount, Roles, & Bindings for the pipelinesNamespace + pipelinesNamespace := pipelinesNamespace(k) + templateCtx["pipelinesNamespace"] = pipelinesNamespace + + f, err = rev.OpenOrchestration(scPipelinesNamespaceServiceAccount) + if err != nil { + return err + } + + // Delete the ServiceAccount if the PipelinesNamespace was changed + if len(k.Status.PipelinesNamespace) != 0 { + if k.Status.PipelinesNamespace != pipelinesNamespace { + + templateCtx["pipelinesNamespace"] = k.Status.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.Delete() + if err != nil { + return err + } + + } + } + + // Apply the ServiceAccount to the pipelinesNamespace + templateCtx["pipelinesNamespace"] = pipelinesNamespace + + s, err = renderOrchestration(f, templateCtx) + if err != nil { + return err + } + + mOrig, 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() + if err != nil { + return err + } + + k.Status.PipelinesNamespace = pipelinesNamespace + + + return nil } @@ -171,6 +230,31 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c return err } + + // Cleanup PipelinesNamespace + templateCtx["pipelinesNamespace"] = k.Status.PipelinesNamespace + + f, err = rev.OpenOrchestration(scPipelinesNamespaceServiceAccount) + 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 +303,14 @@ 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 +} \ No newline at end of file diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index 91eb46f0..e2cdcaf8 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -247,6 +247,7 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re r_log = r_log.WithValues("Stack.Name", stackName) +/* // Ensure PipelinesNamespace exists err := reconcilePipelinesNamespace(c, r.client, r_log) if err != nil { @@ -258,9 +259,10 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re if err != nil { log.Error(err, fmt.Sprintf("Error during reconcilePipelinesServiceAccount")) } +*/ // Process the versions array and activate (or deactivate) the desired versions. - err = reconcileActiveVersions(c, r.client, r_log) + err := reconcileActiveVersions(c, r.client, r_log) if err != nil { // TODO - what is useful to print? log.Error(err, fmt.Sprintf("Error during reconcileActiveVersions")) @@ -867,110 +869,12 @@ func deleteAsset(c client.Client, asset kabanerov1alpha2.RepositoryAssetStatus, } -func reconcilePipelinesNamespace(stackResource *kabanerov1alpha2.Stack, c client.Client, logger logr.Logger) error { - // Ensure PipelinesNamespace exists - - pipelinesNamespace := pipelinesNamespace(stackResource) - - namespace := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "Namespace", - "metadata": map[string]interface{}{ - "name": pipelinesNamespace, - }, - }, - } - - err := c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: pipelinesNamespace,}, namespace) - if err != nil { - if errors.IsNotFound(err) { - err = c.Create(context.TODO(), namespace) - if err != nil { - return err - } - } else { - return err - } - } - return nil -} - -func pipelinesNamespace(stackResource *kabanerov1alpha2.Stack) string { - pipelinesNamespace := "kabanero" - if len(stackResource.Spec.PipelinesNamespace) != 0 { - pipelinesNamespace = stackResource.Spec.PipelinesNamespace +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 } - -func reconcilePipelinesServiceAccount(stackResource *kabanerov1alpha2.Stack, c client.Client, logger logr.Logger) error { - // Ensure PipelinesNamespace exists - - pipelinesNamespace := pipelinesNamespace(stackResource) - serviceAccountName := "kabanero-pipeline" - - serviceAccount := &unstructured.Unstructured{ - Object: map[string]interface{}{ - "apiVersion": "v1", - "kind": "ServiceAccount", - "metadata": map[string]interface{}{ - "name": serviceAccountName, - "namespace": pipelinesNamespace, - }, - }, - } - - err := c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: serviceAccountName,}, serviceAccount) - if err != nil { - if errors.IsNotFound(err) { - err = c.Create(context.TODO(), serviceAccount) - if err != nil { - return err - } - } else { - return err - } - } - - roleName := "kabanero-pipeline-role " - - role := &unstructured.Unstructured{} - - serviceAccount.SetGroupVersionKind(schema.GroupVersionKind{ - Kind: "ServiceAccount", - Version: "v1", - }) - - role.SetGroupVersionKind(schema.GroupVersionKind{ - Group: "rbac.authorization.k8s.io", - Kind: "Role", - Version: "v1", - }) - - role.Object = map[string]interface{}{ - "name": roleName, - "namespace": pipelinesNamespace, - "rules": []map[string]interface{}{ - { - "apiGroups": []string{"security.openshift.io",}, - "resources": []string{"securitycontextconstraints",}, - "verbs": []string{"use",}, - }, - }, - } - - err = c.Get(context.TODO(), client.ObjectKey{Namespace: pipelinesNamespace, Name: roleName,}, role) - if err != nil { - if errors.IsNotFound(err) { - err = c.Create(context.TODO(), role) - if err != nil { - return err - } - } else { - return err - } - } - - return nil -} \ No newline at end of file From 5f85fc6619f160a0c193cfaa74e60b217d32e9b0 Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Wed, 8 Apr 2020 16:40:44 -0400 Subject: [PATCH 5/8] pipelinesNamespace --- .../stack-controller-kabanero-triggers.yaml | 42 ++++ ...troller-pipelines-namespace-manifests.yaml | 192 ++++++++++++++++++ .../stack-controller-pipelines-namespace.yaml | 5 + ...ler-pipelinesnamespace-serviceaccount.yaml | 6 - .../0.1/stack-controller-tekton.yaml | 17 -- .../kabaneroplatform/stack-controller.go | 111 ++++++---- 6 files changed, 307 insertions(+), 66 deletions(-) create mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-kabanero-triggers.yaml create mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace-manifests.yaml create mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace.yaml delete mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml delete mode 100644 config/orchestrations/stack-controller/0.1/stack-controller-tekton.yaml 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..3e3d630e --- /dev/null +++ b/config/orchestrations/stack-controller/0.1/stack-controller-pipelines-namespace-manifests.yaml @@ -0,0 +1,192 @@ +# ServiceAccount, Role & RoleBinding for 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 }} 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-pipelinesnamespace-serviceaccount.yaml b/config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml deleted file mode 100644 index cbc84595..00000000 --- a/config/orchestrations/stack-controller/0.1/stack-controller-pipelinesnamespace-serviceaccount.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# This serviceaccount is created for tekton pipelineruns -apiVersion: v1 -kind: ServiceAccount -metadata: - name: kabanero-pipeline - namespace: {{ .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/pkg/controller/kabaneroplatform/stack-controller.go b/pkg/controller/kabaneroplatform/stack-controller.go index cfd6ab4d..48db267a 100644 --- a/pkg/controller/kabaneroplatform/stack-controller.go +++ b/pkg/controller/kabaneroplatform/stack-controller.go @@ -22,8 +22,10 @@ const ( scDeploymentResourceName = "kabanero-operator-stack-controller" - scPipelinesNamespaceServiceAccount = "stack-controller-pipelinesnamespace-serviceaccount.yaml" + scKabaneroTriggersFileName = "stack-controller-kabanero-triggers.yaml" + scPipelinesNamespaceFileName = "stack-controller-pipelines-namespace.yaml" + scPipelinesNamespaceManifestsFileName = "stack-controller-pipelines-namespace-manifests.yaml" ) // Installs the Kabanero stack controller. @@ -31,42 +33,31 @@ 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) - if err != nil { - logger.Error(err, "Kabanero stack controller deployment failed. Unable to process image overrides.") - return err - } - templateCtx["image"] = image + templateCtx["kabaneroNamespace"] = k.GetNamespace() - f, err := rev.OpenOrchestration(scOrchestrationFileName) - if err != nil { - return err - } + // 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" - s, err := renderOrchestration(f, templateCtx) + f, err := rev.OpenOrchestration(scKabaneroTriggersFileName) if err != nil { return err } - mOrig, err := mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) + s, err := renderOrchestration(f, templateCtx) if err != nil { return err } - transforms := []mf.Transformer{ - mf.InjectOwner(k), - mf.InjectNamespace(k.GetNamespace()), - } - - m, err := mOrig.Transform(transforms...) + m, err := mf.ManifestFrom(mf.Reader(strings.NewReader(s)), mf.UseClient(mfc.NewClient(c)), mf.UseLogger(logger.WithName("manifestival"))) if err != nil { return err } @@ -76,13 +67,13 @@ 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() + // Create the Namespace, ServiceAccount, Roles, & Bindings for the pipelinesNamespace + pipelinesNamespace := pipelinesNamespace(k) + templateCtx["pipelinesNamespace"] = pipelinesNamespace + - f, err = rev.OpenOrchestration("stack-controller-tekton.yaml") + // Namespace + f, err = rev.OpenOrchestration(scPipelinesNamespaceFileName) if err != nil { return err } @@ -92,27 +83,23 @@ 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() + err = m.Apply() if err != nil { return err } - - // Create the Namespace, ServiceAccount, Roles, & Bindings for the pipelinesNamespace - pipelinesNamespace := pipelinesNamespace(k) - templateCtx["pipelinesNamespace"] = pipelinesNamespace - - f, err = rev.OpenOrchestration(scPipelinesNamespaceServiceAccount) + // ServiceAccount, Role, Rolebinding + f, err = rev.OpenOrchestration(scPipelinesNamespaceManifestsFileName) if err != nil { return err } - // Delete the ServiceAccount if the PipelinesNamespace was changed + // Delete if the PipelinesNamespace was changed if len(k.Status.PipelinesNamespace) != 0 { if k.Status.PipelinesNamespace != pipelinesNamespace { @@ -135,8 +122,7 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, } } - - // Apply the ServiceAccount to the pipelinesNamespace + templateCtx["pipelinesNamespace"] = pipelinesNamespace s, err = renderOrchestration(f, templateCtx) @@ -144,12 +130,12 @@ 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() + err = m.Apply() if err != nil { return err } @@ -157,6 +143,43 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, k.Status.PipelinesNamespace = pipelinesNamespace + // 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(scOrchestrationFileName) + 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 + } + + 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 + } return nil } @@ -210,7 +233,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 } @@ -231,10 +254,10 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c } - // Cleanup PipelinesNamespace + // Delete the ServiceAccount, Roles, & Bindings for the pipelinesNamespace (leave Namespace) templateCtx["pipelinesNamespace"] = k.Status.PipelinesNamespace - f, err = rev.OpenOrchestration(scPipelinesNamespaceServiceAccount) + f, err = rev.OpenOrchestration(scPipelinesNamespaceManifestsFileName) if err != nil { return err } @@ -255,6 +278,8 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c } + + return nil } From 5a8ddd0e6e357e0662aca812533043946f9610ed Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Fri, 10 Apr 2020 14:21:10 -0400 Subject: [PATCH 6/8] pipelinesNamespace --- ...troller-pipelines-namespace-manifests.yaml | 38 +++++++- .../0.1/stack-controller.yaml | 64 ++++--------- pkg/apis/kabanero/v1alpha2/stack_types.go | 1 + .../kabaneroplatform/featured_stacks.go | 32 ++++++- .../kabaneroplatform_controller.go | 8 ++ .../kabaneroplatform/stack-controller.go | 91 +++++++++++++------ pkg/controller/stack/stack_controller.go | 19 +--- 7 files changed, 156 insertions(+), 97 deletions(-) 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 index 3e3d630e..963847fe 100644 --- 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 @@ -1,4 +1,4 @@ -# ServiceAccount, Role & RoleBinding for piplines to be run +# ServiceAccount, Role & RoleBinding for stack-controller to create & piplines to be run apiVersion: v1 kind: ServiceAccount metadata: @@ -190,3 +190,39 @@ 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.yaml b/config/orchestrations/stack-controller/0.1/stack-controller.yaml index 3014a59b..f54649a0 100644 --- a/config/orchestrations/stack-controller/0.1/stack-controller.yaml +++ b/config/orchestrations/stack-controller/0.1/stack-controller.yaml @@ -60,19 +60,27 @@ rules: verbs: - get - apiGroups: - - "" + - apps resources: - - namespaces + - replicasets + - deployments verbs: - - create - get - apiGroups: - - apps + - tekton.dev resources: - - replicasets - - deployments + - conditions + - pipelines + - tasks + - triggerbindings + - triggertemplates verbs: + - delete - get + - create + - list + - update + - watch - apiGroups: - kabanero.io resources: @@ -116,50 +124,10 @@ spec: - name: kabanero-operator-stack-controller image: {{ .image }} imagePullPolicy: Always + command: + - /usr/local/bin/kabanero-operator-stack-controller env: - name: KABANERO_NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - creationTimestamp: null - name: kabanero-operator-stack-controller -rules: -- apiGroups: - - "" - resources: - - namespaces - verbs: - - create - - get -- apiGroups: - - tekton.dev - resources: - - conditions - - pipelines - - tasks - - triggerbindings - - triggertemplates - verbs: - - delete - - get - - create - - list - - update - - watch ---- -kind: ClusterRoleBinding -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: kabanero-operator-stack-controller -subjects: -- kind: ServiceAccount - name: kabanero-operator-stack-controller - namespace: kabanero -roleRef: - kind: ClusterRole - name: kabanero-operator-stack-controller - apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/pkg/apis/kabanero/v1alpha2/stack_types.go b/pkg/apis/kabanero/v1alpha2/stack_types.go index 67cae9a7..a2b4da9f 100644 --- a/pkg/apis/kabanero/v1alpha2/stack_types.go +++ b/pkg/apis/kabanero/v1alpha2/stack_types.go @@ -78,6 +78,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 f00c1f8e..60a6cb81 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,7 +74,7 @@ func reconcileFeaturedStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, }, Spec: kabanerov1alpha2.StackSpec{ Name: key, - PipelinesNamespace: k.Spec.PipelinesNamespace, + PipelinesNamespace: pipelinesNamespace, }, } } else { @@ -167,10 +173,31 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } + // Only keep the FeaturedStack if the Kabanero pipelinesNamespace did not change, otherwise delete & recreate + log.Info(fmt.Sprintf("Check pipelinesNamespace")) + pipelinesNamespace := pipelinesNamespace(k) + for _, deployedStack := range deployedStacks.Items { + if deployedStack.Spec.PipelinesNamespace != pipelinesNamespace { + log.Info(fmt.Sprintf("PipelinesNamespace has changed. Delete Stack: %v", deployedStack.Spec.Name)) + 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{} + log.Info(fmt.Sprintf("Match pipelinesNamespace")) for _, dStackVersion := range deployedStack.Spec.Versions { deployedStackVersionMatchIndex := false // Keep the stacks with matching versions. The caller will do the updates if necessary. @@ -191,6 +218,7 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, // If there were no indications that the stack should be kept around, delete it. if len(newStackVersions) == 0 { + log.Info(fmt.Sprintf("Delete Stack: %v", deployedStack.Spec.Name)) err := cl.Delete(ctx, &deployedStack) if err != nil { return err diff --git a/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go b/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go index 4a418685..8982d9fd 100644 --- a/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go +++ b/pkg/controller/kabaneroplatform/kabaneroplatform_controller.go @@ -347,6 +347,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 48db267a..fb168fe4 100644 --- a/pkg/controller/kabaneroplatform/stack-controller.go +++ b/pkg/controller/kabaneroplatform/stack-controller.go @@ -98,30 +98,6 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, if err != nil { return err } - - // Delete if the PipelinesNamespace was changed - if len(k.Status.PipelinesNamespace) != 0 { - if k.Status.PipelinesNamespace != pipelinesNamespace { - - templateCtx["pipelinesNamespace"] = k.Status.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.Delete() - if err != nil { - return err - } - - } - } templateCtx["pipelinesNamespace"] = pipelinesNamespace @@ -140,9 +116,6 @@ func reconcileStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, return err } - k.Status.PipelinesNamespace = pipelinesNamespace - - // Deploy the Kabanero stack operator. image, err := imageUriWithOverrides(k.Spec.StackController.Repository, k.Spec.StackController.Tag, k.Spec.StackController.Image, rev) if err != nil { @@ -277,9 +250,6 @@ func cleanupStackController(ctx context.Context, k *kabanerov1alpha2.Kabanero, c return err } - - - return nil } @@ -338,4 +308,65 @@ func pipelinesNamespace(k *kabanerov1alpha2.Kabanero) string { 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 e2cdcaf8..f5d69bfb 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -246,20 +246,6 @@ func (r *ReconcileStack) ReconcileStack(c *kabanerov1alpha2.Stack) (reconcile.Re } r_log = r_log.WithValues("Stack.Name", stackName) - -/* - // Ensure PipelinesNamespace exists - err := reconcilePipelinesNamespace(c, r.client, r_log) - if err != nil { - log.Error(err, fmt.Sprintf("Error during reconcilePipelinesNamespace")) - } - - // Ensure Pipelines ServeAccount, Role & Rolebinding exists - err = reconcilePipelinesServiceAccount(c, r.client, r_log) - if err != nil { - log.Error(err, fmt.Sprintf("Error during reconcilePipelinesServiceAccount")) - } -*/ // Process the versions array and activate (or deactivate) the desired versions. err := reconcileActiveVersions(c, r.client, r_log) @@ -316,9 +302,9 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext := make(map[string]interface{}) pipelinesNamespace := pipelinesNamespace(stackResource) - + log.Info(fmt.Sprintf("starting reconcileActiveVersions, pipelinesNamespace is: %v", pipelinesNamespace)) // 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 @@ -568,6 +554,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) { From 2e5a3e645298b53b467ff144a2cdbd7189df7ec0 Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Mon, 13 Apr 2020 09:35:16 -0400 Subject: [PATCH 7/8] pipelinesNamespace --- config/samples/full.yaml | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/config/samples/full.yaml b/config/samples/full.yaml index bb59fafd..e435018e 100644 --- a/config/samples/full.yaml +++ b/config/samples/full.yaml @@ -9,7 +9,7 @@ metadata: spec: # The platform version determines the desired version for all components, but those # can be overriden individually as well - version: "0.8.0" + version: "0.9.0" targetNamespaces: - ns1 @@ -17,14 +17,14 @@ spec: cliServices: # Overrides the setting for version on this component - version: "0.7.0" + version: "0.8.0-rc.1" # Overrides the image as a separate repository or tag repository: kabanero/kabanero-command-line-services - tag: "0.7.0" + tag: "0.8.0-rc.1" # Overrides the image uri - image: kabanero/kabanero-command-line-services:0.7.0 + image: kabanero/kabanero-command-line-services:0.8.0-rc.1 # Indicates the token expiration time # Specify a positive integer followed by a unit of time, which can be hours (h), minutes (m), or seconds (s). @@ -34,50 +34,50 @@ spec: collectionController: # Overrides the setting for version on this component - version: "0.8.0" + version: "0.9.0" # Overrides the image as a separate repository or tag - repository: kabanero/kabaner-operator-collection-controller - tag: "0.8.0-alpha.1" + repository: kabanero/kabanero-operator + tag: "TRAVIS_TAG" # Overrides the image uri - image: kabanero/kabanero-operator-collection-controller:0.8.0-alpha.1 + image: kabanero/kabanero-operator:TRAVIS_TAG stackController: # Overrides the setting for version on this component - version: "0.8.0" + version: "0.9.0" # Overrides the image as a separate repository or tag - repository: kabanero/kabaner-operator-stack-controller - tag: "0.8.0-alpha.1" + repository: kabanero/kabanero-operator + tag: "TRAVIS_TAG" # Overrides the image uri - image: kabanero/kabanero-operator-stack-controller:0.8.0-alpha.1 + image: kabanero/kabanero-operator:TRAVIS_TAG landing: # The landing page is enabled by default. To disable specify false. enable: true # Overrides the setting for version on this component - version: "0.7.0" + version: "0.8.0-rc.1" # Overrides the image as a separate repository or tag repository: kabanero/landing - tag: "0.7.0" + tag: "0.8.0-rc.1" # Overrides the image uri - image: kabanero/landing:0.7.0 + image: kabanero/landing:0.8.0-rc.1 admissionControllerWebhook: # Overrides the setting for version on this component - version: "0.8.0" + version: "0.9.0" # Overrides the image as a separate repository or tag - repository: kabanero/kabanero-operator-admission-webhook - tag: "0.8.0-alpha.1" + repository: kabanero/kabanero-operator + tag: "TRAVIS_TAG" # Overrides the image uri - image: kabanero/kabanero-operator-admission-webhook:0.8.0-alpha.1 + image: kabanero/kabanero-operator:TRAVIS_TAG codeReadyWorkspaces: # CodeReadyWorkspaces CR instance deployment is disabled by default. To enable it, set the enable value to true. @@ -118,15 +118,15 @@ spec: repositories: - name: incubator https: - url: https://github.com/kabanero-io/kabanero-stack-hub/releases/download/0.7.0/kabanero-stack-hub-index.yaml + url: https://github.com/kabanero-io/kabanero-stack-hub/releases/download/0.8.0-rc1/kabanero-stack-hub-index.yaml pipelines: - id: default - sha256: e6ebc6aeaf21540f0d0dac8caf0a2d805e8d90f174cb912a31831f700d049bb1 + sha256: 653e5c69abcefdaf7ac9ef3b826376edb8517f64aca44d5eda40a74ff1d62ee5 https: - url: https://github.com/kabanero-io/kabanero-pipelines/releases/download/0.7.0/default-kabanero-pipelines.tar.gz - + 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-pipelines + pipelinesNamespace: kabanero-pipeliness governancePolicy: # Provide governance configuration for all stacks managed by Kabanero. The allowed configuration policies are: From 92df991ed062cb70c23f76f25208ca2f48128aab Mon Sep 17 00:00:00 2001 From: Daniel Cleyrat Date: Mon, 13 Apr 2020 09:43:51 -0400 Subject: [PATCH 8/8] cleanup debug --- pkg/controller/kabaneroplatform/featured_stacks.go | 4 ---- pkg/controller/stack/stack_controller.go | 1 - 2 files changed, 5 deletions(-) diff --git a/pkg/controller/kabaneroplatform/featured_stacks.go b/pkg/controller/kabaneroplatform/featured_stacks.go index b77f2a16..494064f1 100644 --- a/pkg/controller/kabaneroplatform/featured_stacks.go +++ b/pkg/controller/kabaneroplatform/featured_stacks.go @@ -176,11 +176,9 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, } // Only keep the FeaturedStack if the Kabanero pipelinesNamespace did not change, otherwise delete & recreate - log.Info(fmt.Sprintf("Check pipelinesNamespace")) pipelinesNamespace := pipelinesNamespace(k) for _, deployedStack := range deployedStacks.Items { if deployedStack.Spec.PipelinesNamespace != pipelinesNamespace { - log.Info(fmt.Sprintf("PipelinesNamespace has changed. Delete Stack: %v", deployedStack.Spec.Name)) err := cl.Delete(ctx, &deployedStack) if err != nil { return err @@ -199,7 +197,6 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, iStackList, _ := indexStackMap[deployedStack.GetName()] newStackVersions := []kabanerov1alpha2.StackVersion{} - log.Info(fmt.Sprintf("Match pipelinesNamespace")) for _, dStackVersion := range deployedStack.Spec.Versions { deployedStackVersionMatchIndex := false // Keep the stacks with matching versions. The caller will do the updates if necessary. @@ -220,7 +217,6 @@ func preProcessCurrentStacks(ctx context.Context, k *kabanerov1alpha2.Kabanero, // If there were no indications that the stack should be kept around, delete it. if len(newStackVersions) == 0 { - log.Info(fmt.Sprintf("Delete Stack: %v", deployedStack.Spec.Name)) err := cl.Delete(ctx, &deployedStack) if err != nil { return err diff --git a/pkg/controller/stack/stack_controller.go b/pkg/controller/stack/stack_controller.go index 42c2aa91..a43bc2a4 100644 --- a/pkg/controller/stack/stack_controller.go +++ b/pkg/controller/stack/stack_controller.go @@ -304,7 +304,6 @@ func reconcileActiveVersions(stackResource *kabanerov1alpha2.Stack, c client.Cli renderingContext := make(map[string]interface{}) pipelinesNamespace := pipelinesNamespace(stackResource) - log.Info(fmt.Sprintf("starting reconcileActiveVersions, pipelinesNamespace is: %v", pipelinesNamespace)) // The stack id is the name of the Appsody stack directory ("the stack name from the stack path"). // 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,