diff --git a/charts/library/common-test/ci/configMapsFolder/test_2/helm.binary.jpg b/charts/library/common-test/ci/configMapsFolder/test_2/helm.binary.jpg new file mode 100644 index 00000000..83dda637 Binary files /dev/null and b/charts/library/common-test/ci/configMapsFolder/test_2/helm.binary.jpg differ diff --git a/charts/library/common-test/tests/_values/rbac_values.yaml b/charts/library/common-test/tests/_values/rbac_values.yaml new file mode 100644 index 00000000..017cc8f4 --- /dev/null +++ b/charts/library/common-test/tests/_values/rbac_values.yaml @@ -0,0 +1,19 @@ +serviceAccount: + create: true + +rbac: + roles: + defaultRole: + type: Role + rules: + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] + + bindings: + defaultBinding: + type: RoleBinding + roleRef: + identifier: defaultRole + subjects: + - identifier: default diff --git a/charts/library/common-test/tests/pod/field_serviceAccount_test.yaml b/charts/library/common-test/tests/pod/field_serviceAccount_test.yaml index 206f50c2..aad5c8a0 100644 --- a/charts/library/common-test/tests/pod/field_serviceAccount_test.yaml +++ b/charts/library/common-test/tests/pod/field_serviceAccount_test.yaml @@ -69,4 +69,75 @@ tests: - documentIndex: *deploymentDocument equal: path: spec.template.spec.serviceAccountName - value: mySA + value: default + + - it: with extraServiceAccounts default should pass + set: + serviceAccount: + create: false + name: mySA + extraServiceAccounts: + mySA2: + create: false + mySA3: + create: true + asserts: + - hasDocuments: + count: 3 + - documentIndex: &deploymentDocument 1 + isKind: + of: Deployment + - documentIndex: *deploymentDocument + equal: + path: spec.template.spec.serviceAccountName + value: default + + - it: with extraServiceAccounts identifier should pass + set: + controllers: + main: + serviceAccount: + identifier: mySA3 + serviceAccount: + create: false + name: mySA + extraServiceAccounts: + mySA2: + create: false + mySA3: + create: true + asserts: + - hasDocuments: + count: 3 + - documentIndex: &deploymentDocument 1 + isKind: + of: Deployment + - documentIndex: *deploymentDocument + equal: + path: spec.template.spec.serviceAccountName + value: RELEASE-NAME-mySA3 + + - it: with extraServiceAccounts name should pass + set: + controllers: + main: + serviceAccount: + name: arbitrary-SA + serviceAccount: + create: false + name: mySA + extraServiceAccounts: + mySA2: + create: false + mySA3: + create: true + asserts: + - hasDocuments: + count: 3 + - documentIndex: &deploymentDocument 1 + isKind: + of: Deployment + - documentIndex: *deploymentDocument + equal: + path: spec.template.spec.serviceAccountName + value: arbitrary-SA diff --git a/charts/library/common-test/tests/rbac/metadata_test.yaml b/charts/library/common-test/tests/rbac/metadata_test.yaml new file mode 100644 index 00000000..28e1f12f --- /dev/null +++ b/charts/library/common-test/tests/rbac/metadata_test.yaml @@ -0,0 +1,60 @@ +--- +suite: rbac metadata + +set: + serviceAccount: + name: test-sa + +templates: + - common.yaml +values: + - ../_values/rbac_values.yaml +tests: + - it: default metadata should pass + asserts: + - hasDocuments: + count: 4 + - documentIndex: &RoleDocument 2 + isKind: + of: Role + - documentIndex: *RoleDocument + notExists: + path: metadata.annotations + - documentIndex: *RoleDocument + 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: + rbac: + roles: + defaultRole: + annotations: + test_annotation: test + labels: + test_label: test + asserts: + - hasDocuments: + count: 4 + - documentIndex: &RoleDocument 2 + isKind: + of: Role + - documentIndex: *RoleDocument + equal: + path: metadata.annotations + value: + test_annotation: test + - documentIndex: *RoleDocument + 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 diff --git a/charts/library/common-test/tests/rbac/names_test.yaml b/charts/library/common-test/tests/rbac/names_test.yaml new file mode 100644 index 00000000..31a5c672 --- /dev/null +++ b/charts/library/common-test/tests/rbac/names_test.yaml @@ -0,0 +1,58 @@ +--- +suite: rbac names + +set: + serviceAccount: + name: test-sa + +templates: + - common.yaml +values: + - ../_values/rbac_values.yaml +tests: + - it: default role and rolebinding names should pass + asserts: + - hasDocuments: + count: 4 + - documentIndex: &RoleDocument 2 + isKind: + of: Role + - documentIndex: *RoleDocument + equal: + path: metadata.name + value: RELEASE-NAME-defaultRole + + - documentIndex: &BindingDocument 3 + isKind: + of: RoleBinding + - documentIndex: *BindingDocument + equal: + path: metadata.name + value: RELEASE-NAME-defaultBinding + + - it: custom role name should pass + set: + rbac: + roles: + defaultRole: + forceRename: customRole + bindings: + defaultBinding: + forceRename: customBinding + asserts: + - hasDocuments: + count: 4 + - documentIndex: &RoleDocument 2 + isKind: + of: Role + - documentIndex: &BindingDocument 3 + isKind: + of: RoleBinding + - documentIndex: *RoleDocument + equal: + path: metadata.name + value: customRole + - documentIndex: *BindingDocument + equal: + path: metadata.name + value: customBinding diff --git a/charts/library/common-test/tests/rbac/validations_test.yaml b/charts/library/common-test/tests/rbac/validations_test.yaml new file mode 100644 index 00000000..16575909 --- /dev/null +++ b/charts/library/common-test/tests/rbac/validations_test.yaml @@ -0,0 +1,44 @@ +--- +suite: rbac validations + +set: + serviceAccount: + name: test-sa + +templates: + - common.yaml +values: + - ../_values/rbac_values.yaml +tests: + - it: role type must be valid + set: + rbac: + roles: + invalidRole: + type: InvalidRole + rules: {} + asserts: + - failedTemplate: + errorMessage: "You selected: `InvalidRole`. Type must be one of:" + + - it: role rules can't be empty + set: + rbac: + roles: + invalidRole: + type: Role + rules: [] + asserts: + - failedTemplate: + errorMessage: "Rules can't be empty" + + - it: roleBinding requires roleRef + set: + rbac: + bindings: + invalidBinding: + type: RoleBinding + roleRef: {} + asserts: + - failedTemplate: + errorMessage: "If not using identifier roleRef must have a `name` key" diff --git a/charts/library/common-test/tests/rbac/values_test.yaml b/charts/library/common-test/tests/rbac/values_test.yaml new file mode 100644 index 00000000..e6574dd3 --- /dev/null +++ b/charts/library/common-test/tests/rbac/values_test.yaml @@ -0,0 +1,52 @@ +--- +suite: rbac values + +set: + serviceAccount: + name: test-sa + +templates: + - common.yaml +values: + - ../_values/rbac_values.yaml +tests: + - it: default role and rolebinding should pass + asserts: + - hasDocuments: + count: 4 + - documentIndex: &RoleDocument 2 + isKind: + of: Role + - documentIndex: *RoleDocument + equal: + path: rules[0].verbs + value: ["get", "list"] + + - documentIndex: &BindingDocument 3 + isKind: + of: RoleBinding + - documentIndex: *BindingDocument + equal: + path: subjects[0].name + value: "test-sa" + + - it: custom role values should pass + set: + rbac: + roles: + customRole: + type: ClusterRole + rules: + - apiGroups: ["*"] + resources: ["*"] + verbs: ["get", "list", "watch"] + asserts: + - hasDocuments: + count: 5 + - documentIndex: &RoleDocument 2 + isKind: + of: ClusterRole + - documentIndex: *RoleDocument + equal: + path: rules[0].verbs + value: ["get", "list", "watch"] diff --git a/charts/library/common-test/tests/service/values_test.yaml b/charts/library/common-test/tests/service/values_test.yaml index 7dea1fa9..464033d7 100644 --- a/charts/library/common-test/tests/service/values_test.yaml +++ b/charts/library/common-test/tests/service/values_test.yaml @@ -56,6 +56,22 @@ tests: path: spec.externalTrafficPolicy value: Local + - it: internalTrafficPolicy should pass + values: + - ../_values/service_main_default.yaml + set: + service: + main: + internalTrafficPolicy: Local + asserts: + - documentIndex: &ServiceDocument 1 + isKind: + of: Service + - documentIndex: *ServiceDocument + equal: + path: spec.internalTrafficPolicy + value: Local + - it: externalTrafficPolicy should pass for LoadBalancer service values: - ../_values/service_main_default.yaml diff --git a/charts/library/common-test/tests/serviceAccount/serviceaccount_test.yaml b/charts/library/common-test/tests/serviceAccount/serviceaccount_test.yaml index dd6bfb11..1c86a26a 100644 --- a/charts/library/common-test/tests/serviceAccount/serviceaccount_test.yaml +++ b/charts/library/common-test/tests/serviceAccount/serviceaccount_test.yaml @@ -51,7 +51,7 @@ tests: equal: path: secrets value: - - name: RELEASE-NAME-sa-token + - name: RELEASE-NAME-default-sa-token - documentIndex: *DeploymentDocument equal: path: spec.template.spec.serviceAccountName @@ -87,7 +87,7 @@ tests: equal: path: secrets value: - - name: RELEASE-NAME-sa-token + - name: RELEASE-NAME-default-sa-token - documentIndex: *DeploymentDocument equal: path: spec.template.spec.serviceAccountName @@ -97,3 +97,125 @@ tests: path: metadata.annotations value: kubernetes.io/service-account.name: *ServiceAccountName + + - it: multiple serviceAccounts and Secrets are created when enabled + set: + serviceAccount: + create: true + name: &ServiceAccountName myAccount + extraServiceAccounts: + mySA: + create: true + asserts: + - hasDocuments: + count: 5 + - documentIndex: &ServiceAccountDocument 0 + isKind: + of: ServiceAccount + - documentIndex: &ServiceAccountDocument2 1 + isKind: + of: ServiceAccount + - documentIndex: &DeploymentDocument 2 + isKind: + of: Deployment + - documentIndex: &SecretDocument 3 + isKind: + of: Secret + - documentIndex: &SecretDocument2 4 + isKind: + of: Secret + - documentIndex: *ServiceAccountDocument + equal: + path: metadata.name + value: *ServiceAccountName + - documentIndex: *ServiceAccountDocument2 + equal: + path: metadata.name + value: RELEASE-NAME-mySA + - documentIndex: *ServiceAccountDocument + equal: + path: secrets + value: + - name: RELEASE-NAME-default-sa-token + - documentIndex: *ServiceAccountDocument2 + equal: + path: secrets + value: + - name: RELEASE-NAME-mySA-sa-token + - documentIndex: *DeploymentDocument + equal: + path: spec.template.spec.serviceAccountName + value: *ServiceAccountName + - documentIndex: *SecretDocument + equal: + path: metadata.annotations + value: + kubernetes.io/service-account.name: *ServiceAccountName + - documentIndex: *SecretDocument2 + equal: + path: metadata.annotations + value: + kubernetes.io/service-account.name: RELEASE-NAME-mySA + + - it: multiple serviceAccounts and Secrets are created with custom names + set: + serviceAccount: + create: true + name: &ServiceAccountName myAccount + extraServiceAccounts: + mySA: + create: true + name: &ServiceAccountName2 mySAcustom + mySA2: + create: false + name: &ServiceAccountName3 mySAcustom2 + asserts: + - hasDocuments: + count: 5 + - documentIndex: &ServiceAccountDocument 0 + isKind: + of: ServiceAccount + - documentIndex: &ServiceAccountDocument2 1 + isKind: + of: ServiceAccount + - documentIndex: &DeploymentDocument 2 + isKind: + of: Deployment + - documentIndex: &SecretDocument 3 + isKind: + of: Secret + - documentIndex: &SecretDocument2 4 + isKind: + of: Secret + - documentIndex: *ServiceAccountDocument + equal: + path: metadata.name + value: *ServiceAccountName + - documentIndex: *ServiceAccountDocument2 + equal: + path: metadata.name + value: *ServiceAccountName2 + - documentIndex: *ServiceAccountDocument + equal: + path: secrets + value: + - name: RELEASE-NAME-default-sa-token + - documentIndex: *ServiceAccountDocument2 + equal: + path: secrets + value: + - name: RELEASE-NAME-mySA-sa-token + - documentIndex: *DeploymentDocument + equal: + path: spec.template.spec.serviceAccountName + value: *ServiceAccountName + - documentIndex: *SecretDocument + equal: + path: metadata.annotations + value: + kubernetes.io/service-account.name: *ServiceAccountName + - documentIndex: *SecretDocument2 + equal: + path: metadata.annotations + value: + kubernetes.io/service-account.name: *ServiceAccountName2 diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 5b573058..5b81f7d8 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.4.0 +version: 3.5.0 kubeVersion: ">=1.22.0-0" keywords: - common @@ -16,16 +16,13 @@ annotations: artifacthub.io/changes: |- - kind: added description: |- - Add configMapsFromFolderBasePath to create ConfigMaps from a folder + Add support for binary files in configMapsFromFolderBasePath - kind: added description: |- - Added support for setting `defaultContainerOptions`. - links: - - name: Documentation - url: https://bjw-s.github.io/helm-charts/docs/common-library/howto/default-container-options + Add support for internalTrafficPolicy field in Services - kind: added description: |- - Added support for `loadBalancerClass`. - - kind: fixed + Add support for multiple ServiceAccounts + - kind: added description: |- - Fixed volume name reference when persistence key matches release name. + Add support for multiple RBAC resources diff --git a/charts/library/common/README.md b/charts/library/common/README.md index 88c4f026..0b888675 100644 --- a/charts/library/common/README.md +++ b/charts/library/common/README.md @@ -1,6 +1,6 @@ # common -![Version: 3.4.0](https://img.shields.io/badge/Version-3.4.0-informational?style=flat-square) ![Type: library](https://img.shields.io/badge/Type-library-informational?style=flat-square) +![Version: 3.5.0](https://img.shields.io/badge/Version-3.5.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.4.0 + version: 3.5.0 repository: https://bjw-s.github.io/helm-charts/ ``` diff --git a/charts/library/common/schemas/configmap.json b/charts/library/common/schemas/configmap.json index 830bebe7..bf6387e2 100644 --- a/charts/library/common/schemas/configmap.json +++ b/charts/library/common/schemas/configmap.json @@ -25,8 +25,17 @@ "additionalProperties": { "type": "string" } + }, + "binaryData": { + "type": "object", + "additionalProperties": { + "type": "string" + } } }, - "required": ["data"] + "oneOf": [ + {"required": ["data"]}, + {"required": ["binaryData"]} + ] } } diff --git a/charts/library/common/schemas/controllers.json b/charts/library/common/schemas/controllers.json index a3c1f2af..6ca1fbd3 100644 --- a/charts/library/common/schemas/controllers.json +++ b/charts/library/common/schemas/controllers.json @@ -2,7 +2,6 @@ "instance": { "type": "object", "additionalProperties": false, - "properties": { "enabled": { "type": "boolean", @@ -10,7 +9,13 @@ }, "type": { "type": "string", - "enum": ["deployment", "statefulset", "daemonset", "cronjob", "job"], + "enum": [ + "deployment", + "statefulset", + "daemonset", + "cronjob", + "job" + ], "default": "deployment" }, "annotations": { @@ -26,7 +31,10 @@ "$ref": "pod.json#/options" }, "replicas": { - "type": ["integer", "null"], + "type": [ + "integer", + "null" + ], "default": 1 }, "revisionHistoryLimit": { @@ -54,7 +62,10 @@ "defaultContainerOptionsStrategy": { "type": "string", "default": "overwrite", - "enum": ["overwrite", "merge"] + "enum": [ + "overwrite", + "merge" + ] }, "defaultContainerOptions": { "type": "object", @@ -94,23 +105,51 @@ "additionalProperties": { "$ref": "containers.json#/container" } + }, + "serviceAccount": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "identifier": { + "type": "string" + } + } } }, - "allOf": [ { "if": { "properties": { - "type": {"const": "deployment"} + "type": { + "const": "deployment" + } } }, "then": { "not": { "anyOf": [ - {"required": ["statefulset"]}, - {"required": ["cronjob"]}, - {"required": ["job"]}, - {"required": ["daemonset"]} + { + "required": [ + "statefulset" + ] + }, + { + "required": [ + "cronjob" + ] + }, + { + "required": [ + "job" + ] + }, + { + "required": [ + "daemonset" + ] + } ] } } @@ -118,16 +157,32 @@ { "if": { "properties": { - "type": {"const": "statefulset"} + "type": { + "const": "statefulset" + } }, - "required": ["type"] + "required": [ + "type" + ] }, "then": { "not": { "anyOf": [ - {"required": ["cronjob"]}, - {"required": ["job"]}, - {"required": ["daemonset"]} + { + "required": [ + "cronjob" + ] + }, + { + "required": [ + "job" + ] + }, + { + "required": [ + "daemonset" + ] + } ] } } @@ -135,49 +190,83 @@ { "if": { "properties": { - "type": {"const": "cronjob"} + "type": { + "const": "cronjob" + } }, - "required": ["type"] + "required": [ + "type" + ] }, "then": { "allOf": [ { "not": { "anyOf": [ - {"required": ["statefulset"]}, - {"required": ["job"]}, - {"required": ["daemonset"]} + { + "required": [ + "statefulset" + ] + }, + { + "required": [ + "job" + ] + }, + { + "required": [ + "daemonset" + ] + } ] } }, - {"required": ["cronjob"]} + { + "required": [ + "cronjob" + ] + } ] } }, { "if": { "properties": { - "type": {"const": "job"} + "type": { + "const": "job" + } }, - "required": ["type"] + "required": [ + "type" + ] }, "then": { "not": { "anyOf": [ - {"required": ["statefulset"]}, - {"required": ["cronjob"]}, - {"required": ["daemonset"]} + { + "required": [ + "statefulset" + ] + }, + { + "required": [ + "cronjob" + ] + }, + { + "required": [ + "daemonset" + ] + } ] } } } ] }, - "statefulset": { "type": "object", "additionalProperties": false, - "properties": { "podManagementPolicy": { "type": "string" @@ -188,12 +277,18 @@ "properties": { "whenDeleted": { "type": "string", - "enum": ["Delete", "Retain"], + "enum": [ + "Delete", + "Retain" + ], "default": "Retain" }, "whenScaled": { "type": "string", - "enum": ["Delete", "Retain"], + "enum": [ + "Delete", + "Retain" + ], "default": "Retain" } } @@ -206,11 +301,9 @@ } } }, - "statefulset.volumeClaimTemplate": { "type": "object", "additionalProperties": false, - "properties": { "enabled": { "type": "boolean", @@ -225,11 +318,21 @@ "$ref": "persistence.json#/mountPathCollection" } }, - "annotations": {"$ref": "definitions.json#/annotations"}, - "dataSource": {"$ref": "persistence.json#/dataSourceReference"}, - "dataSourceRef": {"$ref": "persistence.json#/dataSourceReference"}, - "globalMounts": {"$ref": "persistence.json#/globalMounts"}, - "labels": {"$ref": "definitions.json#/labels"}, + "annotations": { + "$ref": "definitions.json#/annotations" + }, + "dataSource": { + "$ref": "persistence.json#/dataSourceReference" + }, + "dataSourceRef": { + "$ref": "persistence.json#/dataSourceReference" + }, + "globalMounts": { + "$ref": "persistence.json#/globalMounts" + }, + "labels": { + "$ref": "definitions.json#/labels" + }, "name": { "type": "string" }, @@ -240,13 +343,14 @@ "type": "string" } }, - "required": ["name", "size"] + "required": [ + "name", + "size" + ] }, - "cronjob": { "type": "object", "additionalProperties": false, - "properties": { "backoffLimit": { "type": "integer", @@ -288,13 +392,13 @@ "type": "integer" } }, - "required": ["schedule"] + "required": [ + "schedule" + ] }, - "job": { "type": "object", "additionalProperties": false, - "properties": { "backoffLimit": { "type": "integer", diff --git a/charts/library/common/schemas/service.json b/charts/library/common/schemas/service.json index ee597177..dab114a3 100644 --- a/charts/library/common/schemas/service.json +++ b/charts/library/common/schemas/service.json @@ -35,6 +35,10 @@ "loadBalancerClass": { "type": "string" }, + "internalTrafficPolicy": { + "type": "string", + "enum": ["Cluster", "Local"] + }, "externalTrafficPolicy": { "type": "string", "enum": ["Cluster", "Local"] diff --git a/charts/library/common/schemas/serviceAccount.json b/charts/library/common/schemas/serviceAccount.json index a11f7c6c..ec2e1344 100644 --- a/charts/library/common/schemas/serviceAccount.json +++ b/charts/library/common/schemas/serviceAccount.json @@ -15,6 +15,28 @@ }, "labels": { "$ref": "definitions.json#/labels" + }, + "extraServiceAccounts": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": false, + "properties": { + "create": { + "type": "boolean", + "default": false + }, + "name": { + "type": "string" + }, + "annotations": { + "$ref": "definitions.json#/annotations" + }, + "labels": { + "$ref": "definitions.json#/labels" + } + } + } } } } diff --git a/charts/library/common/templates/classes/_configmap.tpl b/charts/library/common/templates/classes/_configmap.tpl index f0ed645a..0e634fae 100644 --- a/charts/library/common/templates/classes/_configmap.tpl +++ b/charts/library/common/templates/classes/_configmap.tpl @@ -31,8 +31,12 @@ metadata: {{- printf "%s: %s" $key (tpl $value $rootContext | toYaml ) | nindent 4 }} {{- end }} {{- end }} +{{- with $configMapObject.data }} data: - {{- with $configMapObject.data }} {{- tpl (toYaml .) $rootContext | nindent 2 }} - {{- end }} +{{- end }} +{{- with $configMapObject.binaryData }} +binaryData: + {{- tpl (toYaml .) $rootContext | nindent 2 }} +{{- end }} {{- end -}} diff --git a/charts/library/common/templates/classes/_role.tpl b/charts/library/common/templates/classes/_role.tpl new file mode 100644 index 00000000..0c1b9a6d --- /dev/null +++ b/charts/library/common/templates/classes/_role.tpl @@ -0,0 +1,40 @@ +{{/* +This template serves as a blueprint for generating Role objects in Kubernetes. +*/}} +{{- define "bjw-s.common.class.rbac.Role" -}} + {{- $rootContext := .rootContext -}} + {{- $roleObject := .object -}} + + {{- $labels := merge + ($roleObject.labels | default dict) + (include "bjw-s.common.lib.metadata.allLabels" $rootContext | fromYaml) + -}} + {{- $annotations := merge + ($roleObject.annotations | default dict) + (include "bjw-s.common.lib.metadata.globalAnnotations" $rootContext | fromYaml) + -}} + {{- $rules := "" -}} + {{- with $roleObject.rules -}} + {{- $rules = (toYaml . ) | trim -}} + {{- end -}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{ with $roleObject.type -}} +kind: {{ . }} +{{ end -}} +metadata: + name: {{ $roleObject.name }} + {{- with $labels }} + labels: {{- toYaml . | nindent 4 -}} + {{- end }} + {{- with $annotations }} + annotations: {{- toYaml . | nindent 4 -}} + {{- end }} + {{ if eq $roleObject.type "Role" -}} + namespace: {{ $rootContext.Release.Namespace }} + {{- end -}} +{{ with $rules }} +rules: {{- tpl . $rootContext | nindent 2 }} +{{- end }} + +{{- end -}} diff --git a/charts/library/common/templates/classes/_rolebinding.tpl b/charts/library/common/templates/classes/_rolebinding.tpl new file mode 100644 index 00000000..076658f0 --- /dev/null +++ b/charts/library/common/templates/classes/_rolebinding.tpl @@ -0,0 +1,68 @@ +{{/* +This template serves as a blueprint for generating RoleBinding objects in Kubernetes. +*/}} +{{- define "bjw-s.common.class.rbac.roleBinding" -}} + {{- $rootContext := .rootContext -}} + {{- $roleBindingObject := .object -}} + + {{- $labels := merge + ($roleBindingObject.labels | default dict) + (include "bjw-s.common.lib.metadata.allLabels" $rootContext | fromYaml) + -}} + {{- $annotations := merge + ($roleBindingObject.annotations | default dict) + (include "bjw-s.common.lib.metadata.globalAnnotations" $rootContext | fromYaml) + -}} + {{- $subjects := list -}} + {{- with $roleBindingObject.subjects -}} + {{- range $subject := . -}} + {{- if hasKey . "identifier" -}} + {{- $subject := include "bjw-s.common.lib.serviceAccount.getByIdentifier" (dict "rootContext" $rootContext "id" .identifier) | fromYaml -}} + {{- $subject = pick $subject "name" -}} + {{- $_ := set $subject "kind" "ServiceAccount" -}} + {{- $_ := set $subject "namespace" $rootContext.Release.Namespace -}} + {{- $subjects = mustAppend $subjects $subject -}} + {{- else -}} + {{- $subject := dict "name" .name "kind" .kind "namespace" .namespace -}} + {{- $subjects = mustAppend $subjects $subject -}} + {{- end -}} + {{- end -}} + {{- $subjects = $subjects | uniq | toYaml -}} + {{- end -}} + + {{- $role := dict -}} + {{- with $roleBindingObject.roleRef -}} + {{- if hasKey . "identifier" -}} + {{- $role = include "bjw-s.common.lib.rbac.role.getByIdentifier" (dict "rootContext" $rootContext "id" .identifier) | fromYaml -}} + {{- else -}} + {{- $_ := set $role "name" .name -}} + {{- $_ := set $role "type" .kind -}} + {{- end -}} + + {{- end -}} +--- +apiVersion: rbac.authorization.k8s.io/v1 +{{ with $roleBindingObject.type -}} +kind: {{ . }} +{{ end -}} +metadata: + name: {{ $roleBindingObject.name }} + {{- with $labels }} + labels: {{- toYaml . | nindent 4 -}} + {{- end }} + {{- with $annotations }} + annotations: {{- toYaml . | nindent 4 -}} + {{- end }} + {{ if eq $roleBindingObject.type "RoleBinding" -}} + namespace: {{ $rootContext.Release.Namespace }} + {{- end }} +roleRef: + kind: {{ $role.type }} + name: {{ $role.name }} + apiGroup: rbac.authorization.k8s.io +{{ with $subjects -}} +subjects: {{- tpl . $rootContext | nindent 2 }} + +{{- end -}} + +{{- end -}} diff --git a/charts/library/common/templates/classes/_service.tpl b/charts/library/common/templates/classes/_service.tpl index 2b991d7f..c70db2d1 100644 --- a/charts/library/common/templates/classes/_service.tpl +++ b/charts/library/common/templates/classes/_service.tpl @@ -60,6 +60,9 @@ spec: {{- else }} type: {{ $svcType }} {{- end }} + {{- if $serviceObject.internalTrafficPolicy }} + internalTrafficPolicy: {{ $serviceObject.internalTrafficPolicy }} + {{- end }} {{- if $serviceObject.externalTrafficPolicy }} externalTrafficPolicy: {{ $serviceObject.externalTrafficPolicy }} {{- end }} diff --git a/charts/library/common/templates/classes/_serviceAccount.tpl b/charts/library/common/templates/classes/_serviceAccount.tpl index 068d1e18..6bfac3a7 100644 --- a/charts/library/common/templates/classes/_serviceAccount.tpl +++ b/charts/library/common/templates/classes/_serviceAccount.tpl @@ -32,5 +32,5 @@ metadata: {{- end }} {{- end }} secrets: - - name: {{ include "bjw-s.common.lib.chart.names.fullname" $rootContext }}-sa-token + - name: {{ get (include "bjw-s.common.lib.secret.getByIdentifier" (dict "rootContext" $rootContext "id" (printf "%s-sa-token" $serviceAccountObject.identifier) ) | fromYaml) "name"}} {{- end -}} diff --git a/charts/library/common/templates/lib/configMap/_valuesToObject.tpl b/charts/library/common/templates/lib/common/_valuesToObject.tpl similarity index 69% rename from charts/library/common/templates/lib/configMap/_valuesToObject.tpl rename to charts/library/common/templates/lib/common/_valuesToObject.tpl index 0e9286d4..cec04530 100644 --- a/charts/library/common/templates/lib/configMap/_valuesToObject.tpl +++ b/charts/library/common/templates/lib/common/_valuesToObject.tpl @@ -1,15 +1,17 @@ {{/* -Convert configMap values to an object +Convert values to an object */}} -{{- define "bjw-s.common.lib.configMap.valuesToObject" -}} +{{- define "bjw-s.common.lib.valuesToObject" -}} {{- $rootContext := .rootContext -}} {{- $identifier := .id -}} {{- $objectValues := .values -}} - {{- /* Determine and inject the configMap name */ -}} + {{- /* Determine and inject the name */ -}} {{- $objectName := (include "bjw-s.common.lib.chart.names.fullname" $rootContext) -}} - {{- if $objectValues.nameOverride -}} + {{- if $objectValues.forceRename -}} + {{- $objectName = tpl $objectValues.forceRename $rootContext -}} + {{- else if $objectValues.nameOverride -}} {{- $override := tpl $objectValues.nameOverride $rootContext -}} {{- if not (eq $objectName $override) -}} {{- $objectName = printf "%s-%s" $objectName $override -}} @@ -19,9 +21,9 @@ Convert configMap values to an object {{- $objectName = printf "%s-%s" $objectName $identifier -}} {{- end -}} {{- end -}} + {{- $_ := set $objectValues "name" $objectName -}} {{- $_ := set $objectValues "identifier" $identifier -}} - - {{- /* Return the configMap object */ -}} + {{- /* Return the object */ -}} {{- $objectValues | toYaml -}} {{- end -}} diff --git a/charts/library/common/templates/lib/configMap/_getByIdentifier.tpl b/charts/library/common/templates/lib/configMap/_getByIdentifier.tpl index 87b10a3b..395a086d 100644 --- a/charts/library/common/templates/lib/configMap/_getByIdentifier.tpl +++ b/charts/library/common/templates/lib/configMap/_getByIdentifier.tpl @@ -7,6 +7,6 @@ Return a configMap Object by its Identifier. {{- $configMapValues := dig $identifier nil $rootContext.Values.configMaps -}} {{- if not (empty $configMapValues) -}} - {{- include "bjw-s.common.lib.configMap.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $configMapValues) -}} + {{- include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $configMapValues) -}} {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/lib/configMap/_validate.tpl b/charts/library/common/templates/lib/configMap/_validate.tpl index c61c7044..0b23d490 100644 --- a/charts/library/common/templates/lib/configMap/_validate.tpl +++ b/charts/library/common/templates/lib/configMap/_validate.tpl @@ -4,4 +4,8 @@ Validate configMap values {{- define "bjw-s.common.lib.configMap.validate" -}} {{- $rootContext := .rootContext -}} {{- $configMapValues := .object -}} + + {{- if and (empty (get $configMapValues "data")) (empty (get $configMapValues "binaryData")) -}} + {{- fail (printf "No data or binaryData specified for configMap. (configMap: %s)" $configMapValues.identifier) }} + {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/lib/pod/fields/_serviceAccountName.tpl b/charts/library/common/templates/lib/pod/fields/_serviceAccountName.tpl index 947a1a46..ae17088b 100644 --- a/charts/library/common/templates/lib/pod/fields/_serviceAccountName.tpl +++ b/charts/library/common/templates/lib/pod/fields/_serviceAccountName.tpl @@ -3,9 +3,21 @@ Returns the value for serviceAccountName */ -}} {{- define "bjw-s.common.lib.pod.field.serviceAccountName" -}} {{- $rootContext := .ctx.rootContext -}} + {{- $controllerObject := .ctx.controllerObject -}} - {{- $serviceAccountValues := (mustDeepCopy $rootContext.Values.serviceAccount) -}} - {{- $serviceAccountObject := (include "bjw-s.common.lib.serviceAccount.valuesToObject" (dict "rootContext" $rootContext "id" "default" "values" $serviceAccountValues)) | fromYaml -}} - {{- $serviceAccountObject.name -}} + {{- $serviceAccountName := "default" -}} + + {{- if (get (include "bjw-s.common.lib.serviceAccount.getByIdentifier" (dict "rootContext" $rootContext "id" "default") | fromYaml) "create") -}} + {{- $serviceAccountName = get (include "bjw-s.common.lib.serviceAccount.getByIdentifier" (dict "rootContext" $rootContext "id" "default") | fromYaml) "name" -}} + {{- end -}} + + {{- with $controllerObject.serviceAccount -}} + {{- if hasKey . "identifier" -}} + {{- $serviceAccountName = get (include "bjw-s.common.lib.serviceAccount.getByIdentifier" (dict "rootContext" $rootContext "id" .identifier) | fromYaml) "name" -}} + {{- else if hasKey . "name" -}} + {{- $serviceAccountName = .name -}} + {{- end -}} + {{- end -}} + {{- $serviceAccountName -}} {{- end -}} diff --git a/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl b/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl deleted file mode 100644 index 52b5e36a..00000000 --- a/charts/library/common/templates/lib/rawResource/_valuesToObject.tpl +++ /dev/null @@ -1,27 +0,0 @@ -{{/* -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/lib/role/_getByIdentifier.tpl b/charts/library/common/templates/lib/role/_getByIdentifier.tpl new file mode 100644 index 00000000..f1092ed1 --- /dev/null +++ b/charts/library/common/templates/lib/role/_getByIdentifier.tpl @@ -0,0 +1,12 @@ +{{/* +Return a Role Object by its Identifier. +*/}} +{{- define "bjw-s.common.lib.rbac.role.getByIdentifier" -}} + {{- $rootContext := .rootContext -}} + {{- $identifier := .id -}} + + {{- $roleValues := dig $identifier nil $rootContext.Values.rbac.roles -}} + {{- if not (empty $roleValues) -}} + {{- include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $roleValues) -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/role/_validate.tpl b/charts/library/common/templates/lib/role/_validate.tpl new file mode 100644 index 00000000..eae77db8 --- /dev/null +++ b/charts/library/common/templates/lib/role/_validate.tpl @@ -0,0 +1,18 @@ +{{/* +Validate Role values +*/}} +{{- define "bjw-s.common.lib.rbac.role.validate" -}} + {{- $rootContext := .rootContext -}} + {{- $roleValues := .object -}} + {{- $type := required "The role needs to have an explicitly declared type" $roleValues.type -}} + {{- $typeList := list "Role" "ClusterRole" -}} + {{- $rules := $roleValues.rules -}} + + {{- if not (mustHas $type $typeList) -}} + {{- fail (printf "You selected: `%s`. Type must be one of:\n%s\n" $type ($typeList|toYaml)) -}} + {{- end -}} + {{- if not $rules -}} + {{- fail "Rules can't be empty" -}} + {{- end -}} + +{{- end -}} diff --git a/charts/library/common/templates/lib/rolebinding/_getByIdentifier.tpl b/charts/library/common/templates/lib/rolebinding/_getByIdentifier.tpl new file mode 100644 index 00000000..e9a99d4c --- /dev/null +++ b/charts/library/common/templates/lib/rolebinding/_getByIdentifier.tpl @@ -0,0 +1,12 @@ +{{/* +Return a RoleBinding Object by its Identifier. +*/}} +{{- define "bjw-s.common.lib.rbac.roleBinding.getByIdentifier" -}} + {{- $rootContext := .rootContext -}} + {{- $identifier := .id -}} + + {{- $roleBindingValues := dig $identifier nil $rootContext.Values.rbac.bindings -}} + {{- if not (empty $roleBindingValues) -}} + {{- include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $roleBindingValues) -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/rolebinding/_validate.tpl b/charts/library/common/templates/lib/rolebinding/_validate.tpl new file mode 100644 index 00000000..928bdc3f --- /dev/null +++ b/charts/library/common/templates/lib/rolebinding/_validate.tpl @@ -0,0 +1,32 @@ +{{/* +Validate RoleBinding values +*/}} +{{- define "bjw-s.common.lib.rbac.roleBinding.validate" -}} + {{- $rootContext := .rootContext -}} + {{- $roleBindingValues := .object -}} + {{- $type := required "The binding needs to have an explicitly declared type" $roleBindingValues.type -}} + {{- $typeList := list "RoleBinding" "ClusterRoleBinding" -}} + {{- $subjects := $roleBindingValues.subjects -}} + {{- $roleRef := required "A roleRef is required" $roleBindingValues.roleRef -}} + + {{- if not (mustHas $type $typeList) -}} + {{- fail (printf "You selected: `%s`. Type must be one of:\n%s\n" $type ($typeList|toYaml)) -}} + {{- end -}} + + {{- if not (hasKey $roleRef "identifier") -}} + {{- $name := required "If not using identifier roleRef must have a `name` key" $roleRef.name -}} + {{- $name := required "If not using identifier roleRef must have a `kind` key" $roleRef.kind -}} + {{- end -}} + + {{- range $subject := $subjects -}} + {{- if not (hasKey . "identifier") -}} + {{- if not (hasKey . "name") -}} + {{- $name := required "If not using identifier a subject must have a `name` key" .name -}} + {{- else if not (hasKey . "namespace") -}} + {{- $namespace := required "If not using identifier a subject must have a `namespace` key" .namespace -}} + {{- else if not (hasKey . "kind") -}} + {{- $kind := required "If not using identifier a subject must have a `kind` key" .kind -}} + {{- end -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/secret/_getByIdentifier.tpl b/charts/library/common/templates/lib/secret/_getByIdentifier.tpl index ddcb4547..ae797bf5 100644 --- a/charts/library/common/templates/lib/secret/_getByIdentifier.tpl +++ b/charts/library/common/templates/lib/secret/_getByIdentifier.tpl @@ -7,6 +7,6 @@ Return a secret Object by its Identifier. {{- $secretValues := dig $identifier nil $rootContext.Values.secrets -}} {{- if not (empty $secretValues) -}} - {{- include "bjw-s.common.lib.secret.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $secretValues) -}} + {{- include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $secretValues) -}} {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/lib/secret/_valuesToObject.tpl b/charts/library/common/templates/lib/secret/_valuesToObject.tpl deleted file mode 100644 index 4b24d2ab..00000000 --- a/charts/library/common/templates/lib/secret/_valuesToObject.tpl +++ /dev/null @@ -1,27 +0,0 @@ -{{/* -Convert Secret values to an object -*/}} -{{- define "bjw-s.common.lib.secret.valuesToObject" -}} - {{- $rootContext := .rootContext -}} - {{- $identifier := .id -}} - {{- $objectValues := .values -}} - - {{- /* Determine and inject the Secret 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 Secret object */ -}} - {{- $objectValues | toYaml -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/serviceAccount/_getByIdentifier.tpl b/charts/library/common/templates/lib/serviceAccount/_getByIdentifier.tpl new file mode 100644 index 00000000..c187188f --- /dev/null +++ b/charts/library/common/templates/lib/serviceAccount/_getByIdentifier.tpl @@ -0,0 +1,17 @@ +{{/* +Return a ServiceAccount Object by its Identifier. +*/}} +{{- define "bjw-s.common.lib.serviceAccount.getByIdentifier" -}} + {{- $rootContext := .rootContext -}} + {{- $identifier := .id -}} + {{- if eq $identifier "default" -}} + {{- include "bjw-s.common.lib.serviceAccount.valuesToObject" (dict "rootContext" $rootContext "id" "default" "values" $rootContext.Values.serviceAccount) -}} + {{- else -}} + {{- $serviceAccountValues := dig "extraServiceAccounts" $identifier nil $rootContext.Values.serviceAccount -}} + {{- if not (empty $serviceAccountValues) -}} + {{- include "bjw-s.common.lib.serviceAccount.valuesToObject" (dict "rootContext" $rootContext "id" $identifier "values" $serviceAccountValues) -}} + {{- else -}} + {{- fail (printf "No ServiceAccount configured with identifier: %s" $identifier) -}} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/serviceAccount/_valuesToObject.tpl b/charts/library/common/templates/lib/serviceAccount/_valuesToObject.tpl index 9451e101..435a66b4 100644 --- a/charts/library/common/templates/lib/serviceAccount/_valuesToObject.tpl +++ b/charts/library/common/templates/lib/serviceAccount/_valuesToObject.tpl @@ -7,17 +7,19 @@ Convert ServiceAccount values to an object {{- $objectValues := .values -}} {{- /* Determine and inject the serviceAccount name */ -}} - {{- $serviceAccountName := "" -}} - {{- $defaultServiceAccountName := "default" -}} - {{- if $objectValues.create -}} - {{- $defaultServiceAccountName = (include "bjw-s.common.lib.chart.names.fullname" $rootContext) -}} + {{- $defaultServiceAccountName := (include "bjw-s.common.lib.chart.names.fullname" $rootContext) -}} + + {{- $objectName := $defaultServiceAccountName -}} + + {{- with $objectValues.name -}} + {{- $objectName = . -}} + {{- end -}} + {{- if and (ne $identifier "default") (not $objectValues.name) -}} + {{- $objectName = printf "%s-%s" $defaultServiceAccountName $identifier -}} {{- end -}} - {{- $serviceAccountName = default $defaultServiceAccountName $objectValues.name -}} - - {{- $_ := set $objectValues "name" $serviceAccountName -}} + {{- $_ := set $objectValues "name" $objectName -}} {{- $_ := set $objectValues "identifier" $identifier -}} - {{- /* Return the serviceAccount object */ -}} {{- $objectValues | toYaml -}} {{- end -}} diff --git a/charts/library/common/templates/loader/_generate.tpl b/charts/library/common/templates/loader/_generate.tpl index 3dc1af44..aa57c3e3 100644 --- a/charts/library/common/templates/loader/_generate.tpl +++ b/charts/library/common/templates/loader/_generate.tpl @@ -18,4 +18,5 @@ Secondary entrypoint and primary loader for the common chart {{- include "bjw-s.common.render.secrets" . | nindent 0 -}} {{- include "bjw-s.common.render.networkpolicies" . | nindent 0 -}} {{- include "bjw-s.common.render.rawResources" . | nindent 0 -}} + {{- include "bjw-s.common.render.rbac" . | nindent 0 -}} {{- end -}} diff --git a/charts/library/common/templates/render/_configmaps.tpl b/charts/library/common/templates/render/_configmaps.tpl index 484a3d5e..4663dddf 100644 --- a/charts/library/common/templates/render/_configmaps.tpl +++ b/charts/library/common/templates/render/_configmaps.tpl @@ -2,6 +2,8 @@ Renders the configMap objects required by the chart. */}} {{- define "bjw-s.common.render.configMaps" -}} + {{- $rootContext := $ -}} + {{- /* Generate named configMaps as required */ -}} {{- range $key, $configMap := .Values.configMaps }} {{- /* Enable configMap by default, but allow override */ -}} @@ -14,7 +16,7 @@ Renders the configMap objects required by the chart. {{- $configMapValues := (mustDeepCopy $configMap) -}} {{- /* Create object from the raw configMap values */ -}} - {{- $configMapObject := (include "bjw-s.common.lib.configMap.valuesToObject" (dict "rootContext" $ "id" $key "values" $configMapValues)) | fromYaml -}} + {{- $configMapObject := (include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $configMapValues)) | fromYaml -}} {{- /* Perform validations on the configMap before rendering */ -}} {{- include "bjw-s.common.lib.configMap.validate" (dict "rootContext" $ "object" $configMapObject) -}} @@ -37,21 +39,25 @@ Renders configMap objects required by the chart from a folder in the repo's path {{- $_ := set $topLevelFolders (dir $path) "" -}} {{- end -}} {{- $top_level_folder_list := keys $topLevelFolders | sortAlpha -}} - {{/* Iterate over the top level folders */}} {{ range $path := $top_level_folder_list }} {{- $filesContentNoFormat := ($.Files.Glob (printf "%s/*" $path)) -}} {{- $filesContent := dict -}} + {{- $binaryFilesContent := dict -}} {{- range $file_name, $content := $filesContentNoFormat -}} {{- $key := base $file_name -}} {{- if contains ".escape" $key -}} {{- $key := $key | replace ".escape" "" -}} {{- $filesContent = merge $filesContent (dict $key (($.Files.Get $file_name) | replace "{{" "{{ `{{` }}")) -}} + {{- else if contains ".binary" $key -}} + {{- $key := $key | replace ".binary" "" -}} + {{- $binaryFilesContent = merge $binaryFilesContent (dict $key ($.Files.Get $file_name | b64enc )) -}} {{- else -}} {{- $filesContent = merge $filesContent (dict $key ($.Files.Get $file_name)) -}} {{- end -}} {{- end -}} - {{- $configMapValues := dict "enabled" true "labels" dict "annotations" dict "data" $filesContent -}} + + {{- $configMapValues := dict "enabled" true "labels" dict "annotations" dict "data" $filesContent "binaryData" $binaryFilesContent -}} {{- $existingConfigMaps := (get $rootValues "configMaps"| default dict) -}} {{- $mergedConfigMaps := deepCopy $existingConfigMaps | merge (dict (base $path) $configMapValues) -}} {{- $rootValues := merge $rootValues (dict "configMaps" $mergedConfigMaps) -}} diff --git a/charts/library/common/templates/render/_controllers.tpl b/charts/library/common/templates/render/_controllers.tpl index 0d58998f..4a294716 100644 --- a/charts/library/common/templates/render/_controllers.tpl +++ b/charts/library/common/templates/render/_controllers.tpl @@ -2,6 +2,8 @@ Renders the controller objects required by the chart. */}} {{- define "bjw-s.common.render.controllers" -}} + {{- $rootContext := $ -}} + {{- /* Generate named controller objects as required */ -}} {{- range $key, $controller := .Values.controllers -}} {{- /* Enable controller by default, but allow override */ -}} @@ -14,31 +16,31 @@ Renders the controller objects required by the chart. {{- $controllerValues := $controller -}} {{- /* Create object from the raw controller values */ -}} - {{- $controllerObject := (include "bjw-s.common.lib.controller.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerValues)) | fromYaml -}} + {{- $controllerObject := (include "bjw-s.common.lib.controller.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerValues)) | fromYaml -}} {{- /* Perform validations on the controller before rendering */ -}} - {{- include "bjw-s.common.lib.controller.validate" (dict "rootContext" $ "object" $controllerObject) -}} + {{- include "bjw-s.common.lib.controller.validate" (dict "rootContext" $rootContext "object" $controllerObject) -}} {{- if eq $controllerObject.type "deployment" -}} - {{- $deploymentObject := (include "bjw-s.common.lib.deployment.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerObject)) | fromYaml -}} - {{- include "bjw-s.common.lib.deployment.validate" (dict "rootContext" $ "object" $deploymentObject) -}} - {{- include "bjw-s.common.class.deployment" (dict "rootContext" $ "object" $deploymentObject) | nindent 0 -}} + {{- $deploymentObject := (include "bjw-s.common.lib.deployment.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerObject)) | fromYaml -}} + {{- include "bjw-s.common.lib.deployment.validate" (dict "rootContext" $rootContext "object" $deploymentObject) -}} + {{- include "bjw-s.common.class.deployment" (dict "rootContext" $rootContext "object" $deploymentObject) | nindent 0 -}} {{- else if eq $controllerObject.type "cronjob" -}} - {{- $cronjobObject := (include "bjw-s.common.lib.cronjob.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerObject)) | fromYaml -}} - {{- include "bjw-s.common.lib.cronjob.validate" (dict "rootContext" $ "object" $cronjobObject) -}} - {{- include "bjw-s.common.class.cronjob" (dict "rootContext" $ "object" $cronjobObject) | nindent 0 -}} + {{- $cronjobObject := (include "bjw-s.common.lib.cronjob.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerObject)) | fromYaml -}} + {{- include "bjw-s.common.lib.cronjob.validate" (dict "rootContext" $rootContext "object" $cronjobObject) -}} + {{- include "bjw-s.common.class.cronjob" (dict "rootContext" $rootContext "object" $cronjobObject) | nindent 0 -}} {{- else if eq $controllerObject.type "daemonset" -}} - {{- $daemonsetObject := (include "bjw-s.common.lib.daemonset.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerObject)) | fromYaml -}} - {{- include "bjw-s.common.lib.daemonset.validate" (dict "rootContext" $ "object" $daemonsetObject) -}} - {{- include "bjw-s.common.class.daemonset" (dict "rootContext" $ "object" $daemonsetObject) | nindent 0 -}} + {{- $daemonsetObject := (include "bjw-s.common.lib.daemonset.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerObject)) | fromYaml -}} + {{- include "bjw-s.common.lib.daemonset.validate" (dict "rootContext" $rootContext "object" $daemonsetObject) -}} + {{- include "bjw-s.common.class.daemonset" (dict "rootContext" $rootContext "object" $daemonsetObject) | nindent 0 -}} {{- else if eq $controllerObject.type "statefulset" -}} - {{- $statefulsetObject := (include "bjw-s.common.lib.statefulset.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerObject)) | fromYaml -}} - {{- include "bjw-s.common.lib.statefulset.validate" (dict "rootContext" $ "object" $statefulsetObject) -}} - {{- include "bjw-s.common.class.statefulset" (dict "rootContext" $ "object" $statefulsetObject) | nindent 0 -}} + {{- $statefulsetObject := (include "bjw-s.common.lib.statefulset.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerObject)) | fromYaml -}} + {{- include "bjw-s.common.lib.statefulset.validate" (dict "rootContext" $rootContext "object" $statefulsetObject) -}} + {{- include "bjw-s.common.class.statefulset" (dict "rootContext" $rootContext "object" $statefulsetObject) | nindent 0 -}} {{- else if eq $controllerObject.type "job" -}} - {{- $jobObject := (include "bjw-s.common.lib.job.valuesToObject" (dict "rootContext" $ "id" $key "values" $controllerObject)) | fromYaml -}} - {{- include "bjw-s.common.lib.job.validate" (dict "rootContext" $ "object" $jobObject) -}} - {{- include "bjw-s.common.class.job" (dict "rootContext" $ "object" $jobObject) | nindent 0 -}} + {{- $jobObject := (include "bjw-s.common.lib.job.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $controllerObject)) | fromYaml -}} + {{- include "bjw-s.common.lib.job.validate" (dict "rootContext" $rootContext "object" $jobObject) -}} + {{- include "bjw-s.common.class.job" (dict "rootContext" $rootContext "object" $jobObject) | nindent 0 -}} {{- end -}} {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/render/_rawResources.tpl b/charts/library/common/templates/render/_rawResources.tpl index f3e3a12c..7137bc1c 100644 --- a/charts/library/common/templates/render/_rawResources.tpl +++ b/charts/library/common/templates/render/_rawResources.tpl @@ -2,7 +2,9 @@ Renders other arbirtrary objects required by the chart. */}} {{- define "bjw-s.common.render.rawResources" -}} - {{- /* Generate pvc as required */ -}} + {{- $rootContext := $ -}} + + {{- /* Generate raw resources as required */ -}} {{- range $key, $resource := .Values.rawResources -}} {{- /* Enable by default, but allow override */ -}} {{- $resourceEnabled := true -}} @@ -14,7 +16,7 @@ Renders other arbirtrary objects required by the chart. {{- $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 -}} + {{- $resourceObject := (include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $resourceValues)) | fromYaml -}} {{- /* Perform validations on the resource before rendering */ -}} {{- include "bjw-s.common.lib.rawResource.validate" (dict "rootContext" $ "object" $resourceValues) -}} diff --git a/charts/library/common/templates/render/_rbac.tpl b/charts/library/common/templates/render/_rbac.tpl new file mode 100644 index 00000000..b4cfdb38 --- /dev/null +++ b/charts/library/common/templates/render/_rbac.tpl @@ -0,0 +1,67 @@ +{{/* +Renders RBAC objects required by the chart. +*/}} +{{- define "bjw-s.common.render.rbac" -}} + {{- $rootContext := . -}} + {{- include "bjw-s.common.render.rbac.roles" (dict "rootContext" $rootContext) -}} + + {{- include "bjw-s.common.render.rbac.roleBindings" (dict "rootContext" $rootContext) -}} + +{{ end }} + +{{/* +Renders RBAC Role objects required by the chart. +*/}} +{{- define "bjw-s.common.render.rbac.roles" -}} + {{- $rootContext := .rootContext -}} + {{- /* Generate named Roles as required */ -}} + {{- range $key, $role := $rootContext.Values.rbac.roles }} + {{- /* Enable role by default, but allow override */ -}} + {{- $roleEnabled := true -}} + {{- if hasKey $role "enabled" -}} + {{- $roleEnabled = $role.enabled -}} + {{- end -}} + + {{- if $roleEnabled -}} + {{- $roleValues := (mustDeepCopy $role) -}} + + {{- /* Create object from the raw role values */ -}} + {{- $roleObject := (include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $roleValues)) | fromYaml -}} + + {{- /* Perform validations on the role before rendering */ -}} + {{- include "bjw-s.common.lib.rbac.role.validate" (dict "rootContext" $rootContext "object" $roleObject) -}} + + {{/* Include the role class */}} + {{- include "bjw-s.common.class.rbac.Role" (dict "rootContext" $rootContext "object" $roleObject) | nindent 0 -}} + + {{- end -}} + {{- end -}} +{{- end -}} + +{{/* +Renders RBAC RoleBinding objects required by the chart. +*/}} +{{- define "bjw-s.common.render.rbac.roleBindings" -}} + {{- $rootContext := .rootContext -}} + {{- range $key, $roleBinding := $rootContext.Values.rbac.bindings }} + {{- /* Enable RoleBinding by default, but allow override */ -}} + {{- $roleBindingEnabled := true -}} + {{- if hasKey $roleBinding "enabled" -}} + {{- $roleBindingEnabled = $roleBinding.enabled -}} + {{- end -}} + + {{- if $roleBindingEnabled -}} + {{- $roleBindingValues := (mustDeepCopy $roleBinding) -}} + + {{- /* Create object from the raw RoleBinding values */ -}} + {{- $roleBindingObject := (include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $roleBindingValues)) | fromYaml -}} + + {{- /* Perform validations on the RoleBinding before rendering */ -}} + {{- include "bjw-s.common.lib.rbac.roleBinding.validate" (dict "rootContext" $rootContext "object" $roleBindingObject) -}} + + {{/* Include the RoleBinding class */}} + {{- include "bjw-s.common.class.rbac.roleBinding" (dict "rootContext" $rootContext "object" $roleBindingObject) | nindent 0 -}} + + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/render/_secrets.tpl b/charts/library/common/templates/render/_secrets.tpl index feaaed2d..63e79f21 100644 --- a/charts/library/common/templates/render/_secrets.tpl +++ b/charts/library/common/templates/render/_secrets.tpl @@ -2,6 +2,8 @@ Renders the Secret objects required by the chart. */}} {{- define "bjw-s.common.render.secrets" -}} + {{- $rootContext := $ -}} + {{- /* Generate named Secrets as required */ -}} {{- range $key, $secret := .Values.secrets }} {{- /* Enable Secret by default, but allow override */ -}} @@ -14,7 +16,7 @@ Renders the Secret objects required by the chart. {{- $secretValues := (mustDeepCopy $secret) -}} {{- /* Create object from the raw Secret values */ -}} - {{- $secretObject := (include "bjw-s.common.lib.secret.valuesToObject" (dict "rootContext" $ "id" $key "values" $secretValues)) | fromYaml -}} + {{- $secretObject := (include "bjw-s.common.lib.valuesToObject" (dict "rootContext" $rootContext "id" $key "values" $secretValues)) | fromYaml -}} {{- /* Perform validations on the Secret before rendering */ -}} {{- include "bjw-s.common.lib.secret.validate" (dict "rootContext" $ "object" $secretObject) -}} diff --git a/charts/library/common/templates/render/_serviceaccount.tpl b/charts/library/common/templates/render/_serviceaccount.tpl index ad6f49a6..a60e85fd 100644 --- a/charts/library/common/templates/render/_serviceaccount.tpl +++ b/charts/library/common/templates/render/_serviceaccount.tpl @@ -11,10 +11,39 @@ Renders the serviceAccount object required by the chart. {{- /* Perform validations on the ServiceAccount before rendering */ -}} {{- include "bjw-s.common.lib.serviceAccount.validate" (dict "rootContext" $ "object" $serviceAccountObject) -}} + {{- /* Create a service account secret */ -}} + {{- $_ := set .Values.secrets (printf "%s-sa-token" $serviceAccountObject.identifier) (dict "enabled" true "annotations" (dict "kubernetes.io/service-account.name" $serviceAccountObject.name) "type" "kubernetes.io/service-account-token") -}} + {{/* Include the serviceAccount class */}} {{- include "bjw-s.common.class.serviceAccount" (dict "rootContext" $ "object" $serviceAccountObject) | nindent 0 -}} - {{- /* Create a service account secret */ -}} - {{- $_ := set .Values.secrets "sa-token" (dict "enabled" true "annotations" (dict "kubernetes.io/service-account.name" $serviceAccountObject.name) "type" "kubernetes.io/service-account-token") -}} {{- end -}} + + {{- /* Generate named serviceAccount objects as required */ -}} + {{- with .Values.serviceAccount.extraServiceAccounts -}} + {{- range $key, $serviceAccount := . -}} + {{- $serviceAccountEnabled := true -}} + {{- if hasKey $serviceAccount "create" -}} + {{- $serviceAccountEnabled = $serviceAccount.create -}} + {{- end -}} + + {{- if $serviceAccountEnabled -}} + {{- $serviceAccountValues := $serviceAccount -}} + + {{- /* Create object from the raw ServiceAccount values */ -}} + {{- $serviceAccountObject := (include "bjw-s.common.lib.serviceAccount.valuesToObject" (dict "rootContext" $ "id" $key "values" $serviceAccountValues)) | fromYaml -}} + + {{- /* Perform validations on the ServiceAccount before rendering */ -}} + {{- include "bjw-s.common.lib.serviceAccount.validate" (dict "rootContext" $ "object" $serviceAccountObject) -}} + + {{- /* Create a service account secret */ -}} + {{- $_ := set $.Values.secrets (printf "%s-sa-token" $serviceAccountObject.identifier) (dict "enabled" true "annotations" (dict "kubernetes.io/service-account.name" $serviceAccountObject.name) "type" "kubernetes.io/service-account-token") -}} + + {{/* Include the serviceAccount class */}} + {{- include "bjw-s.common.class.serviceAccount" (dict "rootContext" $ "object" $serviceAccountObject) | nindent 0 -}} + + {{- end -}} + {{- end -}} + {{- end -}} + {{- end -}} diff --git a/charts/library/common/values.schema.json b/charts/library/common/values.schema.json index 0865edc1..4f0ddd90 100644 --- a/charts/library/common/values.schema.json +++ b/charts/library/common/values.schema.json @@ -1,7 +1,6 @@ { "$schema": "http://json-schema.org/draft-07/schema", - "$id": "https://raw.githubusercontent.com/bjw-s/helm-charts/common-3.4.0/charts/library/common/values.schema.json", - + "$id": "https://raw.githubusercontent.com/bjw-s/helm-charts/common-3.5.0/charts/library/common/values.schema.json", "type": "object", "properties": { "global": { @@ -11,10 +10,16 @@ "$ref": "schemas/definitions.json#/annotations" }, "nameOverride": { - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "fullnameOverride": { - "type": ["string", "null"] + "type": [ + "string", + "null" + ] }, "labels": { "$ref": "schemas/definitions.json#/labels" diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 82207be3..0679e141 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -116,6 +116,14 @@ controllers: {} # # -- ReplicaSet revision history limit # revisionHistoryLimit: 3 +# # -- Set the controller service account name +# # This is entirely optional, if empty or `null` the controller will use the default service account +# serviceAccount: +# # -- Only use one of `name` or `identifier`. In case both are specified it will prioritize `identifier`. +# # -- Reference a service account identifier from this values.yaml +# identifier: +# # -- Explicitly set the service account name +# name: # # -- CronJob configuration. Required only when using `controller.type: cronjob`. # # @default -- See below # cronjob: @@ -393,6 +401,7 @@ controllers: {} serviceAccount: # -- Specifies whether a service account should be created + # The identifier for this ServiceAccount will be `default` create: false # -- Annotations to add to the service account @@ -405,6 +414,19 @@ serviceAccount: # If not set and create is true, a name is generated using the fullname template name: "" + # -- Additional Service Accounts to create + # Each extra service account admit the same keys as the main service account + extraServiceAccounts: {} + # serviceAccount2: + # create: true + # annotations: + # test: test + # serviceAccount3: + # create: true + # name: custom-service-account + # labels: + # test: test + # -- Use this to populate secrets with the values you specify. # Be aware that these values are not encrypted by default, and could therefore visible # to anybody with access to the values.yaml file. @@ -450,6 +472,8 @@ configMaps: # This will generate a ConfigMap named `configmap1` with keys `file1` and `file2`, values being the respective contents of those files. # If your file contains `gotpl` syntax that you don't want templated by Helm, prefix the file extension with `.escape` and it will be treated as a regular string. # For example, `file1.escape.yaml` will be converted to `file1.yaml` in the ConfigMap with the contents of the file not templated. +# If your file is a binary file like an image, prefix the file extension with `.binary` +# For example, `file1.binary.png` will be converted to `file1.png` in the ConfigMap under binaryData with the contents of the file base64 encoded. configMapsFromFolderBasePath: null # -- Configure the services for the chart here. @@ -475,6 +499,10 @@ service: # # -- Set the service type # type: ClusterIP + # # -- Specify the internalTrafficPolicy for the service. Options: Cluster, Local + # # -- [[ref](https://kubernetes.io/docs/concepts/services-networking/service-traffic-policy/)] + # internalTrafficPolicy: + # # -- Specify the externalTrafficPolicy for the service. Options: Cluster, Local # # -- [[ref](https://kubernetes.io/docs/tutorials/services/source-ip/)] # externalTrafficPolicy: @@ -768,7 +796,8 @@ networkpolicies: # -- Configure any unsupported raw resources here. # @default -- See below -rawResources: {} +rawResources: + {} # example: # # -- Enables or disables the resource. Defaults to true # enabled: false @@ -784,3 +813,38 @@ rawResources: {} # labels: {} # # -- Configure the contents of the resource that is to be rendered. # spec: + +# -- Configure the Roles and Role Bindings for the chart here. +rbac: + {} + # roles: + # role1: + # # -- Force replace the name of the object. + # forceRename: + # # -- Enables or disables the Role. Can be templated. + # enabled: true + # # -- Set to Role,ClusterRole + # type: Role + # rules: + # - apiGroups: ["*"] + # resources: ["*"] + # verbs: ["get", "list", "watch"] + # bindings: + # binding1: + # # -- Force replace the name of the object. + # forceRename: + # # -- Enables or disables the Role. Can be templated. + # enabled: true + # # -- Set to RoleBinding,ClusterRoleBinding + # type: RoleBinding + # # -- Can be an identifier of rbac.roles or a custom name and kind + # roleRef: + # name: test-role + # kind: Role + # identifier: test + # # -- If using an identifier it will be automatically filled, otherwise every key will need to be explicitly declared + # subjects: + # - identifier: default + # - kind: ServiceAccount + # name: test + # namespace: "{{ .Release.Namespace }}"