From d69d5a19a35323a264560c7f7f062c9f68617786 Mon Sep 17 00:00:00 2001 From: Piyush Garg Date: Fri, 24 Dec 2021 16:37:24 +0530 Subject: [PATCH] Add field in config to disable hub devconsole integration This will add a struct in config by named hub, where user can add flags and field to set properties related to hub Right now, only one field is available to enable/disable devconsole pipeline builder and hub resources integration on OpenShift, by default the integration is enabled but it can be disabled by adding the field with value false in tektonconfig CR. By default the field will not be there in CR and the integration is enabled. The field getting added is with possible values as true and false. if user provides invalid key and invalid value it will be handled by webhook Also, if the field is not there in CR, webhook will not add it. This patch also add the config CRD view role for all system authenticated users. --- config/base/kustomization.yaml | 2 + config/base/tekton_config_role.yaml | 22 ++++++ config/base/tekton_config_role_binding.yaml | 26 ++++++ docs/TektonConfig.md | 18 +++++ pkg/apis/operator/v1alpha1/const.go | 7 ++ .../operator/v1alpha1/tektonconfig_types.go | 3 + .../v1alpha1/tektonconfig_validation.go | 4 + pkg/apis/operator/v1alpha1/tektonhub_types.go | 28 +++++++ .../operator/v1alpha1/tektonhub_validation.go | 39 +++++++++ .../v1alpha1/tektonhub_validation_test.go | 79 +++++++++++++++++++ .../v1alpha1/zz_generated.deepcopy.go | 22 ++++++ 11 files changed, 250 insertions(+) create mode 100644 config/base/tekton_config_role.yaml create mode 100644 config/base/tekton_config_role_binding.yaml create mode 100644 pkg/apis/operator/v1alpha1/tektonhub_types.go create mode 100644 pkg/apis/operator/v1alpha1/tektonhub_validation.go create mode 100644 pkg/apis/operator/v1alpha1/tektonhub_validation_test.go diff --git a/config/base/kustomization.yaml b/config/base/kustomization.yaml index bb8700f6be..24d7e42f6b 100644 --- a/config/base/kustomization.yaml +++ b/config/base/kustomization.yaml @@ -25,3 +25,5 @@ resources: - role.yaml - role_binding.yaml - operator.yaml +- tekton_config_role.yaml +- tekton_config_role_binding.yaml diff --git a/config/base/tekton_config_role.yaml b/config/base/tekton_config_role.yaml new file mode 100644 index 0000000000..7f558e19e3 --- /dev/null +++ b/config/base/tekton_config_role.yaml @@ -0,0 +1,22 @@ +# Copyright 2022 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. + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: tekton-config-read-role +rules: + - apiGroups: ["operator.tekton.dev"] + resources: ["tektonconfigs"] + verbs: ["get", "watch", "list"] diff --git a/config/base/tekton_config_role_binding.yaml b/config/base/tekton_config_role_binding.yaml new file mode 100644 index 0000000000..621e298b72 --- /dev/null +++ b/config/base/tekton_config_role_binding.yaml @@ -0,0 +1,26 @@ +# Copyright 2022 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. + +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-config-read-rolebinding +subjects: + - kind: Group + apiGroup: rbac.authorization.k8s.io + name: 'system:authenticated' +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-config-read-role diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md index e37caa3fe7..1491e49118 100644 --- a/docs/TektonConfig.md +++ b/docs/TektonConfig.md @@ -54,6 +54,10 @@ The TektonConfig CR provides the following features - pipelinerun keep: 3 schedule: "* * * * *" + hub: + params: + - name: enable-devconsole-integration + value: "true" dashboard: readonly: true ``` @@ -166,6 +170,20 @@ addon: **NOTE**: TektonAddon is currently available for OpenShift Platform only. Enabling this for Kubernetes platform is in roadmap of Operator. +### Hub + +This is to enable/disable showing hub resources in pipeline builder of devconsole(OpenShift UI). By default, the field is +not there in the config object. If you want to disable the integration, you can add the param like below in config with value `false`. +The possible values are `true` and `false`. + +Example: +```yaml +hub: + params: + - name: enable-devconsole-integration + value: "false" +``` + ### Dashboard Dashboard provides configuration options for the Tekton Dashboard if the specified profile value includes the Dashboard component. (E.g. `all` on Kubernetes) diff --git a/pkg/apis/operator/v1alpha1/const.go b/pkg/apis/operator/v1alpha1/const.go index 02da1c189c..9f99c07f4f 100644 --- a/pkg/apis/operator/v1alpha1/const.go +++ b/pkg/apis/operator/v1alpha1/const.go @@ -37,6 +37,9 @@ const ( ClusterTasksParam = "clusterTasks" PipelineTemplatesParam = "pipelineTemplates" + // Hub Params + EnableDevconsoleIntegrationParam = "enable-devconsole-integration" + ApiFieldAlpha = "alpha" ApiFieldStable = "stable" ) @@ -63,6 +66,10 @@ var ( ClusterTasksParam: defaultParamValue, PipelineTemplatesParam: defaultParamValue, } + + HubParams = map[string]ParamValue{ + EnableDevconsoleIntegrationParam: defaultParamValue, + } ) var ( diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_types.go b/pkg/apis/operator/v1alpha1/tektonconfig_types.go index 0af17806aa..5020d72bdf 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_types.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_types.go @@ -80,6 +80,9 @@ type TektonConfigSpec struct { // Addon holds the addons config // +optional Addon Addon `json:"addon,omitempty"` + // Hub holds the hub config + // +optional + Hub Hub `json:"hub,omitempty"` // Pipeline holds the customizable option for pipeline component // +optional Pipeline Pipeline `json:"pipeline,omitempty"` diff --git a/pkg/apis/operator/v1alpha1/tektonconfig_validation.go b/pkg/apis/operator/v1alpha1/tektonconfig_validation.go index 89af6703cc..ea2ebc689c 100644 --- a/pkg/apis/operator/v1alpha1/tektonconfig_validation.go +++ b/pkg/apis/operator/v1alpha1/tektonconfig_validation.go @@ -52,6 +52,10 @@ func (tc *TektonConfig) Validate(ctx context.Context) (errs *apis.FieldError) { errs = errs.Also(validateAddonParams(tc.Spec.Addon.Params, "spec.addon.params")) } + if !tc.Spec.Hub.IsEmpty() { + errs = errs.Also(validateHubParams(tc.Spec.Hub.Params, "spec.hub.params")) + } + errs = errs.Also(tc.Spec.Pipeline.PipelineProperties.validate("spec.pipeline")) return errs.Also(tc.Spec.Trigger.TriggersProperties.validate("spec.trigger")) diff --git a/pkg/apis/operator/v1alpha1/tektonhub_types.go b/pkg/apis/operator/v1alpha1/tektonhub_types.go new file mode 100644 index 0000000000..e0fd68fc7f --- /dev/null +++ b/pkg/apis/operator/v1alpha1/tektonhub_types.go @@ -0,0 +1,28 @@ +/* +Copyright 2022 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 v1alpha1 + +// Hub defines the field to customize Hub component +type Hub struct { + // Params is the list of params passed for Hub customization + // +optional + Params []Param `json:"params,omitempty"` +} + +func (h Hub) IsEmpty() bool { + return len(h.Params) == 0 +} diff --git a/pkg/apis/operator/v1alpha1/tektonhub_validation.go b/pkg/apis/operator/v1alpha1/tektonhub_validation.go new file mode 100644 index 0000000000..180f80aaff --- /dev/null +++ b/pkg/apis/operator/v1alpha1/tektonhub_validation.go @@ -0,0 +1,39 @@ +/* +Copyright 2022 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 v1alpha1 + +import ( + "knative.dev/pkg/apis" +) + +func validateHubParams(params []Param, pathToParams string) *apis.FieldError { + var errs *apis.FieldError + + for i, p := range params { + paramValue, ok := HubParams[p.Name] + if !ok { + errs = errs.Also(apis.ErrInvalidKeyName(p.Name, pathToParams)) + continue + } + if !isValueInArray(paramValue.Possible, p.Value) { + path := pathToParams + "." + p.Name + errs = errs.Also(apis.ErrInvalidArrayValue(p.Value, path, i)) + } + } + + return errs +} diff --git a/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go b/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go new file mode 100644 index 0000000000..d8a53c99fd --- /dev/null +++ b/pkg/apis/operator/v1alpha1/tektonhub_validation_test.go @@ -0,0 +1,79 @@ +/* +Copyright 2022 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 v1alpha1 + +import ( + "context" + "testing" + + "gotest.tools/v3/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func Test_ValidateTektonConfig_InvalidHubParam(t *testing.T) { + + tc := &TektonConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config", + Namespace: "namespace", + }, + Spec: TektonConfigSpec{ + CommonSpec: CommonSpec{ + TargetNamespace: "namespace", + }, + Profile: "all", + Hub: Hub{ + Params: []Param{ + { + Name: "invalid-param", + Value: "val", + }, + }, + }, + }, + } + + err := tc.Validate(context.TODO()) + assert.Equal(t, "invalid key name \"invalid-param\": spec.hub.params", err.Error()) +} + +func Test_ValidateTektonConfig_InvalidHubParamValue(t *testing.T) { + + tc := &TektonConfig{ + ObjectMeta: metav1.ObjectMeta{ + Name: "config", + Namespace: "namespace", + }, + Spec: TektonConfigSpec{ + CommonSpec: CommonSpec{ + TargetNamespace: "namespace", + }, + Profile: "all", + Hub: Hub{ + Params: []Param{ + { + Name: "enable-devconsole-integration", + Value: "test", + }, + }, + }, + }, + } + + err := tc.Validate(context.TODO()) + assert.Equal(t, "invalid value: test: spec.hub.params.enable-devconsole-integration[0]", err.Error()) +} diff --git a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go index 13899ad9bb..7ecb83e856 100644 --- a/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/operator/v1alpha1/zz_generated.deepcopy.go @@ -127,6 +127,27 @@ func (in *DashboardProperties) DeepCopy() *DashboardProperties { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Hub) DeepCopyInto(out *Hub) { + *out = *in + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = make([]Param, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Hub. +func (in *Hub) DeepCopy() *Hub { + if in == nil { + return nil + } + out := new(Hub) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OptionalPipelineProperties) DeepCopyInto(out *OptionalPipelineProperties) { *out = *in @@ -509,6 +530,7 @@ func (in *TektonConfigSpec) DeepCopyInto(out *TektonConfigSpec) { in.Pruner.DeepCopyInto(&out.Pruner) out.CommonSpec = in.CommonSpec in.Addon.DeepCopyInto(&out.Addon) + in.Hub.DeepCopyInto(&out.Hub) in.Pipeline.DeepCopyInto(&out.Pipeline) out.Trigger = in.Trigger out.Dashboard = in.Dashboard