From c77fd642deb2f69c624c66f3e2f4ead8f1dce81f Mon Sep 17 00:00:00 2001 From: Jawed khelil Date: Wed, 27 Nov 2024 09:53:10 +0100 Subject: [PATCH] restore community tasks as openshift addons --- .../all/operator_v1alpha1_config_cr.yaml | 2 + docs/TektonAddon.md | 7 +- docs/TektonConfig.md | 4 +- ...nes-operator-rh.clusterserviceversion.yaml | 2 +- pkg/apis/operator/v1alpha1/const.go | 2 + .../v1alpha1/tektonaddon_default_test.go | 132 +++++++++--------- .../v1alpha1/tektonconfig_default_test.go | 12 +- .../openshift/tektonaddon/community_tasks.go | 87 ++++++++++++ pkg/reconciler/openshift/tektonaddon/const.go | 1 + .../openshift/tektonaddon/controller.go | 35 +++-- .../openshift/tektonaddon/tektonaddon.go | 35 +++-- .../common/00_tektonconfigdeployment_test.go | 1 + test/resources/tektonaddons.go | 1 + test/resources/tektonconfigs.go | 2 +- 14 files changed, 222 insertions(+), 101 deletions(-) create mode 100644 pkg/reconciler/openshift/tektonaddon/community_tasks.go diff --git a/config/crs/openshift/config/all/operator_v1alpha1_config_cr.yaml b/config/crs/openshift/config/all/operator_v1alpha1_config_cr.yaml index 9f21a16e35..26f77d943b 100644 --- a/config/crs/openshift/config/all/operator_v1alpha1_config_cr.yaml +++ b/config/crs/openshift/config/all/operator_v1alpha1_config_cr.yaml @@ -27,6 +27,8 @@ spec: value: "true" - name: resolverStepActions value: "true" + - name: communityResolverTasks + value: "true" params: - name: createRbacResource value: "true" diff --git a/docs/TektonAddon.md b/docs/TektonAddon.md index 63c6d623c3..a7c2123742 100644 --- a/docs/TektonAddon.md +++ b/docs/TektonAddon.md @@ -6,7 +6,7 @@ weight: 6 --> # Tekton Addon -TektonAddon custom resource allows user to install resource like resolverTasks, resolverStepActions and pipelineTemplate along with Pipelines. +TektonAddon custom resource allows user to install resource like resolverTasks, resolverStepActions, communityResolverTasks and pipelineTemplate along with Pipelines. It also allows user to install various Tasks in openshift-pipelines namespace. **NOTE:** TektonAddon is currently available only for OpenShift Platform. This is roadmap to enable it for Kubernetes platform. @@ -28,6 +28,8 @@ spec: value: "true" - name: resolverStepActions value: "true" + - name: communityResolverTasks + value: "true" ``` You can install this component using [TektonConfig](./TektonConfig.md) by choosing appropriate `profile`. @@ -38,7 +40,8 @@ Available params are - `pipelineTemplates` (Default: `true`) - `resolverTasks` (Default: `true`) - `resolverStepActions` (Default: `true`) +- `communityResolverTasks` (Default: `true`) User can disable the installation of resources by changing the value to `false`. -- Pipelines templates uses tasks from `openshift-pipelines` in them so to install pipelineTemplates, resolverTasks must be `true` \ No newline at end of file +- Pipelines templates uses tasks from `openshift-pipelines`. Therefore, to install pipelineTemplates, resolverTasks must be set to `true` diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md index 10c4a7188e..6ac633fadf 100644 --- a/docs/TektonConfig.md +++ b/docs/TektonConfig.md @@ -329,7 +329,7 @@ By default pruner job will be created from the global pruner config (`spec.prune > `keep: 100`
### Addon -TektonAddon install some resources along with Tekton Pipelines on the cluster. This provides few PipelineTemplates, ResolverTasks and ResolverStepActions. +TektonAddon install some resources along with Tekton Pipelines on the cluster. This provides few PipelineTemplates, ResolverTasks, ResolverStepActions and CommunityResolverTasks. This section allows to customize installation of those resources through params. You can read more about the supported params [here](./TektonAddon.md). @@ -343,6 +343,8 @@ addon: value: "true" - name: "resolverStepActions" value: "true" + - name: "communityResolverTasks" + value: "true" ``` **NOTE**: TektonAddon is currently available for OpenShift Platform only. Enabling this for Kubernetes platform is in roadmap diff --git a/operatorhub/openshift/release-artifacts/bundle/manifests/openshift-pipelines-operator-rh.clusterserviceversion.yaml b/operatorhub/openshift/release-artifacts/bundle/manifests/openshift-pipelines-operator-rh.clusterserviceversion.yaml index 7dec5c93d9..f3efd03a0a 100644 --- a/operatorhub/openshift/release-artifacts/bundle/manifests/openshift-pipelines-operator-rh.clusterserviceversion.yaml +++ b/operatorhub/openshift/release-artifacts/bundle/manifests/openshift-pipelines-operator-rh.clusterserviceversion.yaml @@ -14,7 +14,7 @@ metadata: \ {\n \"name\": \"clusterTasks\",\n \"value\": \"\ true\"\n },\n {\n \"name\": \"pipelineTemplates\"\ ,\n \"value\": \"true\"\n },\n {\n \"\ - name\": \"communityClusterTasks\",\n \"value\": \"true\"\n \ + name\": \"communityResolverTasks\",\n \"value\": \"true\"\n \ \ }\n ]\n },\n \"params\": [\n {\n \"name\"\ : \"createRbacResource\",\n \"value\": \"true\"\n }\n ],\n\ \ \"profile\": \"all\",\n \"pruner\": {\n \"keep\": 100,\n\ diff --git a/pkg/apis/operator/v1alpha1/const.go b/pkg/apis/operator/v1alpha1/const.go index c0d8fda787..6268dbfd01 100644 --- a/pkg/apis/operator/v1alpha1/const.go +++ b/pkg/apis/operator/v1alpha1/const.go @@ -33,6 +33,7 @@ const ( ProfileLite = "lite" // Addon Params + CommunityResolverTasks = "communityResolverTasks" PipelineTemplatesParam = "pipelineTemplates" ResolverTasks = "resolverTasks" ResolverStepActions = "resolverStepActions" @@ -109,6 +110,7 @@ var ( } AddonParams = map[string]ParamValue{ + CommunityResolverTasks: defaultParamValue, PipelineTemplatesParam: defaultParamValue, ResolverTasks: defaultParamValue, ResolverStepActions: defaultParamValue, diff --git a/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go b/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go index 2c2dd2d7f3..a6d09e14b8 100644 --- a/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go +++ b/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go @@ -24,87 +24,85 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func Test_AddonSetDefaults_DefaultParamsWithValues(t *testing.T) { - - ta := &TektonAddon{ - ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespace", +func Test_AddonSetDefaults(t *testing.T) { + tests := []struct { + name string + initialParams []Param + expectedParams map[string]string + }{ + { + name: "Default Params with Values", + initialParams: []Param{ + {Name: PipelineTemplatesParam, Value: "true"}, + }, + expectedParams: map[string]string{ + PipelineTemplatesParam: "true", + }, }, - Spec: TektonAddonSpec{ - CommonSpec: CommonSpec{ - TargetNamespace: "namespace", + { + name: "Resolver Task is False", + initialParams: []Param{ + {Name: ResolverTasks, Value: "false"}, + }, + expectedParams: map[string]string{ + ResolverTasks: "false", }, }, - } - - ta.SetDefaults(context.TODO()) - assert.Equal(t, 3, len(ta.Spec.Params)) - - params := ParseParams(ta.Spec.Params) - value, ok := params[PipelineTemplatesParam] - assert.Equal(t, true, ok) - assert.Equal(t, "true", value) -} - -func Test_AddonSetDefaults_ResolverTaskIsFalse(t *testing.T) { - - ta := &TektonAddon{ - ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespace", + { + name: "Resolver Step Actions", + initialParams: []Param{ + {Name: ResolverStepActions, Value: "false"}, + }, + expectedParams: map[string]string{ + ResolverStepActions: "false", + }, }, - Spec: TektonAddonSpec{ - CommonSpec: CommonSpec{ - TargetNamespace: "namespace", + { + name: "Community Resolver Tasks", + initialParams: []Param{ + {Name: CommunityResolverTasks, Value: "false"}, }, - Addon: Addon{ - Params: []Param{ - { - Name: "resolverTasks", - Value: "false", - }, - }, + expectedParams: map[string]string{ + CommunityResolverTasks: "false", }, }, } - ta.SetDefaults(context.TODO()) - assert.Equal(t, 3, len(ta.Spec.Params)) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ta := &TektonAddon{ + ObjectMeta: metav1.ObjectMeta{ + Name: "name", + Namespace: "namespace", + }, + Spec: TektonAddonSpec{ + CommonSpec: CommonSpec{ + TargetNamespace: "namespace", + }, + Addon: Addon{ + Params: tt.initialParams, + }, + }, + } - params := ParseParams(ta.Spec.Params) - value, ok := params[ResolverTasks] - assert.Equal(t, true, ok) - assert.Equal(t, "false", value) + ta.SetDefaults(context.TODO()) + checkAddonParams(t, ta.Spec.Addon.Params, tt.expectedParams) + }) + } } -func Test_AddonSetDefaults_ResolverStepActions(t *testing.T) { +func checkAddonParams(t *testing.T, actualParams []Param, expectedParams map[string]string) { + t.Helper() - ta := &TektonAddon{ - ObjectMeta: metav1.ObjectMeta{ - Name: "name", - Namespace: "namespace", - }, - Spec: TektonAddonSpec{ - CommonSpec: CommonSpec{ - TargetNamespace: "namespace", - }, - Addon: Addon{ - Params: []Param{ - { - Name: "resolverStepActions", - Value: "false", - }, - }, - }, - }, + if len(actualParams) != len(AddonParams) { + t.Fatalf("Expected %d addon params, got %d", len(AddonParams), len(actualParams)) } - ta.SetDefaults(context.TODO()) - assert.Equal(t, 3, len(ta.Spec.Params)) + paramsMap := ParseParams(actualParams) - params := ParseParams(ta.Spec.Params) - value, ok := params[ResolverStepActions] - assert.Equal(t, true, ok) - assert.Equal(t, "false", value) + for key, expectedValue := range expectedParams { + value, exists := paramsMap[key] + assert.Equal(t, true, exists, "Param %q is missing in Spec.Addon.Params", key) + assert.Equal(t, expectedValue, value, "Param %q has incorrect value", key) + } } diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go index 3a385110b1..d007f894b6 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go @@ -89,8 +89,16 @@ func Test_SetDefaults_Addon_Params(t *testing.T) { t.Setenv("PLATFORM", "openshift") tc.SetDefaults(context.TODO()) - if len(tc.Spec.Addon.Params) != 3 { - t.Error("Setting default failed for TektonConfig (spec.addon.params)") + + if len(tc.Spec.Addon.Params) != len(AddonParams) { + t.Fatalf("Expected %d addon params, got %d", len(AddonParams), len(tc.Spec.Addon.Params)) + } + paramsMap := ParseParams(tc.Spec.Addon.Params) + + for key, expectedValue := range AddonParams { + value, exists := paramsMap[key] + assert.Equal(t, true, exists, "Param %q is missing in Spec.Addon.Params", key) + assert.Equal(t, expectedValue.Default, value, "Param %q has incorrect value", key) } } diff --git a/pkg/reconciler/openshift/tektonaddon/community_tasks.go b/pkg/reconciler/openshift/tektonaddon/community_tasks.go new file mode 100644 index 0000000000..8aaf59ee3c --- /dev/null +++ b/pkg/reconciler/openshift/tektonaddon/community_tasks.go @@ -0,0 +1,87 @@ +/* +Copyright 2024 The Tekton Authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package tektonaddon + +import ( + "context" + "strings" + + mf "github.com/manifestival/manifestival" + "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1" + "github.com/tektoncd/operator/pkg/reconciler/common" + "github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client" +) + +var communityResourceURLs = []string{ + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/jib-maven/0.5/jib-maven.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/helm-upgrade-from-source/0.3/helm-upgrade-from-source.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/helm-upgrade-from-repo/0.2/helm-upgrade-from-repo.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/trigger-jenkins-job/0.1/trigger-jenkins-job.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/pull-request/0.1/pull-request.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/master/task/kubeconfig-creator/0.1/kubeconfig-creator.yaml", + "https://raw.githubusercontent.com/tektoncd/catalog/main/task/argocd-task-sync-and-wait/0.2/argocd-task-sync-and-wait.yaml", +} + +func (r *Reconciler) EnsureCommunityResolverTask(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error { + if len(r.communityResolverTaskManifest.Resources()) == 0 { + return nil + } + manifest := *r.communityResolverTaskManifest + if enable == "true" { + if err := r.installerSetClient.CustomSet(ctx, ta, CommunityResolverTaskInstallerSet, &manifest, filterAndTransformCommunityResolverTask(), nil); err != nil { + return err + } + } else { + if err := r.installerSetClient.CleanupCustomSet(ctx, CommunityResolverTaskInstallerSet); err != nil { + return err + } + } + return nil +} + +func filterAndTransformCommunityResolverTask() client.FilterAndTransform { + return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) { + instance := comp.(*v1alpha1.TektonAddon) + addonImages := common.ToLowerCaseKeys(common.ImagesFromEnv(common.AddonsImagePrefix)) + + extra := []mf.Transformer{ + injectLabel(labelProviderType, providerTypeCommunity, overwrite, "Task"), + common.TaskImages(ctx, addonImages), + } + if err := common.Transform(ctx, manifest, instance, extra...); err != nil { + return nil, err + } + return manifest, nil + } +} + +func appendCommunityResolverTasks(manifest *mf.Manifest) error { + urls := strings.Join(communityResourceURLs, ",") + m, err := mf.ManifestFrom(mf.Path(urls)) + if err != nil { + return err + } + *manifest = manifest.Append(m) + return nil +} + +func fetchCommunityResolverTasks(manifest *mf.Manifest) error { + if err := appendCommunityResolverTasks(manifest); err != nil { + return err + } + return nil +} diff --git a/pkg/reconciler/openshift/tektonaddon/const.go b/pkg/reconciler/openshift/tektonaddon/const.go index 89e56a911b..4f36f33c27 100644 --- a/pkg/reconciler/openshift/tektonaddon/const.go +++ b/pkg/reconciler/openshift/tektonaddon/const.go @@ -22,6 +22,7 @@ const ( OpenShiftConsoleInstallerSet = "OpenShiftConsole" VersionedResolverTaskInstallerSet = "VersionedResolverTask" VersionedResolverStepActionInstallerSet = "VersionedResolverStepAction" + CommunityResolverTaskInstallerSet = "CommunityResolverTask" versionedClusterTaskPatchChar = "0" PipelinesTemplateInstallerSet = "PipelinesTemplate" TriggersResourcesInstallerSet = "TriggersResources" diff --git a/pkg/reconciler/openshift/tektonaddon/controller.go b/pkg/reconciler/openshift/tektonaddon/controller.go index b22dc890ad..a5c497f4bb 100644 --- a/pkg/reconciler/openshift/tektonaddon/controller.go +++ b/pkg/reconciler/openshift/tektonaddon/controller.go @@ -114,21 +114,28 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro logger.Fatalf("failed to read console cli from kodata: %v", err) } + communityResolverTaskManifest := &mf.Manifest{} + if err := fetchCommunityResolverTasks(communityResolverTaskManifest); err != nil { + // if unable to fetch community task, don't fail + logger.Errorf("failed to read community resolver task: %v", err) + } + c := &Reconciler{ - crdClientSet: crdClient, - installerSetClient: client.NewInstallerSetClient(tisClient, version, "addon", v1alpha1.KindTektonAddon, metrics), - operatorClientSet: operatorclient.Get(ctx), - extension: generator(ctx), - pipelineInformer: tektonPipelineinformer.Get(ctx), - triggerInformer: tektonTriggerinformer.Get(ctx), - manifest: manifest, - operatorVersion: version, - resolverTaskManifest: resolverTaskManifest, - resolverStepActionManifest: resolverStepActionManifest, - triggersResourcesManifest: triggersResourcesManifest, - pipelineTemplateManifest: pipelineTemplateManifest, - openShiftConsoleManifest: openShiftConsoleManifest, - consoleCLIManifest: consoleCLIManifest, + crdClientSet: crdClient, + installerSetClient: client.NewInstallerSetClient(tisClient, version, "addon", v1alpha1.KindTektonAddon, metrics), + operatorClientSet: operatorclient.Get(ctx), + extension: generator(ctx), + pipelineInformer: tektonPipelineinformer.Get(ctx), + triggerInformer: tektonTriggerinformer.Get(ctx), + manifest: manifest, + operatorVersion: version, + resolverTaskManifest: resolverTaskManifest, + resolverStepActionManifest: resolverStepActionManifest, + triggersResourcesManifest: triggersResourcesManifest, + pipelineTemplateManifest: pipelineTemplateManifest, + openShiftConsoleManifest: openShiftConsoleManifest, + consoleCLIManifest: consoleCLIManifest, + communityResolverTaskManifest: communityResolverTaskManifest, } impl := tektonAddonreconciler.NewImpl(ctx, c) diff --git a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go index 18735d2381..313628f37d 100644 --- a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go +++ b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go @@ -41,19 +41,20 @@ type Reconciler struct { // installer Set client to do CRUD operations for components installerSetClient *client.InstallerSetClient // crdClientSet allows us to talk to the k8s for core APIs - crdClientSet *apiextensionsclient.Clientset - manifest mf.Manifest - operatorClientSet clientset.Interface - extension common.Extension - pipelineInformer informer.TektonPipelineInformer - triggerInformer informer.TektonTriggerInformer - operatorVersion string - resolverTaskManifest *mf.Manifest - resolverStepActionManifest *mf.Manifest - triggersResourcesManifest *mf.Manifest - pipelineTemplateManifest *mf.Manifest - openShiftConsoleManifest *mf.Manifest - consoleCLIManifest *mf.Manifest + crdClientSet *apiextensionsclient.Clientset + manifest mf.Manifest + operatorClientSet clientset.Interface + extension common.Extension + pipelineInformer informer.TektonPipelineInformer + triggerInformer informer.TektonTriggerInformer + operatorVersion string + resolverTaskManifest *mf.Manifest + resolverStepActionManifest *mf.Manifest + triggersResourcesManifest *mf.Manifest + pipelineTemplateManifest *mf.Manifest + openShiftConsoleManifest *mf.Manifest + consoleCLIManifest *mf.Manifest + communityResolverTaskManifest *mf.Manifest } const ( @@ -64,6 +65,7 @@ const ( providerTypeRedHat = "redhat" installerSetNameForResolverTasks = "addon-versioned-resolvertasks" installerSetNameForResolverStepAction = "addon-versioned-resolverstepactions" + providerTypeCommunity = "community" ) // Check that our Reconciler implements controller.Reconciler @@ -131,6 +133,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon ptVal, _ := findValue(ta.Spec.Params, v1alpha1.PipelineTemplatesParam) rtVal, _ := findValue(ta.Spec.Params, v1alpha1.ResolverTasks) rsaVal, _ := findValue(ta.Spec.Params, v1alpha1.ResolverStepActions) + ctVal, _ := findValue(ta.Spec.Params, v1alpha1.CommunityResolverTasks) if ptVal == "true" && rtVal == "false" { ta.Status.MarkNotReady("pipelineTemplates cannot be true if ResolverTask is false") @@ -203,6 +206,12 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon } } + if err := r.EnsureCommunityResolverTask(ctx, ctVal, ta); err != nil { + ready = false + errorMsg = fmt.Sprintf("community tasks not yet ready: %v", err) + logger.Error(errorMsg) + } + if !ready { ta.Status.MarkInstallerSetNotReady(errorMsg) return nil diff --git a/test/e2e/common/00_tektonconfigdeployment_test.go b/test/e2e/common/00_tektonconfigdeployment_test.go index 869269b26f..0c50d9ea85 100644 --- a/test/e2e/common/00_tektonconfigdeployment_test.go +++ b/test/e2e/common/00_tektonconfigdeployment_test.go @@ -349,6 +349,7 @@ func (s *TektonConfigTestSuite) Test05_DisableAndEnableAddons() { // disable addons and update tc := s.getCurrentConfig(timeout) tc.Spec.Addon.Params = []v1alpha1.Param{ + {Name: v1alpha1.CommunityResolverTasks, Value: "false"}, {Name: v1alpha1.PipelineTemplatesParam, Value: "false"}, } _, err := s.clients.TektonConfig().Update(context.TODO(), tc, metav1.UpdateOptions{}) diff --git a/test/resources/tektonaddons.go b/test/resources/tektonaddons.go index 900a377f85..24ca906aaa 100644 --- a/test/resources/tektonaddons.go +++ b/test/resources/tektonaddons.go @@ -102,6 +102,7 @@ func AssertTektonInstallerSets(t *testing.T, clients *utils.Clients) { assertInstallerSets(t, clients, tektonaddon.TriggersResourcesInstallerSet) assertInstallerSets(t, clients, tektonaddon.ConsoleCLIInstallerSet) assertInstallerSets(t, clients, tektonaddon.MiscellaneousResourcesInstallerSet) + assertInstallerSets(t, clients, tektonaddon.CommunityResolverTaskInstallerSet) } func assertInstallerSets(t *testing.T, clients *utils.Clients, component string) { diff --git a/test/resources/tektonconfigs.go b/test/resources/tektonconfigs.go index b49465fb20..6b771c1f89 100644 --- a/test/resources/tektonconfigs.go +++ b/test/resources/tektonconfigs.go @@ -79,7 +79,7 @@ func EnsureTektonConfigExists(kubeClientSet *kubernetes.Clientset, clients opera Value: "true", }, { - Name: "communityClusterTasks", + Name: "communityResolverTasks", Value: "true", }, },