diff --git a/charts/library/common-test/ci/advanced-values.yaml b/charts/library/common-test/ci/advanced-values.yaml index bf961c464..d58ece458 100644 --- a/charts/library/common-test/ci/advanced-values.yaml +++ b/charts/library/common-test/ci/advanced-values.yaml @@ -95,3 +95,16 @@ persistence: - path: /data/config.yaml readOnly: false subPath: config.yaml + +rawResources: + unsupportedPDB: + enabled: true + nameOverride: pdb + apiVersion: policy/v1 + kind: PodDisruptionBudget + spec: + spec: + minAvailable: 1 + selector: + matchLabels: + app.kubernetes.io/instance: "{{ .Release.Name }}" diff --git a/charts/library/common-test/tests/rawResource/metadata_test.yaml b/charts/library/common-test/tests/rawResource/metadata_test.yaml new file mode 100644 index 000000000..960cffc13 --- /dev/null +++ b/charts/library/common-test/tests/rawResource/metadata_test.yaml @@ -0,0 +1,98 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +suite: rawResource metadata +templates: + - common.yaml +values: + - ../_values/controllers_main_default_container.yaml +set: + rawResources: + config: + apiVersion: v1 + kind: Endpoint + spec: + test: test +tests: + - it: default metadata should pass + asserts: + - hasDocuments: + count: 2 + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + notExists: + path: metadata.annotations + - documentIndex: *rawResourceDocument + equal: + path: metadata.labels + value: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: RELEASE-NAME + helm.sh/chart: common-test-1.0.0 + + - it: custom metadata should pass + set: + rawResources: + config: + annotations: + test_annotation: test + labels: + test_label: test + asserts: + - hasDocuments: + count: 2 + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: metadata.annotations + value: + test_annotation: test + - documentIndex: *rawResourceDocument + equal: + path: metadata.labels + value: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: RELEASE-NAME + helm.sh/chart: common-test-1.0.0 + test_label: test + + - it: custom metadata with global metadata should pass + set: + global: + labels: + global_label: test + annotations: + global_annotation: test + rawResources: + config: + annotations: + test_annotation: test + labels: + test_label: test + asserts: + - hasDocuments: + count: 2 + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: metadata.annotations + value: + global_annotation: test + test_annotation: test + - documentIndex: *rawResourceDocument + equal: + path: metadata.labels + value: + app.kubernetes.io/instance: RELEASE-NAME + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: RELEASE-NAME + global_label: test + helm.sh/chart: common-test-1.0.0 + test_label: test diff --git a/charts/library/common-test/tests/rawResource/values_test.yaml b/charts/library/common-test/tests/rawResource/values_test.yaml new file mode 100644 index 000000000..d8d104664 --- /dev/null +++ b/charts/library/common-test/tests/rawResource/values_test.yaml @@ -0,0 +1,78 @@ +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/helm-unittest/helm-unittest/main/schema/helm-testsuite.json +suite: rawResource values +templates: + - common.yaml +values: + - ../_values/controllers_main_default_container.yaml +set: + rawResources: + endpoint: + apiVersion: v1 + kind: Endpoint + spec: + subsets: + - addresses: + - ip: 127.0.0.1 + ports: + - name: "{{ .Release.Name }}" + port: 443 + protocol: TCP +tests: + - it: default should pass + asserts: + - hasDocuments: + count: 2 + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: subsets[0].addresses[0].ip + value: 127.0.0.1 + + - it: nameOverride should pass + set: + rawResources.endpoint: + nameOverride: test + asserts: + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: metadata.name + value: RELEASE-NAME-test + + - it: nameOverride with template should pass + set: + rawResources.endpoint: + nameOverride: "{{ .Release.Name }}" + asserts: + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: metadata.name + value: RELEASE-NAME + + - it: spec with template should pass + set: + rawResources.endpoint: + spec: + subsets: + - addresses: + - ip: 127.0.0.1 + ports: + - name: "{{ .Release.Name }}" + port: 443 + protocol: TCP + asserts: + - documentIndex: &rawResourceDocument 1 + isKind: + of: Endpoint + - documentIndex: *rawResourceDocument + equal: + path: subsets[0].ports[0].name + value: RELEASE-NAME diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 5be93be96..22636643a 100644 --- a/charts/library/common/Chart.yaml +++ b/charts/library/common/Chart.yaml @@ -3,7 +3,7 @@ apiVersion: v2 name: common description: Function library for Helm charts type: library -version: 3.2.1 +version: 3.3.0 kubeVersion: ">=1.22.0-0" keywords: - common @@ -16,16 +16,16 @@ annotations: artifacthub.io/changes: |- - kind: added description: |- - Support templating in annotation and label values for all objects (fixed in v3.2.1) + Added support for specifying unsupported raw resources. - kind: added description: |- - Support activeDeadlineSeconds field on CronJobs and Jobs + Added `stdin` and `tty` fields to container spec. - kind: added description: |- - Support excluding secrets and configMaps from pod checksum annotation + Added `persistentVolumeClaimRetentionPolicy` field to statefulset spec. - kind: fixed description: |- - Fixed failing ServiceMonitor test + Added `externalName` field to service schema. - kind: fixed description: |- - Fixed networkPolicies not rendering correctly + Always allow specifying `nodePort` field on service ports. diff --git a/charts/library/common/README.md b/charts/library/common/README.md index 4fb861d54..a00b40394 100644 --- a/charts/library/common/README.md +++ b/charts/library/common/README.md @@ -1,6 +1,6 @@ # common -![Version: 3.2.1](https://img.shields.io/badge/Version-3.2.1-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) +![Version: 3.3.0](https://img.shields.io/badge/Version-3.3.0-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) Function library for Helm charts @@ -27,7 +27,7 @@ Include this chart as a dependency in your `Chart.yaml` e.g. # Chart.yaml dependencies: - name: common - version: 3.2.1 + version: 3.3.0 repository: https://bjw-s.github.io/helm-charts/ ``` diff --git a/charts/library/common/schemas/containers.json b/charts/library/common/schemas/containers.json index e56ca809c..f3806618a 100644 --- a/charts/library/common/schemas/containers.json +++ b/charts/library/common/schemas/containers.json @@ -149,6 +149,10 @@ "securityContext": { "$ref": "k8s-api.json#/core.v1.ContainerSecurityContext" }, + "stdin": { + "type": "boolean", + "default": false + }, "terminationMessagePath": { "type": "string" }, @@ -156,6 +160,10 @@ "type": "string", "enum": ["File", "FallbackToLogsOnError"] }, + "tty": { + "type": "boolean", + "default": false + }, "workingDir": { "type": "string" } diff --git a/charts/library/common/schemas/controllers.json b/charts/library/common/schemas/controllers.json index b792b8ad0..73c67899f 100644 --- a/charts/library/common/schemas/controllers.json +++ b/charts/library/common/schemas/controllers.json @@ -146,6 +146,22 @@ "podManagementPolicy": { "type": "string" }, + "persistentVolumeClaimRetentionPolicy": { + "type": "object", + "additionalProperties": false, + "properties": { + "whenDeleted": { + "type": "string", + "enum": ["Delete", "Retain"], + "default": "Retain" + }, + "whenScaled": { + "type": "string", + "enum": ["Delete", "Retain"], + "default": "Retain" + } + } + }, "volumeClaimTemplates": { "type": "array", "items": { diff --git a/charts/library/common/schemas/rawResource.json b/charts/library/common/schemas/rawResource.json new file mode 100644 index 000000000..72661c917 --- /dev/null +++ b/charts/library/common/schemas/rawResource.json @@ -0,0 +1,29 @@ +{ + "instance": { + "type": "object", + "additionalProperties": false, + "properties": { + "enabled": { + "type": "boolean", + "default": true + }, + "apiVersion": { + "type": "string" + }, + "kind": { + "type": "string" + }, + "annotations": { + "$ref": "definitions.json#/annotations" + }, + "labels": { + "$ref": "definitions.json#/labels" + }, + "nameOverride": { + "type": "string" + }, + "spec": {} + }, + "required": ["apiVersion", "kind", "spec"] + } +} diff --git a/charts/library/common/schemas/service.json b/charts/library/common/schemas/service.json index cff7f79b9..785fce393 100644 --- a/charts/library/common/schemas/service.json +++ b/charts/library/common/schemas/service.json @@ -22,6 +22,9 @@ "clusterIP": { "type": "string" }, + "externalName": { + "type": "string" + }, "loadBalancerIP": { "type": "string" }, diff --git a/charts/library/common/templates/classes/_rawResource.tpl b/charts/library/common/templates/classes/_rawResource.tpl new file mode 100644 index 000000000..016519a41 --- /dev/null +++ b/charts/library/common/templates/classes/_rawResource.tpl @@ -0,0 +1,37 @@ +{{/* +This template serves as a blueprint for all raw resource objects that are created +within the common library. +*/}} +{{- define "bjw-s.common.class.rawResource" -}} + {{- $rootContext := .rootContext -}} + {{- $resourceObject := .object -}} + + {{- $labels := merge + ($resourceObject.labels | default dict) + (include "bjw-s.common.lib.metadata.allLabels" $rootContext | fromYaml) + -}} + {{- $annotations := merge + ($resourceObject.annotations | default dict) + (include "bjw-s.common.lib.metadata.globalAnnotations" $rootContext | fromYaml) + -}} +--- +apiVersion: {{ $resourceObject.apiVersion }} +kind: {{ $resourceObject.kind }} +metadata: + name: {{ $resourceObject.name }} + {{- with $labels }} + labels: + {{- range $key, $value := . }} + {{- printf "%s: %s" $key (tpl $value $rootContext | toYaml ) | nindent 4 }} + {{- end }} + {{- end }} + {{- with $annotations }} + annotations: + {{- range $key, $value := . }} + {{- printf "%s: %s" $key (tpl $value $rootContext | toYaml ) | nindent 4 }} + {{- end }} + {{- end }} +{{- with $resourceObject.spec }} + {{- tpl (toYaml .) $rootContext | nindent 0 }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/classes/_service.tpl b/charts/library/common/templates/classes/_service.tpl index cb17c96ce..efcee403e 100644 --- a/charts/library/common/templates/classes/_service.tpl +++ b/charts/library/common/templates/classes/_service.tpl @@ -93,7 +93,7 @@ spec: protocol: TCP {{- end }} name: {{ $name }} - {{- if (and (eq $svcType "NodePort") (not (empty $port.nodePort))) }} + {{- if (not (empty $port.nodePort)) }} nodePort: {{ $port.nodePort }} {{ end }} {{- if (not (empty $port.appProtocol)) }} diff --git a/charts/library/common/templates/classes/_statefulset.tpl b/charts/library/common/templates/classes/_statefulset.tpl index 706795551..ef9bddc46 100644 --- a/charts/library/common/templates/classes/_statefulset.tpl +++ b/charts/library/common/templates/classes/_statefulset.tpl @@ -47,6 +47,9 @@ spec: app.kubernetes.io/component: {{ $statefulsetObject.identifier }} {{- include "bjw-s.common.lib.metadata.selectorLabels" $rootContext | nindent 6 }} serviceName: {{ include "bjw-s.common.lib.chart.names.fullname" $rootContext }} + {{- with (dig "statefulset" "persistentVolumeClaimRetentionPolicy" nil $statefulsetObject) }} + persistentVolumeClaimRetentionPolicy: {{ . | toYaml | nindent 4 }} + {{- end }} template: metadata: {{- with (include "bjw-s.common.lib.pod.metadata.annotations" (dict "rootContext" $rootContext "controllerObject" $statefulsetObject)) }} diff --git a/charts/library/common/templates/lib/container/_spec.tpl b/charts/library/common/templates/lib/container/_spec.tpl index e0e085716..e199c614c 100644 --- a/charts/library/common/templates/lib/container/_spec.tpl +++ b/charts/library/common/templates/lib/container/_spec.tpl @@ -50,6 +50,12 @@ resources: {{ toYaml . | trim | nindent 2 }} {{- end -}} {{- with $containerObject.restartPolicy }} restartPolicy: {{ . | trim }} + {{- end -}} + {{- with $containerObject.stdin }} +stdin: {{ . | trim }} + {{- end -}} + {{- with $containerObject.tty }} +tty: {{ . | trim }} {{- end -}} {{- with (include "bjw-s.common.lib.container.field.volumeMounts" (dict "ctx" $ctx) | trim) }} volumeMounts: {{ . | trim | nindent 2 }} diff --git a/charts/library/common/templates/lib/rawResource/_validate.tpl b/charts/library/common/templates/lib/rawResource/_validate.tpl new file mode 100644 index 000000000..241e3be39 --- /dev/null +++ b/charts/library/common/templates/lib/rawResource/_validate.tpl @@ -0,0 +1,7 @@ +{{/* +Validate raw resource values +*/}} +{{- define "bjw-s.common.lib.rawResource.validate" -}} + {{- $rootContext := .rootContext -}} + {{- $resourceObject := .object -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl b/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl new file mode 100644 index 000000000..52b5e36a1 --- /dev/null +++ b/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl @@ -0,0 +1,27 @@ +{{/* +Convert raw resource values to an object +*/}} +{{- define "bjw-s.common.lib.rawResource.valuesToObject" -}} + {{- $rootContext := .rootContext -}} + {{- $identifier := .id -}} + {{- $objectValues := .values -}} + + {{- /* Determine and inject the raw resource name */ -}} + {{- $objectName := (include "bjw-s.common.lib.chart.names.fullname" $rootContext) -}} + + {{- if $objectValues.nameOverride -}} + {{- $override := tpl $objectValues.nameOverride $rootContext -}} + {{- if not (eq $objectName $override) -}} + {{- $objectName = printf "%s-%s" $objectName $override -}} + {{- end -}} + {{- else -}} + {{- if not (eq $objectName $identifier) -}} + {{- $objectName = printf "%s-%s" $objectName $identifier -}} + {{- end -}} + {{- end -}} + {{- $_ := set $objectValues "name" $objectName -}} + {{- $_ := set $objectValues "identifier" $identifier -}} + + {{- /* Return the raw resource object */ -}} + {{- $objectValues | toYaml -}} +{{- end -}} diff --git a/charts/library/common/templates/loader/_generate.tpl b/charts/library/common/templates/loader/_generate.tpl index 8788d4d19..62657304c 100644 --- a/charts/library/common/templates/loader/_generate.tpl +++ b/charts/library/common/templates/loader/_generate.tpl @@ -16,4 +16,5 @@ Secondary entrypoint and primary loader for the common chart {{- include "bjw-s.common.render.configMaps" . | nindent 0 -}} {{- include "bjw-s.common.render.secrets" . | nindent 0 -}} {{- include "bjw-s.common.render.networkpolicies" . | nindent 0 -}} + {{- include "bjw-s.common.render.rawResources" . | nindent 0 -}} {{- end -}} diff --git a/charts/library/common/templates/render/_rawResources.tpl b/charts/library/common/templates/render/_rawResources.tpl new file mode 100644 index 000000000..f3e3a12c2 --- /dev/null +++ b/charts/library/common/templates/render/_rawResources.tpl @@ -0,0 +1,26 @@ +{{/* +Renders other arbirtrary objects required by the chart. +*/}} +{{- define "bjw-s.common.render.rawResources" -}} + {{- /* Generate pvc as required */ -}} + {{- range $key, $resource := .Values.rawResources -}} + {{- /* Enable by default, but allow override */ -}} + {{- $resourceEnabled := true -}} + {{- if hasKey $resource "enabled" -}} + {{- $resourceEnabled = $resource.enabled -}} + {{- end -}} + + {{- if $resourceEnabled -}} + {{- $resourceValues := (mustDeepCopy $resource) -}} + + {{- /* Create object from the raw resource values */ -}} + {{- $resourceObject := (include "bjw-s.common.lib.rawResource.valuesToObject" (dict "rootContext" $ "id" $key "values" $resourceValues)) | fromYaml -}} + + {{- /* Perform validations on the resource before rendering */ -}} + {{- include "bjw-s.common.lib.rawResource.validate" (dict "rootContext" $ "object" $resourceValues) -}} + + {{- /* Include the raw resource class */ -}} + {{- include "bjw-s.common.class.rawResource" (dict "rootContext" $ "object" $resourceValues) | nindent 0 -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/values.schema.json b/charts/library/common/values.schema.json index 2acdadde3..17f0cd1ee 100644 --- a/charts/library/common/values.schema.json +++ b/charts/library/common/values.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema", - "$id": "https://raw.githubusercontent.com/bjw-s/helm-charts/common-3.2.1/charts/library/common/values.schema.json", + "$id": "https://raw.githubusercontent.com/bjw-s/helm-charts/common-3.3.0/charts/library/common/values.schema.json", "type": "object", "properties": { @@ -71,6 +71,11 @@ "additionalProperties": { "$ref": "schemas/persistence.json#/item" } + }, + "rawResources": { + "additionalProperties": { + "$ref": "schemas/rawResource.json#/instance" + } } } } diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index e5d6ac110..915d2eb71 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -723,3 +723,22 @@ networkpolicies: # # -- The egress rules for this networkPolicy. Allows all egress traffic by default. # egress: # - {} + +# -- Configure any unsupported raw resources here. +# @default -- See below +rawResources: {} + # example: + # # -- Enables or disables the resource. Defaults to true + # enabled: false + # # -- Specify the apiVersion of the resource. + # apiVersion: v1 + # # -- Specify the kind of the resource. + # kind: Endpoint + # # -- Override the name suffix that is used for this resource. + # nameOverride: "" + # # -- Provide additional annotations which may be required. + # annotations: {} + # # -- Provide additional labels which may be required. + # labels: {} + # # -- Configure the contents of the resource that is to be rendered. + # spec: