diff --git a/Makefile b/Makefile index eedd5a7b0f..6b44aeb694 100644 --- a/Makefile +++ b/Makefile @@ -66,6 +66,7 @@ ifeq ($(TARGET), openshift) rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-pruner rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/addons/02-clustertasks/source_external/ + rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/addons/07-ecosystem/task-* rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code-templates/go.yaml rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code-templates/java.yaml rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code-templates/nodejs.yaml diff --git a/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/role.yaml b/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/role.yaml new file mode 100644 index 0000000000..492ac848ff --- /dev/null +++ b/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: tekton-ecosystem-task-list-role + namespace: openshift-pipelines +rules: + - apiGroups: + - tekton.dev + resources: + - tasks + verbs: + - get + - list diff --git a/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/rolebinding.yaml b/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/rolebinding.yaml new file mode 100644 index 0000000000..d35d8fcf8e --- /dev/null +++ b/cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem/rolebinding.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: tekton-ecosystem-task-list-binding + namespace: openshift-pipelines +subjects: + # Giving all system:authenticated users the access to the + # tasks present in openshift-pipelines namespace + - kind: Group + name: system:authenticated + apiGroup: rbac.authorization.k8s.io +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: tekton-ecosystem-task-list-role 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 399c153218..ff3943a0be 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: communityClusterTasks value: "true" + - name: resolverTasks + value: "true" params: - name: createRbacResource value: "true" diff --git a/docs/TektonAddon.md b/docs/TektonAddon.md index 91093522ff..33cf7bde8e 100644 --- a/docs/TektonAddon.md +++ b/docs/TektonAddon.md @@ -6,7 +6,8 @@ weight: 6 --> # Tekton Addon -TektonAddon custom resource allows user to install resource like clusterTasks and pipelineTemplate along with Pipelines. +TektonAddon custom resource allows user to install resource like clusterTasks 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. @@ -25,6 +26,8 @@ spec: value: "true" - name: pipelineTemplates value: "true" + - name: resolverTasks + value: "true" ``` You can install this component using [TektonConfig](./TektonConfig.md) by choosing appropriate `profile`. @@ -35,6 +38,7 @@ Available params are - `clusterTasks` (Default: `true`) - `pipelineTemplates` (Default: `true`) +- `resolverTasks` (Default: `true`) User can disable the installation of resources by changing the value to `false`. diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md index 0911c0a37c..6c3c0f8801 100644 --- a/docs/TektonConfig.md +++ b/docs/TektonConfig.md @@ -319,7 +319,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 ClusterTasks, PipelineTemplates. +TektonAddon install some resources along with Tekton Pipelines on the cluster. This provides few ClusterTasks, PipelineTemplates, Tasks. This section allows to customize installation of those resources through params. You can read more about the supported params [here](./TektonAddon.md). @@ -331,6 +331,8 @@ addon: value: "true" - name: "pipelineTemplates" value: "true" + - name: "resolverTasks" + value: "true" ``` **NOTE**: TektonAddon is currently available for OpenShift Platform only. Enabling this for Kubernetes platform is in roadmap diff --git a/hack/fetch-releases.sh b/hack/fetch-releases.sh index cb35b90414..91d858fa41 100755 --- a/hack/fetch-releases.sh +++ b/hack/fetch-releases.sh @@ -227,6 +227,8 @@ fetch_openshift_addon_tasks() { fetch_addon_task_script="${SCRIPT_DIR}/hack/openshift" local dest_dir="cmd/openshift/operator/kodata/tekton-addon/addons/02-clustertasks/source_external" ${fetch_addon_task_script}/fetch-tektoncd-catalog-tasks.sh ${dest_dir} + dest_dir='cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem' + ${fetch_addon_task_script}/fetch-tektoncd-catalog-tasks.sh ${dest_dir} "ecosystem" } copy_pruner_yaml() { diff --git a/hack/openshift/fetch-tektoncd-catalog-tasks.sh b/hack/openshift/fetch-tektoncd-catalog-tasks.sh index 60bccdee6d..8ab01eaec0 100755 --- a/hack/openshift/fetch-tektoncd-catalog-tasks.sh +++ b/hack/openshift/fetch-tektoncd-catalog-tasks.sh @@ -53,6 +53,28 @@ declare -A TEKTON_CATALOG_TASKS=( # ["buildah"]="0.1" # ["openshift-client"]="0.2" ) +declare -r TEKTON_ECOSYSTEM="https://raw.githubusercontent.com/openshift-pipelines/tektoncd-catalog" +declare -A TEKTON_ECOSYSTEM_TASKS=( + ['task-buildah']="0.3.1" + ['task-git-cli']="0.3.0" + ['task-git-clone']='0.3.0' + ['task-kn-apply']='0.1.0' + ['task-kn']='0.1.0' + ['task-maven']="0.2.1" + ['task-opc']="0.1.0" + ['task-openshift-client']="0.1.0" + ['task-s2i-dotnet']='0.3.1' + ['task-s2i-go']='0.3.1' + ['task-s2i-java']='0.3.1' + ['task-s2i-nodejs']='0.3.1' + ['task-s2i-perl']='0.3.1' + ['task-s2i-php']='0.3.1' + ['task-s2i-python']='0.3.1' + ['task-s2i-ruby']='0.3.1' + ['task-skopeo-copy']='0.3.1' + ['task-tkn']='0.1.0' + ['task-buildpacks']='0.1.0' +) download_task() { local task_path="$1"; shift @@ -82,15 +104,18 @@ get_tasks() { local dest_dir="$1"; shift local catalog="$1"; shift local catalog_version="$1"; shift - local -n tasks=$1 - + local -n tasks=$1; shift + local type="$1" info "Downloading tasks from catalog $catalog to $dest_dir directory" for t in ${!tasks[@]} ; do # task filenames do not follow a naming convention, # some are taskname.yaml while others are taskname-task.yaml # so, try both before failing - local task_url="$catalog/$catalog_version/task/$t/${tasks[$t]}/${t}.yaml" - echo "$catalog/$catalog_version/task/$t/${tasks[$t]}/${t}.yaml" + if [[ "$type" == "ecosystem" ]]; then + local task_url="$catalog/$catalog_version/tasks/$t/${tasks[$t]}/${t}.yaml" + elif [[ "$type" == 'default' ]];then + local task_url="$catalog/$catalog_version/task/$t/${tasks[$t]}/${t}.yaml" + fi mkdir -p "$dest_dir/$t/" local task_path="$dest_dir/$t/$t-task.yaml" @@ -107,14 +132,31 @@ create_dir_or_die() { } main() { - - local dest_dir=${1:-'cmd/openshift/operator/kodata/tekton-addon/addons/02-clustertasks/source_external'} + local type=${2:-"default"} + + if [[ "$type" == "default" ]]; then + local dest_dir=${1:-'cmd/openshift/operator/kodata/tekton-addon/addons/02-clustertasks/source_external'} + local tasks=TEKTON_CATALOG_TASKS + local branch="main" + local catalog="$TEKTON_CATALOG" + + elif [[ "$type" == "ecosystem" ]]; then + local dest_dir=${1:-'cmd/openshift/operator/kodata/tekton-addon/addons/07-ecosystem'} + local tasks=TEKTON_ECOSYSTEM_TASKS + local branch="p" + local catalog="$TEKTON_ECOSYSTEM" + + else + echo "Invalid type specified: $type" + return $? + fi + [[ -z "$dest_dir" ]] && usage "missing destination directory" shift [[ ! -d "$dest_dir" ]] && create_dir_or_die "$dest_dir" || echo "$dest_dir" exists - get_tasks "$dest_dir" "$TEKTON_CATALOG" "main" TEKTON_CATALOG_TASKS + get_tasks "$dest_dir" $catalog $branch $tasks $type return $? } diff --git a/pkg/apis/operator/v1alpha1/const.go b/pkg/apis/operator/v1alpha1/const.go index b533570492..c1c40d544e 100644 --- a/pkg/apis/operator/v1alpha1/const.go +++ b/pkg/apis/operator/v1alpha1/const.go @@ -36,6 +36,7 @@ const ( ClusterTasksParam = "clusterTasks" PipelineTemplatesParam = "pipelineTemplates" CommunityClusterTasks = "communityClusterTasks" + ResolverTasks = "resolverTasks" // Hub Params EnableDevconsoleIntegrationParam = "enable-devconsole-integration" @@ -112,6 +113,7 @@ var ( ClusterTasksParam: defaultParamValue, PipelineTemplatesParam: defaultParamValue, CommunityClusterTasks: defaultParamValue, + ResolverTasks: defaultParamValue, } HubParams = map[string]ParamValue{ diff --git a/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go b/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go index 71b805ab06..fec01b535e 100644 --- a/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go +++ b/pkg/apis/operator/v1alpha1/tektonaddon_default_test.go @@ -39,7 +39,7 @@ func Test_AddonSetDefaults_DefaultParamsWithValues(t *testing.T) { } ta.SetDefaults(context.TODO()) - assert.Equal(t, 3, len(ta.Spec.Params)) + assert.Equal(t, 4, len(ta.Spec.Params)) params := ParseParams(ta.Spec.Params) value, ok := params[ClusterTasksParam] @@ -70,7 +70,7 @@ func Test_AddonSetDefaults_ClusterTaskIsFalse(t *testing.T) { } ta.SetDefaults(context.TODO()) - assert.Equal(t, 3, len(ta.Spec.Params)) + assert.Equal(t, 4, len(ta.Spec.Params)) params := ParseParams(ta.Spec.Params) value, ok := params[PipelineTemplatesParam] diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go index 5849393ebf..764e460edc 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_default_test.go @@ -90,7 +90,7 @@ func Test_SetDefaults_Addon_Params(t *testing.T) { t.Setenv("PLATFORM", "openshift") tc.SetDefaults(context.TODO()) - if len(tc.Spec.Addon.Params) != 3 { + if len(tc.Spec.Addon.Params) != 4 { t.Error("Setting default failed for TektonConfig (spec.addon.params)") } } diff --git a/pkg/reconciler/openshift/tektonaddon/const.go b/pkg/reconciler/openshift/tektonaddon/const.go index 07717caa31..54691edb77 100644 --- a/pkg/reconciler/openshift/tektonaddon/const.go +++ b/pkg/reconciler/openshift/tektonaddon/const.go @@ -17,6 +17,7 @@ limitations under the License. package tektonaddon const ( + ResolverTaskInstallerSet = "ResolverTask" ClusterTaskInstallerSet = "ClusterTask" OpenShiftConsoleInstallerSet = "OpenShiftConsole" CommunityClusterTaskInstallerSet = "CommunityClusterTask" diff --git a/pkg/reconciler/openshift/tektonaddon/controller.go b/pkg/reconciler/openshift/tektonaddon/controller.go index f53ab04bb8..296d5e5f23 100644 --- a/pkg/reconciler/openshift/tektonaddon/controller.go +++ b/pkg/reconciler/openshift/tektonaddon/controller.go @@ -78,6 +78,11 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro tisClient := operatorclient.Get(ctx).OperatorV1alpha1().TektonInstallerSets() metrics, _ := NewRecorder() + resolverTaskManifest := &mf.Manifest{} + if err := applyAddons(resolverTaskManifest, "07-ecosystem"); err != nil { + logger.Fatalf("failed to read namespaced tasks from kodata: %v", err) + } + clusterTaskManifest := &mf.Manifest{} if err := applyAddons(clusterTaskManifest, "02-clustertasks"); err != nil { logger.Fatalf("failed to read clustertask from kodata: %v", err) @@ -124,6 +129,7 @@ func NewExtendedController(generator common.ExtensionGenerator) injection.Contro triggerInformer: tektonTriggerinformer.Get(ctx), manifest: manifest, operatorVersion: version, + resolverTaskManifest: resolverTaskManifest, clusterTaskManifest: clusterTaskManifest, triggersResourcesManifest: triggersResourcesManifest, pipelineTemplateManifest: pipelineTemplateManifest, diff --git a/pkg/reconciler/openshift/tektonaddon/resolverTask.go b/pkg/reconciler/openshift/tektonaddon/resolverTask.go new file mode 100644 index 0000000000..552ea1334e --- /dev/null +++ b/pkg/reconciler/openshift/tektonaddon/resolverTask.go @@ -0,0 +1,52 @@ +/* +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" + + mf "github.com/manifestival/manifestival" + "github.com/tektoncd/operator/pkg/apis/operator/v1alpha1" + "github.com/tektoncd/operator/pkg/reconciler/kubernetes/tektoninstallerset/client" +) + +func (r *Reconciler) EnsureResolverTask(ctx context.Context, enable string, ta *v1alpha1.TektonAddon) error { + manifest := *r.resolverTaskManifest + if enable == "true" { + if err := r.installerSetClient.CustomSet(ctx, ta, ResolverTaskInstallerSet, &manifest, filterAndTransformResolverTask(), nil); err != nil { + return err + } + } else { + if err := r.installerSetClient.CleanupCustomSet(ctx, ResolverTaskInstallerSet); err != nil { + return err + } + } + return nil +} + +func filterAndTransformResolverTask() client.FilterAndTransform { + return func(ctx context.Context, manifest *mf.Manifest, comp v1alpha1.TektonComponent) (*mf.Manifest, error) { + addon := comp.(*v1alpha1.TektonAddon) + tfs := []mf.Transformer{ + injectLabel(labelProviderType, providerTypeRedHat, overwrite, "Task"), + } + if err := transformers(ctx, manifest, addon, tfs...); err != nil { + return nil, err + } + return manifest, nil + } +} diff --git a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go index 123aa97eb4..df060c6df7 100644 --- a/pkg/reconciler/openshift/tektonaddon/tektonaddon.go +++ b/pkg/reconciler/openshift/tektonaddon/tektonaddon.go @@ -48,6 +48,7 @@ type Reconciler struct { pipelineInformer informer.TektonPipelineInformer triggerInformer informer.TektonTriggerInformer operatorVersion string + resolverTaskManifest *mf.Manifest clusterTaskManifest *mf.Manifest triggersResourcesManifest *mf.Manifest pipelineTemplateManifest *mf.Manifest @@ -130,6 +131,7 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon ptVal, _ := findValue(ta.Spec.Params, v1alpha1.PipelineTemplatesParam) ctVal, _ := findValue(ta.Spec.Params, v1alpha1.ClusterTasksParam) cctVal, _ := findValue(ta.Spec.Params, v1alpha1.CommunityClusterTasks) + rtVal, _ := findValue(ta.Spec.Params, v1alpha1.ResolverTasks) if ptVal == "true" && ctVal == "false" { ta.Status.MarkNotReady("pipelineTemplates cannot be true if clusterTask is false") @@ -151,6 +153,12 @@ func (r *Reconciler) ReconcileKind(ctx context.Context, ta *v1alpha1.TektonAddon ready := true var errorMsg string + if err := r.EnsureResolverTask(ctx, rtVal, ta); err != nil { + ready = false + errorMsg = fmt.Sprintf("namespaced tasks not yet ready: %v", err) + logger.Error(errorMsg) + } + if err := r.EnsureClusterTask(ctx, ctVal, ta); err != nil { ready = false errorMsg = fmt.Sprintf("cluster tasks not yet ready: %v", err)