Repository: tektoncd/operator
Pull request #671 (2022-03-10 15:49:31)

[cherry-pick] Catch generate_bundle() error and exit
# Changes

Cherry pick #668 

# Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

- [x] Includes [tests](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if functionality changed/added)
- [x] Includes [docs](https://github.com/tektoncd/community/blob/master/standards.md#principles) (if user facing)
- [x] Commit messages follow [commit message best practices](https://github.com/tektoncd/community/blob/master/standards.md#commit-messages)

_See [the contribution guide](https://github.com/tektoncd/operator/blob/master/CONTRIBUTING.md) for more details._

# Release Notes

```release-note
NONE
```


tekton-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **sm43**
You can assign the PR to them by writing `/assign @sm43` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/tektoncd/operator/blob/release-v0.55.x/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["sm43"]} -->
tekton-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

Approval requirements bypassed by manually added approval.

This pull-request has been approved by:

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=tektoncd%2Foperator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/tektoncd/operator/blob/release-v0.55.x/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["sm43"]} -->

Patch:
diff --git a/Makefile b/Makefile
index 82ef8013e..03fd328e5 100644
--- a/Makefile
+++ b/Makefile
@@ -68,6 +68,7 @@ ifeq ($(TARGET), openshift)
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-chains
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-hub
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/pipelines-as-code
+	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton-addon/addons/02-clustertasks/source_external/
 else
 	rm -rf ./cmd/$(TARGET)/operator/kodata/tekton*
 endif
diff --git a/operatorhub/tools/bundle.py b/operatorhub/tools/bundle.py
index 9e91745a6..6082f66f3 100755
--- a/operatorhub/tools/bundle.py
+++ b/operatorhub/tools/bundle.py
@@ -304,5 +304,7 @@ def divider(title=''):
 if __name__ == "__main__":
     divider("BundleGen")
     config = buildConfig()
-    generate_bundle(config)
+    return_code = generate_bundle(config)
+    if return_code is not 0:
+        exit(return_code)
     newCSVmods(config)
diff --git a/pkg/reconciler/common/transformers.go b/pkg/reconciler/common/transformers.go
index 4d3c84a4e..aac037d60 100644
--- a/pkg/reconciler/common/transformers.go
+++ b/pkg/reconciler/common/transformers.go
@@ -240,7 +240,7 @@ func replaceContainerImages(containers []corev1.Container, images map[string]str
 
 func replaceContainersArgsImage(container *corev1.Container, images map[string]string) {
 	for a, arg := range container.Args {
-		if argVal, hasArg := splitsByEqual(arg); hasArg {
+		if argVal, hasArg := SplitsByEqual(arg); hasArg {
 			argument := formKey(ArgPrefix, argVal[0])
 			if url, exist := images[argument]; exist {
 				container.Args[a] = argVal[0] + "=" + url
@@ -264,7 +264,7 @@ func formKey(prefix, arg string) string {
 	return strings.ReplaceAll(argument, "-", "_")
 }
 
-func splitsByEqual(arg string) ([]string, bool) {
+func SplitsByEqual(arg string) ([]string, bool) {
 	values := strings.Split(arg, "=")
 	if len(values) == 2 {
 		return values, true
diff --git a/pkg/reconciler/kubernetes/tektonhub/tektonhub.go b/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
index 71732be69..bbb4dc4ac 100644
--- a/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
+++ b/pkg/reconciler/kubernetes/tektonhub/tektonhub.go
@@ -425,7 +425,7 @@ func createUiConfigMap(name, namespace string, th *v1alpha1.TektonHub) *corev1.C
 			"API_URL":       th.Status.ApiRouteUrl,
 			"AUTH_BASE_URL": th.Status.AuthRouteUrl,
 			"API_VERSION":   "v1",
-			"REDIRECT_URI":  "https://" + th.Status.UiRouteUrl,
+			"REDIRECT_URI":  th.Status.UiRouteUrl,
 		},
 	}
 }
diff --git a/pkg/reconciler/openshift/tektontrigger/extension.go b/pkg/reconciler/openshift/tektontrigger/extension.go
index 74d28fc81..31e5d498a 100644
--- a/pkg/reconciler/openshift/tektontrigger/extension.go
+++ b/pkg/reconciler/openshift/tektontrigger/extension.go
@@ -43,6 +43,8 @@ func (oe openshiftExtension) Transformers(comp v1alpha1.TektonComponent) []mf.Tr
 		occommon.RemoveRunAsUser(),
 		occommon.RemoveRunAsGroup(),
 		occommon.ApplyCABundles,
+		replaceDeploymentArgs("-el-security-context", "false"),
+		replaceDeploymentArgs("-el-events", "enable"),
 	}
 }
 func (oe openshiftExtension) PreReconcile(ctx context.Context, tc v1alpha1.TektonComponent) error {
diff --git a/pkg/reconciler/openshift/tektontrigger/transformers.go b/pkg/reconciler/openshift/tektontrigger/transformers.go
new file mode 100644
index 000000000..a2bc5bf2b
--- /dev/null
+++ b/pkg/reconciler/openshift/tektontrigger/transformers.go
@@ -0,0 +1,69 @@
+/*
+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 tektontrigger
+
+import (
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	appsv1 "k8s.io/api/apps/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+// replace the value of a deployment arg provided argToReplace and value
+func replaceDeploymentArgs(argToReplace, value string) mf.Transformer {
+	return func(u *unstructured.Unstructured) error {
+		if u.GetKind() != "Deployment" {
+			return nil
+		}
+
+		d := &appsv1.Deployment{}
+		err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, d)
+		if err != nil {
+			return err
+		}
+
+		containers := d.Spec.Template.Spec.Containers
+		for _, container := range containers {
+			if len(container.Args) == 0 {
+				continue
+			}
+			for j, arg := range container.Args {
+				// for scenario when key and value are in single arg e.g. "key=value"
+				if argVal, hasArg := common.SplitsByEqual(arg); hasArg {
+					if argVal[0] == argToReplace {
+						container.Args[j] = argVal[0] + "=" + value
+					}
+					continue
+				}
+				// for scenario, when key and value are in different args, eg. "key","value"
+				if arg == argToReplace {
+					container.Args[j+1] = value
+				}
+			}
+
+		}
+
+		unstrObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(d)
+		if err != nil {
+			return err
+		}
+		u.SetUnstructuredContent(unstrObj)
+
+		return nil
+	}
+}


Test patch:
diff --git a/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-image.yaml b/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-image.yaml
new file mode 100644
index 000000000..0d6b605a4
--- /dev/null
+++ b/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-image.yaml
@@ -0,0 +1,55 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: controller
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      run: test
+  template:
+    metadata:
+      labels:
+        run: test
+    spec:
+      containers:
+        - image: busybox
+          name: controller-deployment
+          args: [
+            "-logtostderr",
+            "-stderrthreshold", "INFO",
+            "-el-image", "ko://github.com/tektoncd/triggers/cmd/eventlistenersink",
+            "-el-port", "8080",
+            "-el-security-context=true",
+            "-el-events", "disable",
+            "-el-readtimeout", "5",
+            "-el-writetimeout", "40",
+            "-el-idletimeout", "120",
+            "-el-timeouthandler", "30",
+          ]
+        - image: busybox
+          name: sidecar
+          args: [
+            "-logtostderr",
+            "-stderrthreshold", "INFO",
+            "-el-image", "ko://github.com/tektoncd/triggers/cmd/eventlistenersink",
+            "-el-port", "8080",
+            "-el-events", "disable",
+            "-el-readtimeout", "5",
+            "-el-writetimeout", "40",
+            "-el-idletimeout", "120",
+            "-el-timeouthandler", "30",
+          ]
+        - image: busybox
+          name: webhook-deployment
+          args: [
+            "-logtostderr",
+            "-stderrthreshold", "INFO",
+            "-el-image", "ko://github.com/tektoncd/triggers/cmd/eventlistenersink",
+            "-el-port", "8080",
+            "-el-events", "disable",
+            "-el-readtimeout", "5",
+            "-el-writetimeout", "40",
+            "-el-idletimeout", "120",
+            "-el-timeouthandler", "30",
+          ]
diff --git a/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-kind.yaml b/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-kind.yaml
new file mode 100644
index 000000000..304962282
--- /dev/null
+++ b/pkg/reconciler/openshift/tektontrigger/testdata/test-replace-kind.yaml
@@ -0,0 +1,12 @@
+apiVersion: tekton.dev/v1alpha1
+kind: Task
+metadata:
+  name: echo-hello-world
+spec:
+  steps:
+  - name: echo
+    image: ubuntu
+    command:
+    - echo
+    args:
+    - "hello world"
diff --git a/pkg/reconciler/openshift/tektontrigger/transformers_test.go b/pkg/reconciler/openshift/tektontrigger/transformers_test.go
new file mode 100644
index 000000000..30d1db291
--- /dev/null
+++ b/pkg/reconciler/openshift/tektontrigger/transformers_test.go
@@ -0,0 +1,100 @@
+/*
+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 tektontrigger
+
+import (
+	"path"
+	"testing"
+
+	"github.com/google/go-cmp/cmp"
+	mf "github.com/manifestival/manifestival"
+	"github.com/tektoncd/operator/pkg/reconciler/common"
+	"github.com/tektoncd/pipeline/test/diff"
+	appsv1 "k8s.io/api/apps/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+)
+
+func TestReplaceImages(t *testing.T) {
+	t.Run("ignore non deployment", func(t *testing.T) {
+		testData := path.Join("testdata", "test-replace-kind.yaml")
+		expected, _ := mf.ManifestFrom(mf.Recursive(testData))
+
+		manifest, err := mf.ManifestFrom(mf.Recursive(testData))
+		if err != nil {
+			t.Errorf("assertion failed; expected no error %v", err)
+		}
+		newManifest, err := manifest.Transform(replaceDeploymentArgs("--test", "value"))
+		if err != nil {
+			t.Errorf("assertion failed; expected no error %v", err)
+		}
+
+		if d := cmp.Diff(expected.Resources(), newManifest.Resources()); d != "" {
+			t.Errorf("failed to update deployment %s", diff.PrintWantGot(d))
+		}
+	})
+
+	t.Run("replace containers args", func(t *testing.T) {
+		testData := path.Join("testdata", "test-replace-image.yaml")
+		manifest, err := mf.ManifestFrom(mf.Recursive(testData))
+		if err != nil {
+			t.Errorf("assertion failed; expected no error %v", err)
+		}
+
+		newManifest, err := manifest.Transform(
+			replaceDeploymentArgs("-el-security-context", "false"),
+			replaceDeploymentArgs("-el-events", "enable"),
+		)
+		if err != nil {
+			t.Errorf("assertion failed; expected no error %v", err)
+		}
+		assertDeployContainerArgsValue(t, newManifest.Resources(), "-el-security-context", "false")
+		assertDeployContainerArgsValue(t, newManifest.Resources(), "-el-events", "enable")
+	})
+}
+
+func assertDeployContainerArgsValue(t *testing.T, resources []unstructured.Unstructured, arg string, value string) {
+	t.Helper()
+
+	for _, resource := range resources {
+		deployment := &appsv1.Deployment{}
+		err := runtime.DefaultUnstructuredConverter.FromUnstructured(resource.Object, deployment)
+		if err != nil {
+			t.Errorf("failed to load deployment yaml")
+		}
+		containers := deployment.Spec.Template.Spec.Containers
+
+		for _, container := range containers {
+			if len(container.Args) == 0 {
+				continue
+			}
+
+			for a, argument := range container.Args {
+				if argVal, hasArg := common.SplitsByEqual(arg); hasArg {
+					if argVal[0] == argument && argVal[1] == value {
+						t.Errorf("not equal: expected %v, got %v", value, argVal[1])
+					}
+					continue
+				}
+
+				if argument == arg && container.Args[a+1] != value {
+					t.Errorf("not equal: expected %v, got %v", value, container.Args[a+1])
+				}
+			}
+		}
+	}
+}