From 1da6727e55ae1c59aa151383d1de6c8d918b8b1f Mon Sep 17 00:00:00 2001 From: PuneetPunamiya Date: Wed, 27 Nov 2024 19:17:40 +0530 Subject: [PATCH] Adds runtimeclassname support in `options` field for deployment and statefulsets Signed-off-by: PuneetPunamiya --- docs/TektonConfig.md | 10 +- ...ions-base-runtimeclassname-deployment.yaml | 177 +++++++++++++++++ ...ons-base-runtimeclassname-statefulset.yaml | 33 ++++ ...ions-test-runtimeclassname-deployment.yaml | 178 ++++++++++++++++++ ...ons-test-runtimeclassname-statefulset.yaml | 44 +++++ .../common/transformer_additional_options.go | 10 + .../transformer_additional_options_test.go | 54 ++++++ 7 files changed, 502 insertions(+), 4 deletions(-) create mode 100644 pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-deployment.yaml create mode 100644 pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-statefulset.yaml create mode 100644 pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-deployment.yaml create mode 100644 pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-statefulset.yaml diff --git a/docs/TektonConfig.md b/docs/TektonConfig.md index c71e4a36c7..10c4a7188e 100644 --- a/docs/TektonConfig.md +++ b/docs/TektonConfig.md @@ -602,17 +602,18 @@ The following fields are supported in `deployment` * `nodeSelector` - replaces the existing NodeSelector with this, if not empty * `tolerations` - replaces the existing tolerations with this, if not empty * `topologySpreadConstraints` - replaces the existing TopologySpreadConstraints with this, if not empty + * `runtimeClassName` - adds and updates runtimeClassName * `volumes` - adds and updates volumes * `initContainers` - updates init-containers * `resources` - replaces the resources requirements with this, if not empty * `envs` - adds and updates environments * `volumeMounts` - adds and updates VolumeMounts - * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** + * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** * `containers` - updates containers * `resources` - replaces the resources requirements with this, if not empty * `envs` - adds and updates environments * `volumeMounts` - adds and updates VolumeMounts - * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** + * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** #### StatefulSets Supports to update the existing StatefulSet. But not supported to create new StatefulSet. @@ -636,17 +637,18 @@ The following fields are supported in `StatefulSet` * `nodeSelector` - replaces the existing NodeSelector with this, if not empty * `tolerations` - replaces the existing tolerations with this, if not empty * `topologySpreadConstraints` - replaces the existing TopologySpreadConstraints with this, if not empty + * `runtimeClassName` - adds and updates runtimeClassName * `volumes` - adds and updates volumes * `initContainers` - updates init-containers * `resources` - replaces the resources requirements with this, if not empty * `envs` - adds and updates environments * `volumeMounts` - adds and updates VolumeMounts - * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** + * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** * `containers` - updates containers * `resources` - replaces the resources requirements with this, if not empty * `envs` - adds and updates environments * `volumeMounts` - adds and updates VolumeMounts - * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** + * `args` - appends given args with existing arguments. **NOTE: THIS OPERATION DO NOT REPLACE EXISTING ARGS** #### HorizontalPodAutoscalers Supports to update the existing HorizontalPodAutoscaler(HPA) also supports to create new HPA. diff --git a/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-deployment.yaml b/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-deployment.yaml new file mode 100644 index 0000000000..da16cac130 --- /dev/null +++ b/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-deployment.yaml @@ -0,0 +1,177 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: tekton-pipelines + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-defaults + namespace: tekton-pipelines + creationTimestamp: null + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + test: "123" + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-events + namespace: tekton-pipelines + creationTimestamp: null +data: + event1: no-data + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-leader-election + namespace: tekton-pipelines-resolvers + labels: + app.kubernetes.io/component: resolvers + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + buckets: "2" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tekton-pipelines-controller + namespace: tekton-pipelines + creationTimestamp: null + labels: + app.kubernetes.io/name: controller + controlled-by-options: "true" + annotations: + hpa-enabled: "false" +status: {} +spec: + strategy: {} + replicas: 4 + selector: + matchLabels: + app.kubernetes.io/name: controller + template: + metadata: + creationTimestamp: null + annotations: + annotation-foo: annotation-bar + labels: + app.kubernetes.io/name: controller + label-foo: label-bar + operator.tekton.dev/deployment-spec-applied-hash: adf5ca03f3b1b83fa0ccd493ab932fa3 + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: disktype + operator: In + values: + - ssd + - nvme + - ramdisk + priorityClassName: test + serviceAccountName: tekton-pipelines-controller + nodeSelector: + zone: east + tolerations: + - key: zone + operator: Equal + value: west + effect: NoSchedule + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app: foo + matchLabelKeys: + - pod-template-hash + containers: + - name: container-xyz + resources: {} + - name: tekton-pipelines-controller + image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/controller:v0.50.1@sha256:9025991c337374dadce6d49e29fbcf86b233ab8f5f96748c67293b2285c3e0b6 + args: + - "-entrypoint-image" + - "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/entrypoint:v0.50.1@sha256:0c66040a16142a598d5aa9f310b1cbf66e843aa7114188f5d0ab5d36b463a09b" + - "--disable-ha=false" + volumeMounts: + - name: config-logging + mountPath: /etc/config-logging-tmp + - name: config-registry-cert + mountPath: /etc/config-registry-cert + - name: custom-mount + mountPath: /etc/custom-mount + env: + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CONFIG_DEFAULTS_NAME + value: config-defaults + - name: CONFIG_LOGGING_NAME + value: pipeline-config-logging + - name: ENV_FOO + value: bar + - name: ENV_FROM_CONFIG_MAP + valueFrom: + configMapKeyRef: + name: config-map-foo + key: foo + optional: true + resources: + limits: + cpu: "2" + memory: "4Gi" + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + runAsUser: 65532 + runAsGroup: 65532 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + ports: + - name: probes + containerPort: 8080 + livenessProbe: + httpGet: + path: /health + port: probes + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /readiness + port: probes + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + volumes: + - name: config-logging + hostPath: + path: /etc/config-logging + - name: config-registry-cert + configMap: + name: config-registry-cert + - name: my-custom-logs + hostPath: + path: /var/custom/logs + diff --git a/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-statefulset.yaml b/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-statefulset.yaml new file mode 100644 index 0000000000..f135fc00c2 --- /dev/null +++ b/pkg/reconciler/common/testdata/test-additional-options-base-runtimeclassname-statefulset.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: web +spec: + serviceName: "nginx" + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: registry.k8s.io/nginx-slim:0.8 + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: www + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: www + spec: + accessModes: ["ReadWriteOnce"] + resources: + requests: + storage: 1Gi diff --git a/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-deployment.yaml b/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-deployment.yaml new file mode 100644 index 0000000000..483777c4f1 --- /dev/null +++ b/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-deployment.yaml @@ -0,0 +1,178 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: tekton-pipelines + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-defaults + namespace: tekton-pipelines + creationTimestamp: null + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + test: "123" + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-events + namespace: tekton-pipelines + creationTimestamp: null +data: + event1: no-data + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: config-leader-election + namespace: tekton-pipelines-resolvers + labels: + app.kubernetes.io/component: resolvers + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines +data: + buckets: "2" + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tekton-pipelines-controller + namespace: tekton-pipelines + creationTimestamp: null + labels: + app.kubernetes.io/name: controller + controlled-by-options: "true" + annotations: + hpa-enabled: "false" +status: {} +spec: + strategy: {} + replicas: 4 + selector: + matchLabels: + app.kubernetes.io/name: controller + template: + metadata: + creationTimestamp: null + annotations: + annotation-foo: annotation-bar + labels: + app.kubernetes.io/name: controller + label-foo: label-bar + operator.tekton.dev/deployment-spec-applied-hash: dd0dbc85a4f6c0d7170a4a1d0d42e688 + spec: + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: disktype + operator: In + values: + - ssd + - nvme + - ramdisk + priorityClassName: test + runtimeClassName: foo + serviceAccountName: tekton-pipelines-controller + nodeSelector: + zone: east + tolerations: + - key: zone + operator: Equal + value: west + effect: NoSchedule + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + labelSelector: + matchLabels: + app: foo + matchLabelKeys: + - pod-template-hash + containers: + - name: container-xyz + resources: {} + - name: tekton-pipelines-controller + image: gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/controller:v0.50.1@sha256:9025991c337374dadce6d49e29fbcf86b233ab8f5f96748c67293b2285c3e0b6 + args: + - "-entrypoint-image" + - "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/entrypoint:v0.50.1@sha256:0c66040a16142a598d5aa9f310b1cbf66e843aa7114188f5d0ab5d36b463a09b" + - "--disable-ha=false" + volumeMounts: + - name: config-logging + mountPath: /etc/config-logging-tmp + - name: config-registry-cert + mountPath: /etc/config-registry-cert + - name: custom-mount + mountPath: /etc/custom-mount + env: + - name: SYSTEM_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: CONFIG_DEFAULTS_NAME + value: config-defaults + - name: CONFIG_LOGGING_NAME + value: pipeline-config-logging + - name: ENV_FOO + value: bar + - name: ENV_FROM_CONFIG_MAP + valueFrom: + configMapKeyRef: + name: config-map-foo + key: foo + optional: true + resources: + limits: + cpu: "2" + memory: "4Gi" + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" + runAsUser: 65532 + runAsGroup: 65532 + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + ports: + - name: probes + containerPort: 8080 + livenessProbe: + httpGet: + path: /health + port: probes + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /readiness + port: probes + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + timeoutSeconds: 5 + volumes: + - name: config-logging + hostPath: + path: /etc/config-logging + - name: config-registry-cert + configMap: + name: config-registry-cert + - name: my-custom-logs + hostPath: + path: /var/custom/logs + diff --git a/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-statefulset.yaml b/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-statefulset.yaml new file mode 100644 index 0000000000..22bf08d22c --- /dev/null +++ b/pkg/reconciler/common/testdata/test-additional-options-test-runtimeclassname-statefulset.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + creationTimestamp: null + name: web +spec: + serviceName: "nginx" + replicas: 2 + selector: + matchLabels: + app: nginx + template: + metadata: + creationTimestamp: null + labels: + app: nginx + spec: + containers: + - image: registry.k8s.io/nginx-slim:0.8 + name: nginx + ports: + - containerPort: 80 + name: web + resources: {} + volumeMounts: + - mountPath: /usr/share/nginx/html + name: www + runtimeClassName: foo + updateStrategy: {} + volumeClaimTemplates: + - metadata: + creationTimestamp: null + name: www + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi + status: {} +status: + availableReplicas: 0 + replicas: 0 diff --git a/pkg/reconciler/common/transformer_additional_options.go b/pkg/reconciler/common/transformer_additional_options.go index a5279c8817..2ec57c01ac 100644 --- a/pkg/reconciler/common/transformer_additional_options.go +++ b/pkg/reconciler/common/transformer_additional_options.go @@ -311,6 +311,11 @@ func (ot *OptionsTransformer) updateDeployments(u *unstructured.Unstructured) er targetDeployment.Spec.Template.Spec.TopologySpreadConstraints = deploymentOptions.Spec.Template.Spec.TopologySpreadConstraints } + // update runTimeClassName + if deploymentOptions.Spec.Template.Spec.RuntimeClassName != nil { + targetDeployment.Spec.Template.Spec.RuntimeClassName = deploymentOptions.Spec.Template.Spec.RuntimeClassName + } + // update volumes targetDeployment.Spec.Template.Spec.Volumes = ot.updateVolumes(targetDeployment.Spec.Template.Spec.Volumes, deploymentOptions.Spec.Template.Spec.Volumes) @@ -541,6 +546,11 @@ func (ot *OptionsTransformer) updateStatefulSets(u *unstructured.Unstructured) e } } + // update runTimeClassName + if statefulSetOptions.Spec.Template.Spec.RuntimeClassName != nil { + targetStatefulSet.Spec.Template.Spec.RuntimeClassName = statefulSetOptions.Spec.Template.Spec.RuntimeClassName + } + // update volumes targetStatefulSet.Spec.Template.Spec.Volumes = ot.updateVolumes(targetStatefulSet.Spec.Template.Spec.Volumes, statefulSetOptions.Spec.Template.Spec.Volumes) diff --git a/pkg/reconciler/common/transformer_additional_options_test.go b/pkg/reconciler/common/transformer_additional_options_test.go index ea4c3397e5..29af48e423 100644 --- a/pkg/reconciler/common/transformer_additional_options_test.go +++ b/pkg/reconciler/common/transformer_additional_options_test.go @@ -574,6 +574,60 @@ func TestExecuteAdditionalOptionsTransformer(t *testing.T) { inputFilename: "./testdata/test-additional-options-base-webhook.yaml", expectedResultFilename: "./testdata/test-additional-options-test-webhook.yaml", }, + { + name: "test-runtimeclassname-for-deployments", + additionalOptions: v1alpha1.AdditionalOptions{ + Disabled: ptr.Bool(false), + Deployments: map[string]appsv1.Deployment{ + "tekton-pipelines-controller": { + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + RuntimeClassName: ptr.String("foo"), + }, + }, + }, + }, + }, + }, + inputFilename: "./testdata/test-additional-options-base-runtimeclassname-deployment.yaml", + expectedResultFilename: "./testdata/test-additional-options-test-runtimeclassname-deployment.yaml", + }, + { + name: "test-runtimeclassname-for-statefulsets", + additionalOptions: v1alpha1.AdditionalOptions{ + Disabled: ptr.Bool(false), + StatefulSets: map[string]appsv1.StatefulSet{ + "web": { + Spec: appsv1.StatefulSetSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + RuntimeClassName: ptr.String("foo"), + Containers: []corev1.Container{ + { + Resources: corev1.ResourceRequirements{}, + }, + }, + }, + }, + }, + }, + }, + Deployments: map[string]appsv1.Deployment{ + "tekton-pipelines-controller": { + Spec: appsv1.DeploymentSpec{ + Template: corev1.PodTemplateSpec{ + Spec: corev1.PodSpec{ + RuntimeClassName: ptr.String("foo"), + }, + }, + }, + }, + }, + }, + inputFilename: "./testdata/test-additional-options-base-runtimeclassname-statefulset.yaml", + expectedResultFilename: "./testdata/test-additional-options-test-runtimeclassname-statefulset.yaml", + }, } for _, tc := range tcs {