diff --git a/.github/workflows/apps.yaml b/.github/workflows/apps.yaml index 1b8d6625f1d..4c76ae7cf7f 100644 --- a/.github/workflows/apps.yaml +++ b/.github/workflows/apps.yaml @@ -142,7 +142,7 @@ jobs: ## TODO: Fix common-test - name: Run chart-testing (install) - if: ${{ matrix.app != 'common' && matrix.app != '.gitkee' && matrix.app != 'common-test' }} + if: ${{ matrix.app != 'common' && matrix.app != '.gitkee' }} run: ct install --config .github/ct-install.yaml --charts 'charts/${{ steps.prep-lint.outputs.train }}/${{ matrix.app }}' app-tests-complete: diff --git a/.tools/tests/charts/common-test_spec.rb b/.tools/tests/charts/common-test_spec.rb deleted file mode 100644 index f9fd601caa1..00000000000 --- a/.tools/tests/charts/common-test_spec.rb +++ /dev/null @@ -1,1046 +0,0 @@ -# frozen_string_literal: true -require_relative '../test_helper' - -class Test < ChartTest - @@chart = Chart.new('charts/library/common-test') - - describe @@chart.name do - describe 'controller type' do - it 'defaults to "Deployment"' do - assert_nil(resource('StatefulSet')) - assert_nil(resource('DaemonSet')) - refute_nil(resource('Deployment')) - end - - it 'accepts "statefulset"' do - chart.value controllerType: 'statefulset' - assert_nil(resource('Deployment')) - assert_nil(resource('DaemonSet')) - refute_nil(resource('StatefulSet')) - end - - it 'accepts "daemonset"' do - chart.value controllerType: 'daemonset' - assert_nil(resource('Deployment')) - assert_nil(resource('StatefulSet')) - refute_nil(resource('DaemonSet')) - end - end - - describe 'pod replicas' do - it 'defaults to 1' do - jq('.spec.replicas', resource('Deployment')).must_equal 1 - end - - it 'accepts integer as value' do - chart.value replicas: 3 - jq('.spec.replicas', resource('Deployment')).must_equal 3 - end - end - - - - describe 'hostNetwork' do - it ' hostnetworking default = nil' do - jq('.spec.template.spec.hostNetwork', resource('Deployment')).must_equal nil - end - - it 'DNSPolic = ClusterFirst, hostnetworking = nil' do - values = { - hostNetwork: false - } - chart.value values - jq('.spec.template.spec.hostNetwork', resource('Deployment')).must_equal nil - jq('.spec.template.spec.dnsPolicy', resource('Deployment')).must_equal 'ClusterFirst' - end - - it 'DNSPolic = ClusterFirstWithHostNet, hostnetworking = true' do - values = { - hostNetwork: true - } - chart.value values - jq('.spec.template.spec.hostNetwork', resource('Deployment')).must_equal true - jq('.spec.template.spec.dnsPolicy', resource('Deployment')).must_equal 'ClusterFirstWithHostNet' - end - end - - describe 'Environment settings' do - it 'Check no environment variables' do - values = {} - chart.value values - jq('.spec.template.spec.containers[0].env[0].name', resource('Deployment')).must_equal 'PUID' - jq('.spec.template.spec.containers[0].env[0].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[1].name', resource('Deployment')).must_equal 'PGID' - jq('.spec.template.spec.containers[0].env[1].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[2].name', resource('Deployment')).must_equal 'UMASK' - jq('.spec.template.spec.containers[0].env[2].value', resource('Deployment')).must_equal "002" - end - - it 'set "static" environment variables' do - values = { - env: { - STATIC_ENV: 'value_of_env' - } - } - chart.value values - jq('.spec.template.spec.containers[0].env[0].name', resource('Deployment')).must_equal 'PUID' - jq('.spec.template.spec.containers[0].env[0].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[1].name', resource('Deployment')).must_equal 'PGID' - jq('.spec.template.spec.containers[0].env[1].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[2].name', resource('Deployment')).must_equal 'UMASK' - jq('.spec.template.spec.containers[0].env[2].value', resource('Deployment')).must_equal "002" - jq('.spec.template.spec.containers[0].env[3].name', resource('Deployment')).must_equal values[:env].keys[0].to_s - jq('.spec.template.spec.containers[0].env[3].value', resource('Deployment')).must_equal values[:env].values[0].to_s - end - - it 'set "valueFrom" environment variables' do - values = { - envValueFrom: { - NODE_NAME: { - fieldRef: { - fieldPath: "spec.nodeName" - } - } - } - } - chart.value values - jq('.spec.template.spec.containers[0].env[0].name', resource('Deployment')).must_equal 'PUID' - jq('.spec.template.spec.containers[0].env[0].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[1].name', resource('Deployment')).must_equal 'PGID' - jq('.spec.template.spec.containers[0].env[1].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[2].name', resource('Deployment')).must_equal 'UMASK' - jq('.spec.template.spec.containers[0].env[2].value', resource('Deployment')).must_equal "002" - jq('.spec.template.spec.containers[0].env[3].name', resource('Deployment')).must_equal values[:envValueFrom].keys[0].to_s - jq('.spec.template.spec.containers[0].env[3].valueFrom | keys[0]', resource('Deployment')).must_equal values[:envValueFrom].values[0].keys[0].to_s - end - - it 'set "static" and "Dynamic/Tpl" environment variables' do - values = { - env: { - STATIC_ENV: 'value_of_env' - }, - envTpl: { - DYN_ENV: "{{ .Release.Name }}-admin" - } - } - chart.value values - jq('.spec.template.spec.containers[0].env[0].name', resource('Deployment')).must_equal 'PUID' - jq('.spec.template.spec.containers[0].env[0].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[1].name', resource('Deployment')).must_equal 'PGID' - jq('.spec.template.spec.containers[0].env[1].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[2].name', resource('Deployment')).must_equal 'UMASK' - jq('.spec.template.spec.containers[0].env[2].value', resource('Deployment')).must_equal "002" - jq('.spec.template.spec.containers[0].env[3].name', resource('Deployment')).must_equal values[:env].keys[0].to_s - jq('.spec.template.spec.containers[0].env[3].value', resource('Deployment')).must_equal values[:env].values[0].to_s - jq('.spec.template.spec.containers[0].env[4].name', resource('Deployment')).must_equal values[:envTpl].keys[0].to_s - jq('.spec.template.spec.containers[0].env[4].value', resource('Deployment')).must_equal 'common-test-admin' - end - - it 'set "Dynamic/Tpl" environment variables' do - values = { - envTpl: { - DYN_ENV: "{{ .Release.Name }}-admin" - } - } - chart.value values - jq('.spec.template.spec.containers[0].env[0].name', resource('Deployment')).must_equal 'PUID' - jq('.spec.template.spec.containers[0].env[0].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[1].name', resource('Deployment')).must_equal 'PGID' - jq('.spec.template.spec.containers[0].env[1].value', resource('Deployment')).must_equal "568" - jq('.spec.template.spec.containers[0].env[2].name', resource('Deployment')).must_equal 'UMASK' - jq('.spec.template.spec.containers[0].env[2].value', resource('Deployment')).must_equal "002" - jq('.spec.template.spec.containers[0].env[3].name', resource('Deployment')).must_equal values[:envTpl].keys[0].to_s - jq('.spec.template.spec.containers[0].env[3].value', resource('Deployment')).must_equal 'common-test-admin' - end - end - - describe 'ports settings' do - default_name = 'http' - default_port = 8080 - - it 'defaults to name "http" on port 8080' do - jq('.spec.ports[0].port', resource('Service')).must_equal default_port - jq('.spec.ports[0].targetPort', resource('Service')).must_equal default_name - jq('.spec.ports[0].name', resource('Service')).must_equal default_name - jq('.spec.template.spec.containers[0].ports[0].containerPort', resource('Deployment')).must_equal default_port - jq('.spec.template.spec.containers[0].ports[0].name', resource('Deployment')).must_equal default_name - end - - it 'port name can be overridden' do - values = { - services: { - main: { - port: { - name: 'server' - } - } - } - } - chart.value values - jq('.spec.ports[0].port', resource('Service')).must_equal default_port - jq('.spec.ports[0].targetPort', resource('Service')).must_equal values[:services][:main][:port][:name] - jq('.spec.ports[0].name', resource('Service')).must_equal values[:services][:main][:port][:name] - jq('.spec.template.spec.containers[0].ports[0].containerPort', resource('Deployment')).must_equal default_port - jq('.spec.template.spec.containers[0].ports[0].name', resource('Deployment')).must_equal values[:services][:main][:port][:name] - end - - it 'targetPort can be overridden' do - values = { - services: { - main: { - port: { - targetPort: 80 - } - } - } - } - chart.value values - jq('.spec.ports[0].port', resource('Service')).must_equal default_port - jq('.spec.ports[0].targetPort', resource('Service')).must_equal values[:services][:main][:port][:targetPort] - jq('.spec.ports[0].name', resource('Service')).must_equal default_name - jq('.spec.template.spec.containers[0].ports[0].containerPort', resource('Deployment')).must_equal values[:services][:main][:port][:targetPort] - jq('.spec.template.spec.containers[0].ports[0].name', resource('Deployment')).must_equal default_name - end - - it 'targetPort cannot be a named port' do - values = { - services: { - main: { - port: { - targetPort: 'test' - } - } - } - } - chart.value values - exception = assert_raises HelmCompileError do - chart.execute_helm_template! - end - assert_match("Our charts do not support named ports for targetPort. (port name #{default_name}, targetPort #{values[:services][:main][:port][:targetPort]})", exception.message) - end - end - - describe 'statefulset volumeClaimTemplates' do - - it 'volumeClaimTemplates should be empty by default' do - chart.value controllerType: 'statefulset' - assert_nil(resource('StatefulSet')['spec']['volumeClaimTemplates']) - end - - it 'can set values for volumeClaimTemplates' do - values = { - controllerType: 'statefulset', - volumeClaimTemplates: [ - { - name: 'storage', - accessMode: 'ReadWriteOnce', - size: '10Gi', - storageClass: 'storage' - } - ] - } - - chart.value values - jq('.spec.volumeClaimTemplates[0].metadata.name', resource('StatefulSet')).must_equal values[:volumeClaimTemplates][0][:name] - jq('.spec.volumeClaimTemplates[0].spec.accessModes[0]', resource('StatefulSet')).must_equal values[:volumeClaimTemplates][0][:accessMode] - jq('.spec.volumeClaimTemplates[0].spec.resources.requests.storage', resource('StatefulSet')).must_equal values[:volumeClaimTemplates][0][:size] - jq('.spec.volumeClaimTemplates[0].spec.storageClassName', resource('StatefulSet')).must_equal values[:volumeClaimTemplates][0][:storageClass] - end - end - - describe 'deviceMounts' do - default_name_1 = 'devicemount-test1' - default_name_2 = 'devicemount-test2' - default_devicePath_1 = '/test1' - default_devicePath_2 = '/test2' - empty_dir = {} - - it 'deviceMounts creates VolumeMounts' do - jq('.spec.template.spec.containers[0].volumeMounts[0].name', resource('Deployment')).must_equal default_name_1 - jq('.spec.template.spec.containers[0].volumeMounts[1].name', resource('Deployment')).must_equal default_name_2 - jq('.spec.template.spec.containers[0].volumeMounts[0].mountPath', resource('Deployment')).must_equal default_devicePath_1 - jq('.spec.template.spec.containers[0].volumeMounts[1].mountPath', resource('Deployment')).must_equal default_devicePath_2 - end - - it 'deviceMounts creates Volumes' do - jq('.spec.template.spec.volumes[0].emptyDir', resource('Deployment')).must_equal empty_dir - jq('.spec.template.spec.volumes[1].hostPath.path', resource('Deployment')).must_equal default_devicePath_2 - end - end - - describe 'customStorage' do - default_name_3 = 'customstorage-0' - default_name_4 = 'customstorage-test4' - default_mountPath_3 = '/test3' - default_mountPath_4 = '/test4' - empty_dir = {} - path = '/tmp' - - it 'customStorage creates VolumeMounts' do - jq('.spec.template.spec.containers[0].volumeMounts[2].name', resource('Deployment')).must_equal default_name_3 - jq('.spec.template.spec.containers[0].volumeMounts[3].name', resource('Deployment')).must_equal default_name_4 - jq('.spec.template.spec.containers[0].volumeMounts[2].mountPath', resource('Deployment')).must_equal default_mountPath_3 - jq('.spec.template.spec.containers[0].volumeMounts[3].mountPath', resource('Deployment')).must_equal default_mountPath_4 - end - - it 'customStorage creates Volumes' do - jq('.spec.template.spec.volumes[2].emptyDir', resource('Deployment')).must_equal empty_dir - jq('.spec.template.spec.volumes[3].hostPath.path', resource('Deployment')).must_equal path - end - end - - describe 'Dynamic Portal creation' do - defaultProtocol = "https" - defaultHost = "$node_ip" - defaultPort = "443" - defaulturl = "https://$node_ip:443" - testNodePort = "666" - testIngressPort = "888" - it 'No portal (=configmap) is created by default' do - assert_nil(resource('ConfigMap')) - end - - it 'portal is created when added' do - values = { - portal: { - enabled: true - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal defaultHost - jq('.data.port', resource('ConfigMap')).must_equal defaultPort - jq('.data.url', resource('ConfigMap')).must_equal defaulturl - end - - it 'portal port can be based on NodePort' do - values = { - portal: { - enabled: true - }, - services: { - main: { - type: "NodePort", - port: { - port: 8080, - nodePort: 666 - } - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal defaultHost - jq('.data.port', resource('ConfigMap')).must_equal testNodePort - end - - it 'NodePort portal port can not be overrulled' do - values = { - portal: { - enabled: true, - ingressPort: 888 - }, - services: { - main: { - type: "NodePort", - port: { - port: 8080, - nodePort: 666 - } - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal defaultHost - jq('.data.port', resource('ConfigMap')).must_equal testNodePort - end - - it 'portal NodePort host can be overrulled' do - values = { - portal: { - enabled: true, - ingressPort: 888, - host: "test.com" - }, - services: { - main: { - type: "NodePort", - port: { - port: 8080, - nodePort: 666 - } - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.host', resource('ConfigMap')).must_equal values[:portal][:host] - jq('.data.port', resource('ConfigMap')).must_equal testNodePort - end - - it 'portal can be based on Ingress' do - values = { - portal: { - enabled: true - }, - services: { - main: { - port: { - port: 8080 - } - } - }, - ingress: { - main: { - enabled: true, - hosts: [ - { - host: 'test.com', - paths: [ - { - path: '/' - } - ] - } - ] - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal values[:ingress][:main][:hosts][0][:host] - jq('.data.port', resource('ConfigMap')).must_equal defaultPort - end - - it 'Ingress portal overrules NodePort portal' do - values = { - portal: { - enabled: true - }, - services: { - main: { - type: "NodePort", - port: { - port: 8080, - nodePort: 666 - } - } - }, - ingress: { - main: { - enabled: true, - hosts: [ - { - host: 'test.com', - paths: [ - { - path: '/' - } - ] - } - ] - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal values[:ingress][:main][:hosts][0][:host] - jq('.data.port', resource('ConfigMap')).must_equal defaultPort - end - - it 'portal ingress, only port can be overrrulled' do - values = { - portal: { - enabled: true, - ingressPort: 888, - host: "test1.com" - }, - services: { - main: { - port: { - port: 8080 - } - } - }, - ingress: { - main: { - enabled: true, - hosts: [ - { - host: 'test2.com', - paths: [ - { - path: '/' - } - ] - } - ] - } - } - } - chart.value values - refute_nil(resource('ConfigMap')) - jq('.data.protocol', resource('ConfigMap')).must_equal defaultProtocol - jq('.data.host', resource('ConfigMap')).must_equal values[:ingress][:main][:hosts][0][:host] - jq('.data.port', resource('ConfigMap')).must_equal testIngressPort - end - - end - - describe 'ingress' do - it 'should be disabled when (additional)ingress enabled = false and certType = disabled' do - values = { - ingress: { - test1: { - enabled: false - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - assert_nil(resource('Ingress')) - end - - it 'should be enabled when (additional)ingress enabled = true' do - values = { - ingress: { - test1: { - enabled: true - }, - test2: { - certType: "plain" - } - }, - additionalIngress: [ - { - enabled: true, - name: "test3" - }, - { - enabled: true, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('Ingress')) - end - - it 'should be not create ingressroute unless type tcp/udp' do - values = { - ingress: { - test1: { - enabled: true - }, - test2: { - certType: "plain" - } - }, - additionalIngress: [ - { - enabled: true, - name: "test3" - }, - { - enabled: true, - name: "test4" - } - ] - } - chart.value values - assert_nil(resource('IngressRouteTCP')) - assert_nil(resource('IngressRouteUDP')) - end - - it 'should be enabled when half (additional)ingress enabled = true' do - values = { - ingress: { - test1: { - enabled: false - }, - test2: { - certType: "plain" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: true, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('Ingress')) - end - - it 'ingress with hosts' do - values = { - ingress: { - test1: { - hosts: [ - { - host: 'hostname', - path: '/' - } - ] - } - } - } - - chart.value values - jq('.spec.rules[0].host', resource('Ingress')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.rules[0].http.paths[0].path', resource('Ingress')).must_equal values[:ingress][:test1][:hosts][0][:path] - end - - - - it 'ingress with selfsigned certtype is evaluated' do - expectedHostName = 'common-test.hostname' - expectedSecretName = 'common-test-hostname-secret-name' - values = { - ingress: { - test1: { - enabled: true, - hosts: [ - { - host: 'hostname', - path: '/' - } - ], - certType: "selfsigned" - } - } - } - - chart.value values - jq('.spec.rules[0].host', resource('Ingress')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.rules[0].http.paths[0].path', resource('Ingress')).must_equal values[:ingress][:test1][:hosts][0][:path] - jq('.spec.tls[0].hosts[0]', resource('Ingress')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.tls[0].secretName', resource('Ingress')).must_equal nil - end - - it 'should create when type = HTTP' do - values = { - ingress: { - test1: { - enabled: true, - type: "HTTP" - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('Ingress')) - end - - it 'check no middleware without traefik' do - values = { - ingress: { - test1: { - enabled: true - } - } - } - chart.value values - assert_nil(resource('Middleware')) - end - - it 'check authForward when authForwardURL is set' do - expectedName = 'common-test-test1-auth-forward' - values = { - ingress: { - test1: { - enabled: true, - authForwardURL: "test.test.com" - } - } - } - chart.value values - refute_nil(resource('Middleware')) - jq('.spec.forwardAuth.address', resource('Middleware')).must_equal values[:ingress][:test1][:authForwardURL] - jq('.metadata.name', resource('Middleware')).must_equal expectedName - end - - end - - describe 'ingressRoutes' do - it 'should create only TCP when type = TCP' do - values = { - ingress: { - test1: { - enabled: true, - type: "TCP" - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('IngressRouteTCP')) - assert_nil(resource('IngressRouteUDP')) - end - - it 'should create only UDP when type = UDP' do - values = { - ingress: { - test1: { - enabled: true, - type: "UDP" - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('IngressRouteUDP')) - assert_nil(resource('IngressRouteTCP')) - end - - it 'should create only additional TCP when type = TCP' do - values = { - ingress: { - test1: { - enabled: false - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: [ - { - enabled: true, - name: "test3", - type: "TCP" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('IngressRouteTCP')) - assert_nil(resource('IngressRouteUDP')) - end - - it 'should create only additional UDP when type = UDP' do - values = { - ingress: { - test1: { - enabled: false - }, - test2: { - certType: "disabled" - } - }, - additionalIngress: { - test3: { - enabled: true, - type: "UDP" - }, - test4: { - enabled: false - } - } - } - chart.value values - refute_nil(resource('IngressRouteUDP')) - assert_nil(resource('IngressRouteTCP')) - end - - it 'should be able to create 3 ingress types' do - values = { - ingress: { - test1: { - enabled: true, - type: "UDP" - }, - test2: { - enabled: true, - type: "TCP" - }, - test2b: { - enabled: true, - type: "HTTP" - } - }, - additionalIngress: [ - { - enabled: false, - name: "test3" - }, - { - enabled: false, - name: "test4" - } - ] - } - chart.value values - refute_nil(resource('IngressRouteUDP')) - refute_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - end - - it 'should be able to create 3 additional ingress types' do - values = { - ingress: { - test1: { - enabled: false, - type: "UDP" - }, - test2: { - certType: "disabled", - type: "TCP" - }, - test2b: { - enabled: false, - type: "HTTP" - } - }, - additionalIngress: [ - { - enabled: true, - type: "HTTP", - name: "test3" - }, - { - enabled: true, - type: "TCP", - name: "test4" - }, - { - enabled: true, - type: "UDP", - name: "test5" - } - ] - } - chart.value values - refute_nil(resource('IngressRouteUDP')) - refute_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - end - - it 'ingressroute with selfsigned certtype is evaluated' do - values = { - ingress: { - test1: { - type: "TCP", - enabled: true, - hosts: [ - { - host: 'hostname' - } - ], - certType: "selfsigned" - } - } - } - - chart.value values - jq('.spec.tls.domains[0].main', resource('IngressRouteTCP')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.tls.secretName', resource('IngressRouteTCP')).must_equal nil - end - - it 'ingressrouteUDP + HTTP +TCP with selfsigned cert is evaluated ' do - values = { - ingress: { - test1: { - type: "TCP", - enabled: true, - hosts: [ - { - host: 'hostname' - } - ], - certType: "selfsigned" - }, - test2: { - enabled: true, - type: "UDP" - }, - test2b: { - enabled: true, - type: "HTTP" - } - } - } - - chart.value values - jq('.spec.tls.domains[0].main', resource('IngressRouteTCP')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.tls.secretName', resource('IngressRouteTCP')).must_equal nil - refute_nil(resource('IngressRouteUDP')) - refute_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - end - - it 'HTTP-ingressRoute is evaluated ' do - expectedHostString = 'Host(`hostname`) && PathPrefix(`/`)' - values = { - ingress: { - test1: { - type: "HTTP-IR", - enabled: true, - hosts: [ - { - host: 'hostname' - } - ] - } - } - } - - chart.value values - jq('.spec.routes[0].match', resource('IngressRoute')).must_equal expectedHostString - assert_nil(resource('IngressRouteUDP')) - assert_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - refute_nil(resource('IngressRoute')) - end - - it 'HTTP-ingressRoute with selfsigned cert is evaluated is evaluated ' do - expectedHostString = 'Host(`hostname`) && PathPrefix(`/`)' - values = { - ingress: { - test1: { - type: "HTTP-IR", - enabled: true, - hosts: [ - { - host: 'hostname' - } - ], - certType: "selfsigned" - } - } - } - - chart.value values - jq('.spec.routes[0].match', resource('IngressRoute')).must_equal expectedHostString - assert_nil(resource('IngressRouteUDP')) - assert_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - refute_nil(resource('IngressRoute')) - jq('.spec.tls.domains[0].main', resource('IngressRoute')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.tls.secretName', resource('IngressRoute')).must_equal nil - end - - it 'HTTP-ingressRoute+selfsigned+forwardAuth is evaluated is evaluated ' do - expectedHostString = 'Host(`hostname`) && PathPrefix(`/`)' - expectedName1 = 'common-test-test1-auth-forward' - expectedName2 = 'default-common-test-test1-auth-forward@kubernetescrd' - values = { - ingress: { - test1: { - type: "HTTP-IR", - enabled: true, - hosts: [ - { - host: 'hostname' - } - ], - certType: "selfsigned", - authForwardURL: "test.com" - } - } - } - - chart.value values - jq('.spec.routes[0].match', resource('IngressRoute')).must_equal expectedHostString - assert_nil(resource('IngressRouteUDP')) - assert_nil(resource('IngressRouteTCP')) - refute_nil(resource('Ingress')) - refute_nil(resource('IngressRoute')) - jq('.spec.tls.domains[0].main', resource('IngressRoute')).must_equal values[:ingress][:test1][:hosts][0][:host] - jq('.spec.tls.secretName', resource('IngressRoute')).must_equal nil - jq('.metadata.name', resource('Middleware')).must_equal expectedName1 - jq('.spec.routes[0].middlewares[1].name', resource('IngressRoute')).must_equal expectedName2 - end - end - - describe 'externalServices' do - it 'no externalService endpoints present by default' do - assert_nil(resource('Endpoints')) - end - - it 'Create externalService endpoint' do - values = { - externalServices: [ - { - enabled: true, - serviceTarget: "192.168.10.20", - servicePort: 9443, - certType: "selfsigned", - entrypoint: "websecure", - type: "HTTP", - host: 'hostname', - path: '/' - } - ] - } - - chart.value values - refute_nil(resource('Endpoints')) - jq('.subsets[0].addresses[0].ip', resource('Endpoints')).must_equal values[:externalServices][0][:serviceTarget] - jq('.subsets[0].ports[0].port', resource('Endpoints')).must_equal values[:externalServices][0][:servicePort] - jq('.metadata.name', resource('Endpoints')).must_equal "common-test-external-0" - end - end -end -end diff --git a/.vscode/extensions.json b/.vscode/extensions.json index e6f236458b8..26c6fd7562e 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,5 +1,6 @@ { - "recommendations": [ - "ms-vscode-remote.remote-containers" - ] + "recommendations": [ + "ms-vscode-remote.remote-containers", + "rebornix.ruby" + ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index b54c90c7578..b619b7ba712 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -27,7 +27,7 @@ "exec", "m", "-r", - "${workspaceFolder}/.tools/tests/charts" + "${workspaceFolder}/tests" ] } ] diff --git a/charts/library/common-test/Chart.yaml b/charts/library/common-test/Chart.yaml index 3c28095a072..ce562118ed3 100644 --- a/charts/library/common-test/Chart.yaml +++ b/charts/library/common-test/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v2 kubeVersion: ">=1.16.0-0" name: common-test -version: 2.1.6 +version: 3.0.0 # upstream_version: appVersion: none description: Helper chart to test different use cases of the common library diff --git a/charts/library/common-test/values.yaml b/charts/library/common-test/values.yaml index f214e74b6d0..f12e55c316f 100644 --- a/charts/library/common-test/values.yaml +++ b/charts/library/common-test/values.yaml @@ -1,80 +1,9 @@ image: repository: b4bz/homer - tag: 21.03.2 + tag: latest pullPolicy: IfNotPresent services: main: port: port: 8080 - test1: - enabled: true - type: ClusterIP - port: - port: 8081 - name: tcp-test - protocol: TCP - targetPort: 8081 - test2: - enabled: true - type: ClusterIP - port: - port: 8082 - name: udp-test - protocol: UDP - targetPort: 8082 - -additionalServices: - - name: test3 - enabled: true - type: ClusterIP - port: - port: 8083 - name: extra-tcp-test - protocol: TCP - targetPort: 8083 - - name: test4 - enabled: true - type: ClusterIP - port: - port: 8084 - name: extra-udp-test - protocol: UDP - targetPort: 8084 - -ingress: - test1: - enabled: true - test2: - certType: "plain" - - -additionalIngress: - - name: "test3" - enabled: true - - name: "test4" - enabled: true - -# these values and names are set specifically with the unittests in mind. -deviceMounts: - test1: - enabled: true - emptyDir: true - devicePath: "/test1" - test2: - enabled: true - emptyDir: false - devicePath: "/test2" - -# these values and names are set specifically with the unittests in mind. -customStorage: - - enabled: true - emptyDir: true - mountPath: "/test3" - hostPath: "" - - name: "test4" - enabled: true - emptyDir: false - setPermissions: true - mountPath: "/test4" - hostPath: "/tmp" diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index c90dc12c3a6..761f578849b 100644 --- a/charts/library/common/Chart.yaml +++ b/charts/library/common/Chart.yaml @@ -19,4 +19,4 @@ name: common sources: - https://github.com/truecharts/apps/tree/master/library/common type: library -version: 3.5.8 +version: 4.0.0 diff --git a/charts/library/common/templates/_all.tpl b/charts/library/common/templates/_all.tpl index 9bb0b3eaf20..28391d77e00 100644 --- a/charts/library/common/templates/_all.tpl +++ b/charts/library/common/templates/_all.tpl @@ -19,9 +19,14 @@ Main entrypoint for the common library chart. It will render all underlying temp {{ else if eq .Values.controllerType "statefulset" }} {{- include "common.statefulset" . | nindent 0 }} {{- end -}} + {{ include "common.classes.hpa" . | nindent 0 }} {{ include "common.services" . | nindent 0 }} {{ include "common.ingress" . | nindent 0 }} - {{ include "common.resources.portal" . | nindent 0 }} - {{ include "common.storage.permissions" . | nindent 0 }} + {{- if .Values.secret -}} + {{- print "---" | nindent 0 -}} + {{ include "common.secret" . | nindent 0 }} + {{- end -}} + {{ include "common.classes.mountPermissions" . | nindent 0 }} + {{ include "common.classes.portal" . | nindent 0 }} {{- end -}} diff --git a/charts/library/common/templates/_ingress.tpl b/charts/library/common/templates/_ingress.tpl index b329c09c088..e4bec46807b 100644 --- a/charts/library/common/templates/_ingress.tpl +++ b/charts/library/common/templates/_ingress.tpl @@ -5,118 +5,30 @@ of the main Ingress and any additionalIngresses. {{- define "common.ingress" -}} {{- /* Generate named ingresses as required */ -}} {{- range $name, $ingress := .Values.ingress }} - {{- $certType := $ingress.certType | default "disabled" -}} - {{- $enabled := $ingress.enabled | default false -}} - {{- if or ( ne $certType "disabled" ) ( $ingress.enabled ) -}} - {{- print ("---") | nindent 0 -}} + {{- if $ingress.enabled -}} + {{- print ("---\n") | nindent 0 -}} {{- $ingressValues := $ingress -}} {{/* set defaults */}} - {{- if and (not $ingressValues.nameSuffix) ( ne $name "main" ) -}} + {{- if not $ingressValues.nameSuffix -}} {{- $_ := set $ingressValues "nameSuffix" $name -}} {{ end -}} {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} - {{- if not $ingressValues.type -}} - {{- $_ := set $ingressValues "type" "HTTP" -}} - {{ end -}} - {{- if not $ingressValues.certType -}} - {{- $_ := set $ingressValues "certType" "" -}} - {{ end -}} - - {{- if or ( eq $ingressValues.type "TCP" ) ( eq $ingressValues.type "UDP" ) ( eq $ingressValues.type "HTTP-IR" ) -}} - {{- include "common.classes.ingressRoute" $ -}} - {{- else -}} - {{- include "common.classes.ingress" $ -}} - {{ end -}} - - {{- if eq $ingressValues.certType "ixcert" -}} - {{- $_ := set $ "ObjectValues" (dict "certHolder" $ingressValues) -}} - {{- print ("---") | nindent 0 -}} - {{- include "common.resources.cert.secret" $ }} - {{ end -}} - {{- end }} - {{- end }} + {{- include "common.classes.ingress" $ }} - {{- /* Generate additional ingresses as required */ -}} - {{- range $index, $additionalIngress := .Values.additionalIngress }} - {{- $certType := $additionalIngress.certType | default "disabled" -}} - {{- if or ( ne $certType "disabled" ) ( $additionalIngress.enabled ) -}} - {{- print ("---") | nindent 0 -}} - {{- $ingressValues := $additionalIngress -}} - - {{/* set defaults */}} - {{- $name := $index -}} - {{- if $ingressValues.name -}} - {{- $name := $ingressValues.name -}} + {{- range $index, $tlsValues := $ingressValues.tls }} + {{- if .scaleCert }} + {{- $nameSuffix := ( printf "%v-%v-%v" $ingressValues.nameSuffix "tls" $index ) -}} + {{- $_ := set $tlsValues "nameSuffix" $nameSuffix -}} + {{- $_ := set $ "ObjectValues" (dict "certHolder" $tlsValues) -}} + {{- print ("---\n") | nindent 0 -}} + {{- include "common.cert.secret" $ -}} + {{- end }} {{- end }} - {{- if or (not $ingressValues.nameSuffix) ( ne ( $name | quote ) "main" ) -}} - {{- $_ := set $ingressValues "nameSuffix" $name -}} - {{ end -}} - {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} - {{- if not $ingressValues.type -}} - {{- $_ := set $ingressValues "type" "HTTP" -}} - {{ end -}} - {{- if not $ingressValues.certType -}} - {{- $_ := set $ingressValues "certType" "" -}} - {{ end -}} - {{- if or ( eq $ingressValues.type "TCP" ) ( eq $ingressValues.type "UDP" ) ( eq $ingressValues.type "HTTP-IR" ) -}} - {{- include "common.classes.ingressRoute" $ -}} - {{- else -}} - {{- include "common.classes.ingress" $ -}} - {{ end -}} - - {{- if eq $ingressValues.certType "ixcert" -}} - {{- $_ := set $ "ObjectValues" (dict "certHolder" $ingressValues) -}} - {{- print ("---") | nindent 0 -}} - {{- include "common.resources.cert.secret" $ }} - {{ end -}} {{- end }} {{- end }} - - {{- /* Generate externalService ingresses as required */ -}} - {{- range $index, $externalService := .Values.externalServices }} - {{- $certType := $externalService.certType | default "disabled" -}} - {{- if or ( ne $certType "disabled" ) ( $externalService.enabled ) -}} - {{- print ("---") | nindent 0 -}} - {{- $ingressValues := $externalService -}} - - {{/* set defaults */}} - {{- $name := $index -}} - {{- if $ingressValues.name -}} - {{- $name := $ingressValues.name -}} - {{- end }} - {{- $name = printf "%v-%v" "external" $name -}} - - {{- if or (not $ingressValues.nameSuffix) -}} - {{- $_ := set $ingressValues "nameSuffix" $name -}} - {{ end -}} - {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} - {{- if not $ingressValues.type -}} - {{- $_ := set $ingressValues "type" "HTTP" -}} - {{ end -}} - {{- if not $ingressValues.certType -}} - {{- $_ := set $ingressValues "certType" "" -}} - {{ end -}} - - {{- if or ( eq $ingressValues.type "TCP" ) ( eq $ingressValues.type "UDP" ) ( eq $ingressValues.type "HTTP-IR" ) -}} - {{- include "common.classes.ingressRoute" $ -}} - {{- else -}} - {{- include "common.classes.ingress" $ -}} - {{ end -}} - - {{- print ("---") | nindent 0 -}} - {{- include "common.classes.externalService" $ }} - - {{- if eq $ingressValues.certType "ixcert" -}} - {{- $_ := set $ "ObjectValues" (dict "certHolder" $ingressValues) -}} - {{- print ("---") | nindent 0 -}} - {{- include "common.resources.cert.secret" $ }} - {{ end -}} - {{- end }} - {{- end }} - {{- end }} diff --git a/charts/library/common/templates/_pvc.tpl b/charts/library/common/templates/_pvc.tpl index 1e00d3e44fa..4f2af2f3e64 100644 --- a/charts/library/common/templates/_pvc.tpl +++ b/charts/library/common/templates/_pvc.tpl @@ -23,14 +23,21 @@ of all the entries of the persistence key. {{- define "common.pvc" -}} {{- /* Generate pvc as required */ -}} {{- range $index, $PVC := .Values.persistence }} - {{- if and $PVC.enabled (not (or $PVC.emptyDir $PVC.existingClaim)) -}} + {{- $emptyDir := false -}} + {{- if $PVC.emptyDir -}} + {{- if $PVC.emptyDir.enabled -}} + {{- $emptyDir = true -}} + {{- end -}} + {{- end -}} + + {{- if and $PVC.enabled (not (or $emptyDir $PVC.existingClaim)) -}} {{- $persistenceValues := $PVC -}} {{- if not $persistenceValues.nameSuffix -}} {{- $_ := set $persistenceValues "nameSuffix" $index -}} {{- end -}} {{- $_ := set $ "ObjectValues" (dict "persistence" $persistenceValues) -}} {{- print ("---") | nindent 0 -}} - {{- include "common.classes.pvc" $ -}} + {{- include "common.classes.pvc" $ | nindent 0 -}} {{- end }} {{- end }} {{- end }} diff --git a/charts/library/common/templates/_secret.tpl b/charts/library/common/templates/_secret.tpl new file mode 100644 index 00000000000..34d10d9c87f --- /dev/null +++ b/charts/library/common/templates/_secret.tpl @@ -0,0 +1,16 @@ +{{/* +The Secret object to be created. +*/}} +{{- define "common.secret" -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "common.names.fullname" . }} + labels: + {{- include "common.labels" . | nindent 4 }} +type: Opaque +{{- with .Values.secret }} +stringData: + {{- toYaml . | nindent 2 }} +{{- end }} +{{- end }} diff --git a/charts/library/common/templates/_services.tpl b/charts/library/common/templates/_services.tpl index 9e72e9d04f5..18a39cf9d3c 100644 --- a/charts/library/common/templates/_services.tpl +++ b/charts/library/common/templates/_services.tpl @@ -1,46 +1,21 @@ {{/* Renders the Service objects required by the chart by returning a concatinated list -of the main Service and any additionalServices. +of the main Service and any additionalservice. */}} {{- define "common.services" -}} {{- if .Values.services -}} - {{- /* Add dict of primary services */ -}} {{- range $name, $service := .Values.services }} - {{- if or ( $service.enabled ) ( eq $name "main" ) -}} - {{- print ("---") | nindent 0 -}} - {{- print ("\n") | nindent 0 -}} + {{- if $service.enabled -}} + {{- print ("---\n") | nindent 0 -}} {{- $serviceValues := $service -}} - {{- /* Dont add name suffix for primary service named "main" */ -}} - {{- if and (not $serviceValues.nameSuffix) ( ne $name "main" ) -}} + {{- if $serviceValues.nameSuffix -}} {{- $_ := set $serviceValues "nameSuffix" $name -}} {{ end -}} + {{- $_ := set $ "ObjectValues" (dict "service" $serviceValues) -}} {{- include "common.classes.service" $ -}} {{- end }} {{- end }} {{- end }} - - - {{- if .Values.additionalServices -}} - {{- /* Generate additional services as required */ -}} - {{- range $index, $extraService := .Values.additionalServices }} - {{- if $extraService.enabled -}} - {{- print ("---") | nindent 0 -}} - {{- $serviceValues := $extraService -}} - - {{- $name := $index -}} - {{- if $serviceValues.name -}} - {{- $name := $serviceValues.name -}} - {{- end }} - - {{- /* Dont add name suffix for primary service named "main" */ -}} - {{- if and (not $serviceValues.nameSuffix) ( ne ( $name | quote ) "main" ) -}} - {{- $_ := set $serviceValues "nameSuffix" $name -}} - {{ end -}} - {{- $_ := set $ "ObjectValues" (dict "service" $serviceValues) -}} - {{- include "common.classes.service" $ -}} - {{- end }} - {{- end }} - {{- end }} {{- end }} diff --git a/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl b/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl new file mode 100644 index 00000000000..ae5769e2c26 --- /dev/null +++ b/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl @@ -0,0 +1,44 @@ +{{/* +This template serves as a blueprint for horizontal pod autoscaler objects that are created +using the common library. +*/}} +{{- define "common.classes.hpa" -}} +{{- if .Values.autoscaling }} +{{- if .Values.autoscaling.enabled }} +{{- print "---" | nindent 0 -}} +{{- $hpaName := include "common.names.fullname" . -}} +{{- $targetName := include "common.names.fullname" . -}} + +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ $hpaName }} + labels: + {{- include "common.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + {{- if eq .Values.controllerType "statefulset" }} + kind: StatefulSet + {{- else }} + kind: Deployment + {{- end }} + name: {{ .Values.autoscaling.target | default $targetName }} + minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} + maxReplicas: {{ .Values.autoscaling.maxReplicas | default 3 }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/classes/_ingress.tpl b/charts/library/common/templates/classes/_ingress.tpl new file mode 100644 index 00000000000..8efc187a78a --- /dev/null +++ b/charts/library/common/templates/classes/_ingress.tpl @@ -0,0 +1,90 @@ +{{/* +This template serves as a blueprint for all Ingress objects that are created +within the common library. +*/}} +{{- define "common.classes.ingress" -}} +{{- $ingressName := include "common.names.fullname" . -}} +{{- $values := index .Values.ingress (keys .Values.ingress | first) -}} + +{{- if hasKey . "ObjectValues" -}} + {{- with .ObjectValues.ingress -}} + {{- $values = . -}} + {{- end -}} +{{ end -}} + +{{- if hasKey $values "nameSuffix" -}} + {{- $ingressName = printf "%v-%v" $ingressName $values.nameSuffix -}} +{{ end -}} + +{{- $svc := index .Values.services (keys .Values.services | first) -}} +{{- $svcName := $values.serviceName | default (include "common.names.fullname" .) -}} +{{- $svcPort := $values.servicePort | default $svc.port.port -}} + +apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} +kind: Ingress +metadata: + name: {{ $ingressName }} + labels: + {{- include "common.labels" . | nindent 4 }} + {{- with $values.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} + {{- if $values.ingressClassName }} + ingressClassName: {{ $values.ingressClassName }} + {{- end }} + {{- end }} + {{- if $values.tls }} + tls: + {{- range $index, $tlsValues := $values.tls }} + - hosts: + {{- range $tlsValues.hosts }} + - {{ . | quote }} + {{- end }} + {{- range $tlsValues.hostsTpl }} + - {{ tpl . $ | quote }} + {{- end }} + {{- if or $tlsValues.secretNameTpl $tlsValues.secretName $tlsValues.scaleCert }} + {{- if $tlsValues.scaleCert }} + secretName: {{ ( printf "%v-%v-%v-%v-%v" $ingressName "tls" $index "ixcert" $tlsValues.scaleCert ) }} + {{- else if $tlsValues.secretNameTpl }} + secretName: {{ tpl $tlsValues.secretNameTpl $ | quote}} + {{- else }} + secretName: {{ $tlsValues.secretName }} + {{- end }} + {{- end }} + {{- end }} + {{- end }} + rules: + {{- range $values.hosts }} + {{- if .hostTpl }} + - host: {{ tpl .hostTpl $ | quote }} + {{- else }} + - host: {{ .host | quote }} + {{- end }} + http: + paths: + {{- range .paths }} + {{- if .pathTpl }} + - path: {{ tpl .pathTpl $ | quote }} + {{- else }} + - path: {{ .path | quote }} + {{- end }} + {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} + pathType: {{ default "Prefix" .pathType }} + {{- end }} + backend: + {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} + service: + name: {{ .serviceName | default $svcName }} + port: + number: {{ .servicePort | default $svcPort }} + {{- else }} + serviceName: {{ .serviceName | default $svcName }} + servicePort: {{ .servicePort | default $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/charts/library/common/templates/classes/_mountPermissions.tpl b/charts/library/common/templates/classes/_mountPermissions.tpl new file mode 100644 index 00000000000..a830b5dc7ea --- /dev/null +++ b/charts/library/common/templates/classes/_mountPermissions.tpl @@ -0,0 +1,91 @@ +{{/* +This template serves as the blueprint for the mountPermissions job that is run +before chart installation. +*/}} +{{- define "common.classes.mountPermissions" -}} +{{- if .Values.hostPathMounts -}} + +{{- $jobName := include "common.names.fullname" . -}} +{{- $values := .Values -}} +{{- $user := 568 -}} +{{- $group := 568 -}} +{{- print "---" | nindent 0 -}} + +{{- if $values.podSecurityContext }} + {{- if $values.podSecurityContext.runAsUser }} + {{- $user = $values.podSecurityContext.runAsUser -}} + {{- end -}} + {{- if $values.podSecurityContext.fsGroup -}} + {{- $group = $values.podSecurityContext.fsGroup -}} + {{- end -}} +{{- else if $values.env }} + {{- if $values.env.PUID }} + {{- $user = $values.env.PUID -}} + {{- end -}} + {{- if $values.env.PGID }} + {{- $group = $values.env.PGID -}} + {{- end -}} +{{- end -}} + +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ $jobName }}-autopermissions + labels: + {{- include "common.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-10" + "helm.sh/hook-delete-policy": hook-succeeded,hook-failed,before-hook-creation +spec: + template: + metadata: + spec: + restartPolicy: Never + containers: + - name: set-mount-permissions + image: "alpine:3.3" + command: + - /bin/sh + - -c + - | {{ range $index, $hpm := .Values.hostPathMounts}}{{ if and $hpm.enabled $hpm.setPermissions}} + chown -R {{ print $user }}:{{ print $group }} {{ print $hpm.mountPath }}{{ end }}{{ end }} + #args: + # + #securityContext: + # + volumeMounts: + {{ range $name, $hpmm := .Values.hostPathMounts }} + {{- if $hpmm.enabled -}} + {{- if $hpmm.setPermissions -}} + {{ if $hpmm.name }} + {{ $name = $hpmm.name }} + {{ end }} + - name: hostpathmounts-{{ $name }} + mountPath: {{ $hpmm.mountPath }} + {{ if $hpmm.subPath }} + subPath: {{ $hpmm.subPath }} + {{ end }} + {{- end -}} + {{- end -}} + {{ end }} + volumes: + {{- range $name, $hpm := .Values.hostPathMounts -}} + {{ if $hpm.enabled }} + {{ if $hpm.setPermissions }} + {{ if $hpm.name }} + {{ $name = $hpm.name }} + {{ end }} + - name: hostpathmounts-{{ $name }} + {{ if $hpm.emptyDir }} + emptyDir: {} + {{- else -}} + hostPath: + path: {{ required "hostPath not set" $hpm.hostPath }} + {{ end }} + {{ end }} + {{ end }} + {{- end -}} + +{{- end }} +{{- end }} diff --git a/charts/library/common/templates/classes/_portal.tpl b/charts/library/common/templates/classes/_portal.tpl new file mode 100644 index 00000000000..ce1919d5749 --- /dev/null +++ b/charts/library/common/templates/classes/_portal.tpl @@ -0,0 +1,72 @@ +{{- define "common.classes.portal" -}} + +{{- if .Values.portal }} +{{- if .Values.portal.enabled }} +{{- $svc := index .Values.services (keys .Values.services | first) -}} +{{- $ingr := index .Values.ingress (keys .Values.ingress | first) -}} +{{- $host := "$node_ip" }} +{{- $port := 443 }} +{{- $protocol := "https" }} +{{- $portProtocol := "" }} +{{- $path := "/" }} + +{{- if $ingr }} + {{- if $ingr.enabled }} + {{- range $ingr.hosts }} + {{- if .hostTpl }} + {{ $host = ( tpl .hostTpl $ ) }} + {{- else if .host }} + {{ $host = .host }} + {{- else }} + {{ $host = "$node_ip" }} + {{- end }} + {{- if .paths }} + {{- $path = (first .paths).path }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} + +{{- if and ( .Values.portal.ingressPort ) ( ne $host "$node_ip" ) }} + {{- $port = .Values.portal.ingressPort }} +{{- else if eq $host "$node_ip" }} + {{- if eq $svc.type "NodePort" }} + {{- $port = $svc.port.nodePort }} + {{- if or ( eq $svc.port.protocol "HTTP" ) ( eq $svc.port.protocol "HTTPS" ) }} + {{- $portProtocol = $svc.port.protocol }} + {{- end }} + {{- end }} +{{- end }} + +{{- if and ( $portProtocol ) ( eq $host "$node_ip" ) }} + {{- $protocol = $portProtocol }} +{{- else if and ( ne $host "$node_ip" ) }} + {{- if $ingr.tls }} + {{- $protocol = "https" }} + {{- end }} +{{- end }} + +{{- if and ( .Values.portal.host ) ( eq $host "$node_ip" ) }} + {{- $host = .Values.portal.host }} +{{- end }} + +{{- if and ( .Values.portal.path ) }} + {{- $path = .Values.portal.path }} +{{- end }} + +{{- print "---" | nindent 0 -}} + +apiVersion: v1 +kind: ConfigMap +metadata: + name: portal + labels: {{ include "common.labels" . | nindent 4 }} +data: + protocol: {{ $protocol }} + host: {{ $host | quote }} + port: {{ $port | quote }} + path: {{ $path | quote }} + url: {{ ( printf "%v://%v:%v%v" $protocol $host $port $path ) | quote }} +{{- end }} +{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/classes/_pvc.tpl b/charts/library/common/templates/classes/_pvc.tpl index 5799ae0a8f8..038ed3de5c1 100644 --- a/charts/library/common/templates/classes/_pvc.tpl +++ b/charts/library/common/templates/classes/_pvc.tpl @@ -31,7 +31,9 @@ within the common library. {{- if hasKey $values "nameOverride" -}} {{- $pvcName = $values.nameOverride -}} {{- else if hasKey $values "nameSuffix" -}} - {{- $pvcName = printf "%v-%v" $pvcName $values.nameSuffix -}} + {{- if not (eq $values.nameSuffix "-") -}} + {{- $pvcName = printf "%v-%v" $pvcName $values.nameSuffix -}} + {{ end -}} {{ end -}} kind: PersistentVolumeClaim apiVersion: v1 @@ -55,8 +57,6 @@ spec: requests: storage: {{ required (printf "size is required for PVC %v" $pvcName) $values.size | quote }} {{- if $values.storageClass }} - storageClassName: {{ include "common.storage.class" . }} - {{- else }} - storageClassName: {{ ( printf "%v-%v" "ix-storage-class" .Release.Name ) }} + storageClassName: {{ if (eq "-" $values.storageClass) }}""{{- else if (eq "SCALE-ZFS" $values.storageClass ) }}{{ ( printf "%v-%v" "ix-storage-class" .Release.Name ) }}{{- else }}{{ $values.storageClass | quote }}{{- end }} {{- end }} {{- end -}} diff --git a/charts/library/common/templates/classes/_service.tpl b/charts/library/common/templates/classes/_service.tpl index c8243072605..cfaec8bc46a 100644 --- a/charts/library/common/templates/classes/_service.tpl +++ b/charts/library/common/templates/classes/_service.tpl @@ -21,27 +21,17 @@ This template serves as a blueprint for all Service objects that are created within the common library. */}} {{- define "common.classes.service" -}} -{{- $values := .Values.services.main -}} +{{- $values := index .Values.services (keys .Values.services | first) -}} {{- if hasKey . "ObjectValues" -}} {{- with .ObjectValues.service -}} {{- $values = . -}} {{- end -}} {{ end -}} - {{- $serviceName := include "common.names.fullname" . -}} - - {{- if hasKey $values "nameSuffix" -}} {{- $serviceName = printf "%v-%v" $serviceName $values.nameSuffix -}} {{ end -}} {{- $svcType := $values.type | default "" -}} - -{{- $portProtocol := $values.port.protocol -}} -{{- if or ( eq $values.port.protocol "HTTP" ) ( eq $values.port.protocol "HTTPS" ) ( eq $values.port.protocol "TCP" ) -}} -{{- $portProtocol = "TCP" -}} -{{- else if eq $values.port.protocol "UDP" }} -{{- $portProtocol = "UDP" -}} -{{- end }} apiVersion: v1 kind: Service metadata: @@ -52,7 +42,7 @@ metadata: {{ toYaml $values.labels | nindent 4 }} {{- end }} annotations: - {{- if eq $values.port.protocol "HTTPS" }} + {{- if eq ( $values.port.protocol | default "" ) "HTTPS" }} traefik.ingress.kubernetes.io/service.serversscheme: https {{- end }} {{- with $values.annotations }} diff --git a/charts/library/common/templates/classes/_service_ports.tpl b/charts/library/common/templates/classes/_service_ports.tpl index 859c3ff5199..7a9f62b70da 100644 --- a/charts/library/common/templates/classes/_service_ports.tpl +++ b/charts/library/common/templates/classes/_service_ports.tpl @@ -29,15 +29,17 @@ Render all the ports and additionalPorts for a Service object. {{- if $ports -}} ports: {{- range $_ := $ports }} - {{- $protocol := "" -}} - {{- if or ( eq .protocol "HTTP" ) ( eq .protocol "HTTPS" ) }} - {{- $protocol = "TCP" -}} - {{- else }} - {{- $protocol = .protocol | default "TCP" -}} - {{- end }} - port: {{ .port }} targetPort: {{ .targetPort | default .name | default "http" }} - protocol: {{ $protocol | default "TCP" }} + {{- if .protocol }} + {{- if or ( eq .protocol "HTTP" ) ( eq .protocol "HTTPS" ) ( eq .protocol "TCP" ) }} + protocol: TCP + {{- else }} + protocol: {{ .protocol }} + {{- end }} + {{- else }} + protocol: TCP + {{- end }} name: {{ .name | default "http" }} {{- if (and (eq $.svcType "NodePort") (not (empty .nodePort))) }} nodePort: {{ .nodePort }} diff --git a/charts/library/common/templates/classes/ingress/_externalService.tpl b/charts/library/common/templates/classes/ingress/_externalService.tpl deleted file mode 100644 index a2aedaf5f00..00000000000 --- a/charts/library/common/templates/classes/ingress/_externalService.tpl +++ /dev/null @@ -1,63 +0,0 @@ -{{- define "common.classes.externalService" -}} -{{- $serviceName := include "common.names.fullname" . -}} -{{- $values := .Values -}} -{{- $svcPort := 80 }} -{{- $ingressService := $.Values }} -{{- if hasKey . "ObjectValues" -}} - {{- with .ObjectValues.ingress -}} - {{- $values = . -}} - {{- end -}} -{{ end -}} - -{{- if hasKey $values "nameSuffix" -}} - {{- $serviceName = printf "%v-%v" $serviceName $values.nameSuffix -}} -{{ end -}} - -{{- $svcName := $values.serviceName | default $serviceName -}} - -{{- if $values.servicePort }} - {{- $svcPort = $values.servicePort -}} -{{- end }} - -apiVersion: v1 -kind: Service -metadata: - name: {{ $svcName }} - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - {{- if eq ( $values.serviceType | default "" ) "HTTPS" }} - traefik.ingress.kubernetes.io/service.serversscheme: https - {{- end }} - {{- with $values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - ports: -{{- if eq $values.type "UDP"}} - - protocol: UDP - port: {{ $values.servicePort }} - targetPort: {{ $values.servicePort }} -{{- else }} - - protocol: TCP - port: {{ $values.servicePort }} - targetPort: {{ $values.servicePort }} -{{- end }} ---- -apiVersion: v1 -kind: Endpoints -metadata: - name: {{ $svcName }} - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - {{- with $values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -subsets: - - addresses: - - ip: {{ $values.serviceTarget }} - ports: - - port: {{ $values.servicePort }} - -{{- end }} diff --git a/charts/library/common/templates/classes/ingress/_ingress.tpl b/charts/library/common/templates/classes/ingress/_ingress.tpl deleted file mode 100644 index a5dcda2ebcc..00000000000 --- a/charts/library/common/templates/classes/ingress/_ingress.tpl +++ /dev/null @@ -1,143 +0,0 @@ -{{/* -This template serves as a blueprint for all Ingress objects that are created -within the common library. -*/}} -{{- define "common.classes.ingress" -}} -{{- $ingressName := include "common.names.fullname" . -}} -{{- $values := .Values -}} -{{- $svcPort := 80 -}} -{{- $portProtocol := "" -}} -{{- $ingressService := $.Values -}} -{{- if hasKey . "ObjectValues" -}} - {{- with .ObjectValues.ingress -}} - {{- $values = . -}} - {{- end -}} -{{ end -}} - - -{{- if hasKey $values "nameSuffix" -}} - {{- $ingressName = printf "%v-%v" $ingressName $values.nameSuffix -}} - {{- if and ( $.Values.services ) ( not $values.servicePort ) }} - {{- $ingressService := index $.Values.services ( $values.nameSuffix | quote ) }} - {{- $svcPort = $ingressService.port.port -}} - {{- $portProtocol = $ingressService.port.protocol | default "" }} - {{ end -}} -{{- else if and ( $.Values.services ) ( not $values.servicePort ) }} - {{- $svcPort = $.Values.services.main.port.port -}} - {{- $portProtocol = $.Values.services.main.port.protocol | default "" -}} -{{ end -}} - -{{- $authForwardName := ( printf "%v-%v" $ingressName "auth-forward" ) -}} - -{{- $svcName := $values.serviceName | default $ingressName -}} - -{{- if $values.dynamicServiceName }} - {{- $dynamicServiceName := printf "%v-%v" .Release.Name $values.dynamicServiceName -}} - {{- $svcName = $dynamicServiceName -}} -{{- end }} - -{{- if $values.servicePort }} - {{- $svcPort = $values.servicePort -}} -{{- end }} - -{{- if $values.serviceType }} - {{- $portProtocol = $values.serviceType -}} -{{- end }} - -apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} -kind: Ingress -metadata: - name: {{ $ingressName }} - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - {{- if eq $portProtocol "HTTPS" }} - traefik.ingress.kubernetes.io/service.serversscheme: https - {{- end }} - traefik.ingress.kubernetes.io/router.entrypoints: {{ $values.entrypoint | default "websecure" }} - traefik.ingress.kubernetes.io/router.middlewares: traefik-middlewares-chain-public@kubernetescrd{{ if $values.authForwardURL }},{{ printf "%v-%v@%v" .Release.Namespace $authForwardName "kubernetescrd" }}{{ end }} - {{- with $values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - {{- if $values.ingressClassName }} - ingressClassName: {{ $values.ingressClassName }} - {{- end }} - {{- end }} - {{- if or ( eq $values.certType "selfsigned") (eq $values.certType "ixcert") }} - tls: - - hosts: - {{- if $values.host}} - - {{ $values.host | quote }} - {{- else }} - {{- range $values.hosts }} - - {{ .host | quote }} - {{- end }} - {{- end }} - {{- if eq $values.certType "ixcert" }} - secretName: {{ $ingressName }} - {{- end }} - {{- end }} - rules: - {{- if $values.host }} - - host: {{ $values.host | quote }} - http: - paths: - - path: {{ $values.path | default "/" }} - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - pathType: Prefix - {{- end }} - backend: - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - service: - name: {{ $svcName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - {{- range $values.hosts }} - - host: {{ .host | quote }} - http: - paths: - - path: {{ .path | default "/" }} - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - pathType: Prefix - {{- end }} - backend: - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - service: - name: {{ $svcName }} - port: - number: {{ $svcPort }} - {{- else }} - serviceName: {{ $svcName }} - servicePort: {{ $svcPort }} - {{- end }} - {{- end }} - -{{- if $values.authForwardURL }} - ---- - -apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware -metadata: - name: {{ $authForwardName }} -spec: - forwardAuth: - address: {{ $values.authForwardURL | quote }} - tls: - insecureSkipVerify: true - trustForwardHeader: true - authResponseHeaders: - - Remote-User - - Remote-Groups - - Remote-Name - - Remote-Email -{{- end }} - -{{- end }} diff --git a/charts/library/common/templates/classes/ingress/_ingressRoute.tpl b/charts/library/common/templates/classes/ingress/_ingressRoute.tpl deleted file mode 100644 index a44fe553ac7..00000000000 --- a/charts/library/common/templates/classes/ingress/_ingressRoute.tpl +++ /dev/null @@ -1,127 +0,0 @@ -{{/* -This template serves as a blueprint for all ingressRoute objects that are created -within the common library. -*/}} -{{- define "common.classes.ingressRoute" -}} -{{- $ingressName := include "common.names.fullname" . -}} -{{- $values := .Values -}} -{{- $svcPort := 80 }} -{{- $portProtocol := "" }} -{{- $ingressService := $.Values }} -{{- if hasKey . "ObjectValues" -}} - {{- with .ObjectValues.ingress -}} - {{- $values = . -}} - {{- end -}} -{{ end -}} - -{{- if hasKey $values "nameSuffix" -}} - {{- $ingressName = printf "%v-%v" $ingressName $values.nameSuffix -}} - {{- if and ( $.Values.services ) ( not $values.servicePort ) }} - {{- $ingressService := index $.Values.services ( $values.nameSuffix | quote) }} - {{- $svcPort = $ingressService.port.port }} - {{- $portProtocol = $ingressService.port.protocol | default "" }} - {{ end -}} -{{- else if and ( $.Values.services ) ( not $values.servicePort ) }} - {{- $svcPort = $.Values.services.main.port.port }} - {{- $portProtocol = $.Values.services.main.port.protocol | default "" }} -{{ end -}} - -{{- $authForwardName := ( printf "%v-%v" $ingressName "auth-forward" ) -}} - -{{- $svcName := $values.serviceName | default $ingressName -}} - -{{- if $values.servicePort }} - {{- $svcPort = $values.servicePort }} -{{- end }} - -{{- if $values.serviceType }} - {{- $portProtocol = $values.serviceType }} -{{- end }} - -apiVersion: traefik.containo.us/v1alpha1 -{{- if eq $values.type "UDP" }} -kind: IngressRouteUDP -{{- else if eq $values.type "TCP" }} -kind: IngressRouteTCP -{{- else }} -kind: IngressRoute -{{- end }} -metadata: - name: {{ $ingressName }} - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - {{- with $values.annotations }} - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - entryPoints: - - {{ $values.entrypoint }} - routes: - {{- if eq $values.type "UDP" }} - - services: - - name: {{ $svcName }} - port: {{ $svcPort }} - weight: 10 - {{- else if eq $values.type "TCP" }} - - match: HostSNI(`*`) - services: - - name: {{ $svcName }} - port: {{ $svcPort }} - weight: 10 - terminationDelay: 400 - {{- else }} - - kind: Rule - match: Host(`{{ (index $values.hosts 0).host }}`) && PathPrefix(`{{ (index $values.hosts 0).path | default "/" }}`) - services: - - name: {{ $svcName }} - {{- if $values.serviceKind }} - kind: {{ $values.serviceKind }} - {{- else }} - port: {{ $svcPort }} - {{- end }} - middlewares: - - name: traefik-middlewares-chain-public@kubernetescrd - {{- if $values.authForwardURL }} - - name: "{{ printf "%v-%v@%v" .Release.Namespace $authForwardName "kubernetescrd" }}" - {{- end }} - {{- end }} - -{{- if not ( eq $values.type "UDP" ) }} -{{- if or ( eq $values.certType "selfsigned") (eq $values.certType "ixcert") }} - tls: - domains: - - main: {{ (index $values.hosts 0).host }} - sans: - {{- range $values.hosts }} - - {{ .host | quote }} - {{- end }} - {{- if eq $values.certType "ixcert" }} - secretName: {{ $ingressName }} - {{- end }} - passthrough: false - -{{- end }} -{{- end }} - -{{- if $values.authForwardURL }} ---- - -apiVersion: traefik.containo.us/v1alpha1 -kind: Middleware -metadata: - name: {{ $authForwardName }} -spec: - forwardAuth: - address: {{ $values.authForwardURL | quote }} - tls: - insecureSkipVerify: true - trustForwardHeader: true - authResponseHeaders: - - Remote-User - - Remote-Groups - - Remote-Name - - Remote-Email - -{{- end }} -{{- end }} diff --git a/charts/library/common/templates/lib/cert/_certSecret.yaml b/charts/library/common/templates/lib/cert/_certSecret.yaml new file mode 100644 index 00000000000..fe133800f37 --- /dev/null +++ b/charts/library/common/templates/lib/cert/_certSecret.yaml @@ -0,0 +1,27 @@ +{{- define "common.cert.secret" -}} + +{{- $secretName := include "common.names.fullname" . -}} + +{{- if .ObjectValues.certHolder -}} + {{- if hasKey .ObjectValues.certHolder "nameSuffix" -}} + {{- $secretName = ( printf "%v-%v-%v-%v" $secretName .ObjectValues.certHolder.nameSuffix "ixcert" .ObjectValues.certHolder.scaleCert ) -}} + {{- else }} + {{- $secretName = ( printf "%v-%v-%v" $secretName "ixcert" .ObjectValues.certHolder.scaleCert ) -}} + {{ end -}} +{{ else }} + {{- $_ := set $ "ObjectValues" (dict "certHolder" .Values) -}} + {{- $secretName = ( printf "%v-%v-%v-%v" $secretName "scalecert" "ixcert" .Values.scaleCert ) -}} +{{ end -}} + +{{- if eq (include "common.cert.available" $ ) "true" -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + labels: {{ include "common.labels" . | nindent 4 }} +type: kubernetes.io/tls +data: + tls.crt: {{ (include "common.cert.publicKey" $ ) | toString | b64enc | quote }} + tls.key: {{ (include "common.cert.privateKey" $ ) | toString | b64enc | quote }} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/cert/_certs.tpl b/charts/library/common/templates/lib/cert/_certs.tpl new file mode 100644 index 00000000000..bc223d25c5c --- /dev/null +++ b/charts/library/common/templates/lib/cert/_certs.tpl @@ -0,0 +1,57 @@ +{{/* +Retrieve true/false if certificate is configured +*/}} +{{- define "common.cert.available" -}} +{{- if .ObjectValues.certHolder.scaleCert -}} +{{- $values := (. | mustDeepCopy) -}} +{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.scaleCert) -}} +{{- template "common.cert_present" $values -}} +{{- else -}} +{{- false -}} +{{- end -}} +{{- end -}} + + +{{/* +Retrieve public key of certificate +*/}} +{{- define "common.cert.publicKey" -}} +{{- $values := (. | mustDeepCopy) -}} +{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.scaleCert "publicKey" true) -}} +{{ include "common.cert" $values }} +{{- end -}} + + +{{/* +Retrieve private key of certificate +*/}} +{{- define "common.cert.privateKey" -}} +{{- $values := (. | mustDeepCopy) -}} +{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.scaleCert) -}} +{{ include "common.cert" $values }} +{{- end -}} + +{{/* +Retrieve true/false if certificate is available in ixCertificates +*/}} +{{- define "common.cert_present" -}} +{{- $values := . -}} +{{- hasKey $values.Values.ixCertificates ($values.commonCertOptions.certKeyName | toString) -}} +{{- end -}} + + +{{/* +Retrieve certificate from variable name +*/}} +{{- define "common.cert" -}} +{{- $values := . -}} +{{- $certKey := ($values.commonCertOptions.certKeyName | toString) -}} +{{- if hasKey $values.Values.ixCertificates $certKey -}} +{{- $cert := get $values.Values.ixCertificates $certKey -}} +{{- if $values.commonCertOptions.publicKey -}} +{{ $cert.certificate }} +{{- else -}} +{{ $cert.privatekey }} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_capabilities.tpl b/charts/library/common/templates/lib/chart/_capabilities.tpl index 37ff7d7420a..809dcae467d 100644 --- a/charts/library/common/templates/lib/chart/_capabilities.tpl +++ b/charts/library/common/templates/lib/chart/_capabilities.tpl @@ -87,9 +87,7 @@ Return the appropriate apiVersion for Ingress objects. */}} {{- define "common.capabilities.ingress.apiVersion" -}} -{{- if .Values.ingress.apiVersion -}} -{{- .Values.ingress.apiVersion -}} -{{- else if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} +{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} {{- print "extensions/v1beta1" -}} {{- else if semverCompare "<1.19-0" .Capabilities.KubeVersion.GitVersion -}} {{- print "networking.k8s.io/v1beta1" -}} @@ -110,37 +108,3 @@ Waiting on https://github.com/helm/helm/pull/8608 {{- end }} {{- end -}} */}} - -{{/* -Return the appropriate apiVersion for RBAC resources. -*/}} -{{- define "common.capabilities.rbac.apiVersion" -}} -{{- if semverCompare "<1.17-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "rbac.authorization.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "rbac.authorization.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Return the appropriate apiVersion for CRDs. -*/}} -{{- define "common.capabilities.crd.apiVersion" -}} -{{- if semverCompare "<1.19-0" (include "common.capabilities.kubeVersion" .) -}} -{{- print "apiextensions.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "apiextensions.k8s.io/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Returns true if the used Helm version is 3.3+. -A way to check the used Helm version was not introduced until version 3.3.0 with .Capabilities.HelmVersion, which contains an additional "{}}" structure. -This check is introduced as a regexMatch instead of {{ if .Capabilities.HelmVersion }} because checking for the key HelmVersion in <3.3 results in a "interface not found" error. -**To be removed when the catalog's minimun Helm version is 3.3** -*/}} -{{- define "common.capabilities.supportsHelmVersion" -}} -{{- if regexMatch "{(v[0-9])*[^}]*}}$" (.Capabilities | toString ) }} - {{- true -}} -{{- end -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_labels.tpl b/charts/library/common/templates/lib/chart/_labels.tpl index b5be05142c0..760bdd65db9 100644 --- a/charts/library/common/templates/lib/chart/_labels.tpl +++ b/charts/library/common/templates/lib/chart/_labels.tpl @@ -35,21 +35,3 @@ Selector labels shared across objects. app.kubernetes.io/name: {{ include "common.names.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} - - -## Bitnami Compatibility links - -{{/* vim: set filetype=mustache: */}} -{{/* -Kubernetes standard labels -*/}} -{{- define "common.labels.standard" -}} -{{ include "common.labels" . }} -{{- end -}} - -{{/* -Labels to use on deploy.spec.selector.matchLabels and svc.spec.selector -*/}} -{{- define "common.labels.matchLabels" -}} -{{ include "common.labels.selectorLabels" . }} -{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_names.tpl b/charts/library/common/templates/lib/chart/_names.tpl index 41273d69c96..0112cc3b3f0 100644 --- a/charts/library/common/templates/lib/chart/_names.tpl +++ b/charts/library/common/templates/lib/chart/_names.tpl @@ -21,8 +21,8 @@ This file is considered to be modified by the TrueCharts Project. Expand the name of the chart. */}} {{- define "common.names.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} -{{- end -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} {{/* Create a default fully qualified app name. @@ -30,18 +30,17 @@ We truncate at 63 chars because some Kubernetes name fields are limited to this If release name contains chart name it will be used as a full name. */}} {{- define "common.names.fullname" -}} -{{- if .Values.fullnameOverride -}} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- if contains $name .Release.Name -}} -{{- .Release.Name | trunc 63 | trimSuffix "-" -}} -{{- else -}} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} -{{- end -}} -{{- end -}} - +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} {{/* Create chart name and version as used by the chart label. diff --git a/charts/library/common/templates/lib/controller/_container.tpl b/charts/library/common/templates/lib/controller/_container.tpl index cdd777ab0f3..fabfeaa2e50 100644 --- a/charts/library/common/templates/lib/controller/_container.tpl +++ b/charts/library/common/templates/lib/controller/_container.tpl @@ -22,71 +22,84 @@ The main container included in the controller. */ -}} {{- define "common.controller.mainContainer" -}} - name: {{ include "common.names.fullname" . }} - image: "{{ include "common.images.image" (dict "imageRoot" .Values.image "global" .Values.global) }}" + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: {{ .Values.image.pullPolicy }} {{- with .Values.command }} + {{- if kindIs "string" . }} command: {{ . }} + {{- else }} + command: + {{ toYaml . | nindent 2 }} + {{- end }} {{- end }} {{- with .Values.args }} + {{- if kindIs "string" . }} args: {{ . }} + {{- else }} + args: + {{ toYaml . | nindent 2 }} + {{- end }} {{- end }} {{- with .Values.securityContext }} securityContext: {{- toYaml . | nindent 4 }} {{- end }} + {{- with .Values.lifecycle }} + lifecycle: + {{- toYaml . | nindent 2 }} + {{- end }} env: - - name: PUID - value: {{ .Values.PUID | quote }} - - name: PGID - value: {{ .Values.PGID | quote }} - - name: UMASK - value: {{ .Values.UMASK | quote }} {{- if .Values.timezone }} - name: TZ value: {{ .Values.timezone | quote }} {{- end }} - {{- if or .Values.env .Values.envTpl .Values.envValueFrom .Values.envVariable .Values.environmentVariables }} - {{- range $envVariable := .Values.environmentVariables }} - {{- if and $envVariable.name $envVariable.value }} - - name: {{ $envVariable.name }} - value: {{ $envVariable.value | quote }} + {{- if or .Values.env .Values.envTpl .Values.envValueFrom .Values.envVariable .Values.envList }} + {{- range $envList := .Values.envList }} + {{- if and $envList.name $envList.value }} + - name: {{ $envList.name }} + value: {{ $envList.value | quote }} {{- else }} {{- fail "Please specify name/value for environment variable" }} {{- end }} {{- end}} {{- range $key, $value := .Values.env }} - - name: {{ $key }} - value: {{ $value | quote }} + - name: {{ $key }} + value: {{ $value | quote }} {{- end }} {{- range $key, $value := .Values.envTpl }} - - name: {{ $key }} - value: {{ tpl $value $ | quote }} + - name: {{ $key }} + value: {{ tpl $value $ | quote }} {{- end }} {{- range $key, $value := .Values.envValueFrom }} - - name: {{ $key }} - valueFrom: - {{- $value | toYaml | nindent 8 }} + - name: {{ $key }} + valueFrom: + {{- $value | toYaml | nindent 6 }} {{- end }} {{- end }} - {{- with .Values.envFrom }} + {{- if or .Values.envFrom .Values.secret }} envFrom: - {{- toYaml . | nindent 12 }} + {{- with .Values.envFrom }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- if or .Values.secret }} + - secretRef: + name: {{ include "common.names.fullname" . }} + {{- end }} {{- end }} {{- include "common.controller.ports" . | trim | nindent 2 }} - {{- with (include "common.controller.volumeMounts" . | trim) }} volumeMounts: {{- . | nindent 2 }} {{- end }} - - {{- include "common.controller.probes" . | nindent 2 }} + + {{/* + Merges the TrueNAS SCALE generated GPU info with the .Values.resources dict + */}} + {{- $resources := dict "limits" ( .Values.scaleGPU | default dict ) }} + {{- $resources = merge $resources .Values.resources }} resources: - {{- with .Values.resources }} + {{- with $resources }} {{- toYaml . | nindent 4 }} {{- end }} - {{- if and .Values.gpuConfiguration }} - limits: - {{- toYaml .Values.gpuConfiguration | nindent 6 }} - {{- end }} {{- end -}} diff --git a/charts/library/common/templates/lib/controller/_pod.tpl b/charts/library/common/templates/lib/controller/_pod.tpl index 90196a4b5ac..5a053a41827 100644 --- a/charts/library/common/templates/lib/controller/_pod.tpl +++ b/charts/library/common/templates/lib/controller/_pod.tpl @@ -24,9 +24,7 @@ hostNetwork: {{ . }} hostname: {{ . }} {{- end }} {{- if .Values.dnsPolicy }} -{{- with .Values.dnsPolicy }} -dnsPolicy: {{ . }} -{{- end }} +dnsPolicy: {{ .Values.dnsPolicy }} {{- else if .Values.hostNetwork }} dnsPolicy: "ClusterFirstWithHostNet" {{- else }} @@ -44,7 +42,7 @@ initContainers: containers: {{- include "common.controller.mainContainer" . | nindent 0 }} {{- with .Values.additionalContainers }} - {{- toYaml . | nindent 0 }} + {{- tpl (toYaml .) $ | nindent 0 }} {{- end }} {{- with (include "common.controller.volumes" . | trim) }} volumes: diff --git a/charts/library/common/templates/lib/controller/_ports.tpl b/charts/library/common/templates/lib/controller/_ports.tpl index 528b233d991..13b1e8e0185 100644 --- a/charts/library/common/templates/lib/controller/_ports.tpl +++ b/charts/library/common/templates/lib/controller/_ports.tpl @@ -1,34 +1,13 @@ -{{/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -`SPDX-License-Identifier: Apache-2.0` - -This file is considered to be modified by the TrueCharts Project. -*/}} - - {{/* Ports included by the controller. */}} {{- define "common.controller.ports" -}} {{- $ports := list -}} - {{/* append the ports for each appAdditionalService - TrueCharts */}} + {{/* append the ports for each service */}} {{- if $.Values.services -}} {{- range $name, $_ := $.Values.services }} - {{- if or ( .enabled ) ( eq $name "main" ) -}} - {{- if eq $name "main" -}} - {{- $_ := set .port "name" (default "http" .port.name) -}} - {{- else if kindIs "string" $name -}} + {{- if .enabled -}} + {{- if kindIs "string" $name -}} {{- $_ := set .port "name" (default .port.name | default $name) -}} {{- else -}} {{- $_ := set .port "name" (required "Missing port.name" .port.name) -}} @@ -42,19 +21,6 @@ Ports included by the controller. {{- end }} {{- end }} - {{- if $.Values.additionalServices -}} - {{- range $_ := $.Values.additionalServices }} - {{- if .enabled -}} - {{- $_ := set .port "name" (required "Missing port.name" .port.name) -}} - {{- $ports = mustAppend $ports .port -}} - {{- range $_ := .additionalPorts -}} - {{/* append the additonalPorts for each additional service */}} - {{- $ports = mustAppend $ports . -}} - {{- end }} - {{- end }} - {{- end }} - {{- end }} - {{/* export/render the list of ports */}} {{- if $ports -}} ports: diff --git a/charts/library/common/templates/lib/controller/_probes.tpl b/charts/library/common/templates/lib/controller/_probes.tpl index 47d3344217e..0083fb65b4b 100644 --- a/charts/library/common/templates/lib/controller/_probes.tpl +++ b/charts/library/common/templates/lib/controller/_probes.tpl @@ -21,7 +21,8 @@ This file is considered to be modified by the TrueCharts Project. Probes selection logic. */}} {{- define "common.controller.probes" -}} -{{- $svcPort := .Values.services.main.port.name -}} +{{- $svc := index .Values.services (keys .Values.services | first) -}} +{{- $svcPort := $svc.port.name -}} {{- range $probeName, $probe := .Values.probes }} {{- if $probe.enabled -}} {{- "" | nindent 0 }} diff --git a/charts/library/common/templates/lib/controller/_volumeMounts.tpl b/charts/library/common/templates/lib/controller/_volumeMounts.tpl index e69903e0286..98dd4af3f42 100644 --- a/charts/library/common/templates/lib/controller/_volumeMounts.tpl +++ b/charts/library/common/templates/lib/controller/_volumeMounts.tpl @@ -1,11 +1,11 @@ - {{/* Volumes included by the controller. */}} {{- define "common.controller.volumeMounts" -}} + {{- range $index, $PVC := .Values.persistence }} -{{- if and ( $PVC.enabled ) ( $PVC.mountPath ) }} -- mountPath: {{ $PVC.mountPath }} +{{- if $PVC.enabled }} +- mountPath: {{ $PVC.mountPath | default (printf "/%v" $index) }} name: {{ $index }} {{- if $PVC.subPath }} subPath: {{ $PVC.subPath }} @@ -13,7 +13,9 @@ Volumes included by the controller. {{- end }} {{- end }} - +{{/* +Creates mountpoints to mount devices directly to the same path inside the container +*/}} {{ range $name, $dmm := .Values.deviceMounts }} {{- if $dmm.enabled -}} {{ if $dmm.name }} @@ -27,28 +29,29 @@ Volumes included by the controller. {{- end -}} {{ end }} -{{ range $name, $csm := .Values.customStorage }} -{{- if $csm.enabled -}} -{{ if $csm.name }} - {{ $name = $csm.name }} +{{/* +Creates mountpoints to mount hostPaths directly to the container +*/}} +{{ range $name, $hpm := .Values.hostPathMounts }} +{{- if $hpm.enabled -}} +{{ if $hpm.name }} + {{ $name = $hpm.name }} {{ end }} -- name: customstorage-{{ $name }} - mountPath: {{ $csm.mountPath }} - {{ if $csm.subPath }} - subPath: {{ $csm.subPath }} +- name: hostpathmounts-{{ $name }} + mountPath: {{ $hpm.mountPath }} + {{ if $hpm.subPath }} + subPath: {{ $hpm.subPath }} {{ end }} - {{ if $csm.readOnly }} - readOnly: {{ $csm.readOnly }} + {{ if $hpm.readOnly }} + readOnly: {{ $hpm.readOnly }} {{ end }} {{- end -}} {{ end }} - {{- if .Values.additionalVolumeMounts }} - {{- toYaml .Values.additionalVolumeMounts | nindent 0 }} +{{- toYaml .Values.additionalVolumeMounts | nindent 0 }} {{- end }} - {{- if eq .Values.controllerType "statefulset" }} {{- range $index, $vct := .Values.volumeClaimTemplates }} - mountPath: {{ $vct.mountPath }} diff --git a/charts/library/common/templates/lib/controller/_volumes.tpl b/charts/library/common/templates/lib/controller/_volumes.tpl index 49403cfa243..ccb602d00d7 100644 --- a/charts/library/common/templates/lib/controller/_volumes.tpl +++ b/charts/library/common/templates/lib/controller/_volumes.tpl @@ -29,23 +29,46 @@ Volumes included by the controller. persistentVolumeClaim: claimName: {{ $persistence.existingClaim }} {{- else -}} - {{- if $persistence.emptyDir -}} {{- /* Always prefer an emptyDir next if that is set */}} + {{- $emptyDir := false -}} + {{- if $persistence.emptyDir -}} + {{- if $persistence.emptyDir.enabled -}} + {{- $emptyDir = true -}} + {{- end -}} + {{- end -}} + {{- if $emptyDir }} + {{- if or $persistence.emptyDir.medium $persistence.emptyDir.sizeLimit }} + emptyDir: + {{- with $persistence.emptyDir.medium }} + medium: "{{ . }}" + {{- end }} + {{- with $persistence.emptyDir.sizeLimit }} + sizeLimit: "{{ . }}" + {{- end }} + {{- else }} emptyDir: {} + {{- end }} {{- else -}} {{- /* Otherwise refer to the PVC name */}} - persistentVolumeClaim: - {{- if $persistence.nameOverride }} - claimName: {{ $persistence.nameOverride }} - {{- else if $persistence.nameSuffix }} - claimName: {{ printf "%s-%s" (include "common.names.fullname" $) $persistence.nameSuffix }} - {{- else }} - claimName: {{ printf "%s-%s" (include "common.names.fullname" $) $index }} - {{- end }} + {{- $pvcName := (include "common.names.fullname" $) -}} + {{- if $persistence.nameOverride -}} + {{- $pvcName = $persistence.nameOverride -}} + {{- else if $persistence.nameSuffix -}} + {{- if not (eq $persistence.nameSuffix "-") -}} + {{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $persistence.nameSuffix) -}} + {{- end -}} + {{- else -}} + {{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $index) -}} {{- end }} + persistentVolumeClaim: + claimName: {{ $pvcName }} {{- end }} {{- end }} {{- end }} +{{- end }} +{{- if .Values.additionalVolumes }} + {{- toYaml .Values.additionalVolumes | nindent 0 }} +{{- end }} {{- range $name, $dm := .Values.deviceMounts -}} {{ if $dm.enabled }} @@ -62,23 +85,22 @@ Volumes included by the controller. {{ end }} {{- end -}} -{{- range $name, $cs := .Values.customStorage -}} -{{ if $cs.enabled }} -{{ if $cs.name }} -{{ $name = $cs.name }} +{{/* +Creates Volumes for hostPaths which can be directly mounted to a container +*/}} +{{- range $name, $hpm := .Values.hostPathMounts -}} +{{ if $hpm.enabled }} +{{ if $hpm.name }} +{{ $name = $hpm.name }} {{ end }} -- name: customstorage-{{ $name }} - {{ if $cs.emptyDir }} +- name: hostpathmounts-{{ $name }} + {{ if $hpm.emptyDir }} emptyDir: {} {{- else -}} hostPath: - path: {{ required "hostPath not set" $cs.hostPath }} + path: {{ required "hostPath not set" $hpm.hostPath }} {{ end }} {{ end }} {{- end -}} - -{{- if .Values.additionalVolumes }} - {{- toYaml .Values.additionalVolumes | nindent 0 }} -{{- end }} {{- end -}} diff --git a/charts/library/common/templates/lib/resources/_certHelpers.tpl b/charts/library/common/templates/lib/resources/_certHelpers.tpl deleted file mode 100644 index d2b07a9b7d1..00000000000 --- a/charts/library/common/templates/lib/resources/_certHelpers.tpl +++ /dev/null @@ -1,32 +0,0 @@ -{{/* -Retrieve true/false if certificate is configured -*/}} -{{- define "common.resources.cert.available" -}} -{{- if .ObjectValues.certHolder.certificate -}} -{{- $values := (. | mustDeepCopy) -}} -{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.certificate) -}} -{{- template "common.resources.cert_present" $values -}} -{{- else -}} -{{- false -}} -{{- end -}} -{{- end -}} - - -{{/* -Retrieve public key of certificate -*/}} -{{- define "common.resources.cert.publicKey" -}} -{{- $values := (. | mustDeepCopy) -}} -{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.certificate "publicKey" true) -}} -{{ include "common.resources.cert" $values }} -{{- end -}} - - -{{/* -Retrieve private key of certificate -*/}} -{{- define "common.resources.cert.privateKey" -}} -{{- $values := (. | mustDeepCopy) -}} -{{- $_ := set $values "commonCertOptions" (dict "certKeyName" $values.ObjectValues.certHolder.certificate) -}} -{{ include "common.resources.cert" $values }} -{{- end -}} diff --git a/charts/library/common/templates/lib/resources/_certSecret.yaml b/charts/library/common/templates/lib/resources/_certSecret.yaml deleted file mode 100644 index 2409ae70517..00000000000 --- a/charts/library/common/templates/lib/resources/_certSecret.yaml +++ /dev/null @@ -1,25 +0,0 @@ -{{- define "common.resources.cert.secret" -}} - - -{{- $secretName := include "common.names.fullname" . -}} - -{{- if .ObjectValues.certHolder -}} - {{- if hasKey .ObjectValues.certHolder "nameSuffix" -}} - {{- $secretName = printf "%v-%v" $secretName .ObjectValues.certHolder.nameSuffix -}} - {{ end -}} -{{ else }} - {{- $_ := set $ "ObjectValues" (dict "certHolder" .Values) -}} -{{ end -}} - -{{- if eq (include "common.resources.cert.available" $ ) "true" -}} -apiVersion: v1 -kind: Secret -metadata: - name: {{ $secretName }} - labels: {{ include "common.labels" . | nindent 4 }} -type: kubernetes.io/tls -data: - tls.crt: {{ (include "common.resources.cert.publicKey" $ ) | toString | b64enc | quote }} - tls.key: {{ (include "common.resources.cert.privateKey" $ ) | toString | b64enc | quote }} -{{- end -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/resources/_certs.tpl b/charts/library/common/templates/lib/resources/_certs.tpl deleted file mode 100644 index 91c525abd51..00000000000 --- a/charts/library/common/templates/lib/resources/_certs.tpl +++ /dev/null @@ -1,24 +0,0 @@ -{{/* -Retrieve true/false if certificate is available in ixCertificates -*/}} -{{- define "common.resources.cert_present" -}} -{{- $values := . -}} -{{- hasKey $values.Values.ixCertificates ($values.commonCertOptions.certKeyName | toString) -}} -{{- end -}} - - -{{/* -Retrieve certificate from variable name -*/}} -{{- define "common.resources.cert" -}} -{{- $values := . -}} -{{- $certKey := ($values.commonCertOptions.certKeyName | toString) -}} -{{- if hasKey $values.Values.ixCertificates $certKey -}} -{{- $cert := get $values.Values.ixCertificates $certKey -}} -{{- if $values.commonCertOptions.publicKey -}} -{{ $cert.certificate }} -{{- else -}} -{{ $cert.privatekey }} -{{- end -}} -{{- end -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/resources/_portal_config.tpl b/charts/library/common/templates/lib/resources/_portal_config.tpl deleted file mode 100644 index d92961a0f87..00000000000 --- a/charts/library/common/templates/lib/resources/_portal_config.tpl +++ /dev/null @@ -1,64 +0,0 @@ -{{- define "common.resources.portal" -}} - -{{- if .Values.portal }} -{{- if .Values.portal.enabled }} -{{- $host := "$node_ip" }} -{{- $port := 443 }} -{{- $protocol := "https" }} -{{- $portProtocol := "" }} - -{{- if hasKey .Values "ingress" }} - {{- if hasKey .Values.ingress "main" -}} - {{- if .Values.ingress.main.host }} - {{- $host = .Values.ingress.main.host }} - {{- else }} - {{- range .Values.ingress.main.hosts }} - {{- $host = ( .host | quote ) }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} - -{{- if and ( .Values.portal.ingressPort ) ( ne $host "$node_ip" ) }} - {{- $port = .Values.portal.ingressPort }} -{{- else if and ( eq $host "$node_ip" ) ( hasKey .Values "services" ) }} - {{- if hasKey .Values.services "main" }} - {{- if and (hasKey .Values.services.main.port "nodePort" ) ( eq .Values.services.main.type "NodePort" ) }} - {{- $port = .Values.services.main.port.nodePort }} - {{- if or ( eq .Values.services.main.port.protocol "HTTP" ) ( eq .Values.services.main.port.protocol "HTTPS" ) }} - {{- $portProtocol = .Values.services.main.port.protocol }} - {{- end }} - {{- end }} - {{- end }} -{{- end }} - -{{- if and ( $portProtocol ) ( eq $host "$node_ip" ) }} - {{- $protocol = $portProtocol }} -{{- else if and ( ne $host "$node_ip" ) }} - {{- if .Values.ingress.main.certType }} - {{- if eq .Values.ingress.main.certType "" }} - {{- $protocol = "http" }} - {{- end }} - {{- end }} -{{- end }} - -{{- if and ( .Values.portal.host ) ( eq $host "$node_ip" ) }} - {{- $host = .Values.portal.host }} -{{- end }} - ---- - -apiVersion: v1 -kind: ConfigMap -metadata: - name: portal - labels: {{ include "common.labels" . | nindent 4 }} -data: - protocol: {{ $protocol }} - host: {{ $host }} - port: {{ $port | quote }} - url: {{ printf "%v%v%v%v%v" $protocol "://" $host ":" $port }} - -{{- end }} -{{- end }} -{{- end -}} diff --git a/charts/library/common/templates/lib/storage/_mountPermissions.tpl b/charts/library/common/templates/lib/storage/_mountPermissions.tpl deleted file mode 100644 index 323d2a33771..00000000000 --- a/charts/library/common/templates/lib/storage/_mountPermissions.tpl +++ /dev/null @@ -1,77 +0,0 @@ -{{/* -This template serves as the blueprint for the mountPermissions job that is run -before chart installation. -*/}} -{{- define "common.storage.permissions" -}} -{{- if .Values.fixMountPermissions }} - - -{{- $jobName := include "common.names.fullname" . -}} -{{- $values := .Values -}} - - -{{- print "---" | nindent 0 -}} - -apiVersion: batch/v1 -kind: Job -metadata: - name: {{ $jobName }}-autopermissions - labels: - {{- include "common.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-10" - "helm.sh/hook-delete-policy": hook-succeeded,hook-failed,before-hook-creation -spec: - template: - metadata: - spec: - restartPolicy: Never - containers: - - name: set-mount-permissions - image: "alpine:3.3" - command: - - /bin/sh - - -c - - | {{ range $index, $cs := .Values.customStorage}}{{ if and $cs.enabled $cs.setPermissions}} - chown -R {{ if eq $values.podSecurityContext.runAsNonRoot false }}{{ print $values.PUID }}{{ else }}{{ print $values.podSecurityContext.runAsUser }}{{ end }}:{{ print $values.podSecurityContext.fsGroup }} {{ print $cs.mountPath }}{{ end }}{{ end }} - #args: - # - #securityContext: - # - volumeMounts: - {{ range $name, $csm := .Values.customStorage }} - {{- if $csm.enabled -}} - {{- if $csm.setPermissions -}} - {{ if $csm.name }} - {{ $name = $csm.name }} - {{ end }} - - name: customstorage-{{ $name }} - mountPath: {{ $csm.mountPath }} - {{ if $csm.subPath }} - subPath: {{ $csm.subPath }} - {{ end }} - {{- end -}} - {{- end -}} - {{ end }} - volumes: - {{- range $name, $cs := .Values.customStorage -}} - {{ if $cs.enabled }} - {{ if $cs.setPermissions }} - {{ if $cs.name }} - {{ $name = $cs.name }} - {{ end }} - - name: customstorage-{{ $name }} - {{ if $cs.emptyDir }} - emptyDir: {} - {{- else -}} - hostPath: - path: {{ required "hostPath not set" $cs.hostPath }} - {{ end }} - {{ end }} - {{ end }} - {{- end -}} - - -{{- end }} -{{- end }} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 9b15e1274ed..0b2c1332d8e 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -82,12 +82,12 @@ hostNetwork: false enableServiceLinks: true # Configure the Security Context for the Pod -podSecurityContext: - runAsNonRoot: true - runAsUser: 568 - runAsGroup: 568 - fsGroup: 568 - fsGroupChangePolicy: "OnRootMismatch" +# podSecurityContext: +# runAsNonRoot: true +# runAsUser: 568 +# runAsGroup: 568 +# fsGroup: 568 +# fsGroupChangePolicy: "OnRootMismatch" # Configure the Security Context for the main container securityContext: {} @@ -141,11 +141,14 @@ services: enabled: true type: ClusterIP ## Specify the default port information + ## It is adviced not to mix different port protocols on the same service port: port: ## name defaults to http name: - protocol: TCP + ## Accepts: HTTP, HTTPS, TCP and UDP + ## HTTPS and HTTPS spawn a TCP service and get used for internal URL and name generation + protocol: HTTP ## Specify a service targetPort if you wish to differ the service port from the application port. ## If targetPort is specified, this port number is used in the container definition instead of ## service.port.port. Therefore named ports are not supported for this field. @@ -163,60 +166,21 @@ services: annotations: {} labels: {} -additionalServices: [] -# - enabled: false -# nameSuffix: api -# type: ClusterIP -# # Specify the default port information -# port: -# port: -# # name defaults to http -# name: -# protocol: TCP -# # targetPort defaults to http -# targetPort: -# # nodePort: -# additionalPorts: [] -# annotations: {} -# labels: {} - -# ingress: -# main: -# enabled: false -# # Used when including ingress using {{ include "common.ingress" . }} -# type: "HTTP" -# entrypoint: "websecure" -# certType: "" -# ## Optional: defaults to IngressName -# serviceName: "" -# ## Optional: Almost never needed -# serviceKind: "" -# ## Optional: defaults to either service port -# servicePort: 80 -# annotations: {} -# # kubernetes.io/ingress.class: nginx -# # kubernetes.io/tls-acme: "true" -# labels: {} -# hosts: -# - host: chart-example.local -# path: / -# additionalIngresses: [] -# - enabled: false -# nameSuffix: "api" -# annotations: {} -# # kubernetes.io/ingress.class: nginx -# # kubernetes.io/tls-acme: "true" -# labels: {} -# hosts: -# - host: chart-example.local -# paths: -# - path: /api -# # Ignored if not kubeVersion >= 1.14-0 -# pathType: Prefix -# tls: [] -# # - secretName: chart-example-tls -# # hosts: -# # - chart-example.local + ## additionalServices can be created as either a dict. + # additionalService: + # type: ClusterIP + # # Specify the default port information + # port: + # port: + # # name defaults to http + # name: + # protocol: TCP + # # targetPort defaults to http + # targetPort: + # # nodePort: + # additionalPorts: [] + # annotations: {} + # labels: {} persistence: config: @@ -243,7 +207,8 @@ persistence: # Create an emptyDir volume to share between all containers shared: enabled: false - emptyDir: true + emptyDir: + enabled: true mountPath: /shared additionalVolumes: [] @@ -289,12 +254,10 @@ resources: {} # cpu: 100m # memory: 128Mi -## TrueCharts Specific +## Used by TrueNAS SCALE to easily set add GPU's to Apps +# scaleGPU: {} -PUID: 568 -PGID: 568 -UMASK: "002" -fixMountPermissions: true +## TrueCharts Specific # deviceMounts: # config: @@ -312,3 +275,60 @@ fixMountPermissions: true # hostPath: "" # readOnly: false # setPermissions: true + +ingress: + main: + enabled: false + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + # ingressClassName: "nginx" + hosts: + - host: chart-example.local + ## Or a tpl that is evaluated + # hostTpl: '{{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.{{ .Values.ingress.domainname }}' + paths: + - path: / + ## Or a tpl that is evaluated + # pathTpl: '{{ include "common.names.fullname" . }}' + ## Ignored if not kubeVersion >= 1.14-0 + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + ## Or if you need a dynamic secretname + # - secretNameTpl: '{{ include "common.names.fullname" . }}-ingress' + # hosts: + # - chart-example.local + ## Or a tpl that is evaluated + # hostsTpl: + # - '{{ include "common.names.fullname" . }}.{{ .Release.Namespace }}.{{ .Values.ingress.domainname }}' + # additionalIngress: + # annotations: {} + # # kubernetes.io/ingress.class: nginx + # # kubernetes.io/tls-acme: "true" + # labels: {} + # hosts: + # - host: chart-example.local + # paths: + # - path: /api + # # Ignored if not kubeVersion >= 1.14-0 + # pathType: Prefix + # serviceName: # optionally target a specific service + # servicePort: # optionally target a specific service port + # tls: [] + # # - secretName: chart-example-tls + # # hosts: + # # - chart-example.local + +# ## Adds a portal configmap for use with TrueNAS SCALE +# ## This should not be enabled on other systems than TrueNAS SCALE, +# ## Because it requires a seperate namespace for each chart. +# portal: +# enabled: false +# ## Override default port used for the portal button when using ingress. +# # ingressPort: 80 +# ## Override hostname used for the portal button when using nodePort +# # host: 192.168.0.2 +# ## Override the path used in the url +# # path: /example diff --git a/tests/library/common/cert_spec.rb b/tests/library/common/cert_spec.rb new file mode 100644 index 00000000000..c129c8285ea --- /dev/null +++ b/tests/library/common/cert_spec.rb @@ -0,0 +1,322 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + describe @@chart.name do + describe 'scaleCertificate' do + it 'disabled by default' do + values = { + ingress: { + main: { + enabled: true + } + } + } + chart.value values + assert_nil(resource('Secret')) + end + it 'can be enabled and selected' do + values = { + "ixCertificateAuthorities": {}, + "ixCertificates": { + "1": { + "CA_type_existing": false, + "CA_type_intermediate": false, + "CA_type_internal": false, + "CSR": "", + "DN": "/C=US/O=iXsystems/CN=localhost/emailAddress=info@ixsystems.com/ST=Tennessee/L=Maryville/subjectAltName=DNS:localhost", + "cert_type": "CERTIFICATE", + "cert_type_CSR": false, + "cert_type_existing": true, + "cert_type_internal": false, + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n", + "certificate_path": "/etc/certificates/freenas_default.crt", + "chain": false, + "chain_list": [ + "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n" + ], + "city": "Maryville", + "common": "localhost", + "country": "US", + "csr_path": "/etc/certificates/freenas_default.csr", + "digest_algorithm": "SHA256", + "email": "info@ixsystems.com", + "extensions": { + "ExtendedKeyUsage": "TLS Web Server Authentication", + "SubjectAltName": "DNS:localhost" + }, + "fingerprint": "9C:5A:1D:1B:E7:9E:0B:89:2B:37:F4:19:83:ED:3C:6B:D8:14:0D:9B", + "from": "Fri Sep 25 16:05:38 2020", + "id": 1, + "internal": "NO", + "issuer": "external", + "key_length": 2048, + "key_type": "RSA", + "lifetime": 825, + "name": "freenas_default", + "organization": "iXsystems", + "organizational_unit": "", + "parsed": true, + "privatekey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6aBpYooul/A3q\nBXS3Ee447HySJ95wvH9aUy0N0VER1DhMoT092ek5IWh3h6I/A+pIl0TociSat5MO\nTnqhmYrH6RkIZMY6cZH4fXwIZb4bi8Alh2jL0odU2k/offnh33Md7p+QiGh/G9Sm\nEQTB/o5ihaa+45DzZAVy0jAO4yiCGvKQ/UepReIALG6iWnwm090e26pHfcad5949\nmIakMxE1NpZruH62twT4qKHyuO5EpILlAuprZOlaw39vkLQipWNHbWxd3tmQTVqN\nWo/OrIwraBJqjgjLD0S3P18EHHxKh2OF32n18KpNBtFMVdnHtfMSqEf6TdzKSwWe\nuTcz56Z9AgMBAAECggEARwcb4uIs7BZbBu0FSCyg5TfXT6m5bKOmszg2VqmHho+i\n1DAsMcEyyP4d3E3mWLSZNQfOzfOQVxPUCQOGXsUuyHXdgAFGN0bHJDRMara59a0O\njj5GhEO4JXD6OdCmwpZuOt2OF3iiuKxWHuElOvZQMuJSYzI7LULTgKjufv23lbsf\nxMO/v9yi57c5EGgnQ8siLKOy/FQZapn4Z9qKn+lVyk5gfaKP0pDsvV4d7nGYMDD2\nYijfkSyNecApFdtWiLE5zLUlvF6oNj8o66z3YrVNKrCPzhA/5Rkkwwk32SNxvKU3\nVZFSNPeOZ60BicxYcWO+b2aAa0WF+uazJAZ4q52gUQKBgQDu88R+0wm76secYkzE\nQglteLNZKFcvth0kI5xH42Hmk9IXkGimFoDJCIrLAuopyGnfNmqmh2is3QUMUPdR\n/wDLnKc4MCezEidNoD2RBC+bzM1hB9oye/b5sOZUDFXSa0k4XSLu1UEuy1yWhkuS\n6JjY1KQfc4FN0K0Fjqqo7UCTCwKBgQDHtKQh/NvMJ2ok4YW+/QAsus4mEK9eCyUy\nOuyDszQYrGvjkS7STKJVNxGLhWb0XKSIAxMZ66b1MwOt+71h7xNn6pcancfVdK7F\n1Xl5J+76SwbXSgQwTZuoMDxPIvZn7v/2ep5Ni/BcOhMcPIcobWb/OmXrFN1brBvo\nlFNQyWWhlwKBgFDAyPMjVvLO0U6kWdUpjA4W8GV9IJnbLdX8wt/4lClcY2/bOcKH\ncFaAMIeTIJemR0FMHpbQxCtHNmGHK03mo9orwsdWXtRBmk69jJDpnT1F5VKZWMAe\n7MRNaEmXMZm+8CvALgIQx8qMp2mnUPsA6Ea+9gg6/MPTdeWe5UXZiC0pAoGAGtSt\nPJfBXBNrklruYjORo3DRo5GYThVHQRFjl2orNKltsVxfIwgCw1ortEgPBgOwY0mu\ndkwP2V+qPeTVk+PQAqUk+gF6yLXtiUzeDiYMWHpeB+y81VSH9jfM0oELA/m7T/03\naYnEmE+BI8kKC6dvMBlDeisKdneQJFZRP0hfrC8CgYEAgYIyCGwcydKpe2Nkj0Fz\nKTtCMC/k4DvJfd5Kb9AbmrPUfKgA9Xj4GT6yPG6uBMi8r5etvLCKJ2x2NtN024a8\nQJLATYPrSsaZkE+9zM0j5nYAgbKpxBhlDzDAzn//3ByVzfgJ25S80XhTI2lfbLH/\nU07ssxdZaQCo+WuD82OvNcg=\n-----END PRIVATE KEY-----\n", + "privatekey_path": "/etc/certificates/freenas_default.key", + "revoked": false, + "revoked_date": "", + "root_path": "/etc/certificates", + "san": [ + "DNS:localhost" + ], + "serial": 1, + "signedby": "", + "state": "Tennessee", + "subject_name_hash": 3193428416, + "type": 8, + "until": "Thu Dec 29 15:05:38 2022" + } + }, + ingress: { + main: { + enabled: true, + tls: [ + { + scaleCert: 1 + } + ] + } + } + } + chart.value values + refute_nil(resource('Secret')) + secret = chart.resources(kind: "Secret").first + assert_equal("common-test-main-tls-0-ixcert-1", secret["metadata"]["name"]) + refute_nil(secret["data"]["tls.crt"]) + refute_nil(secret["data"]["tls.key"]) + end + + it 'secret can be used for TLS ingress' do + values = { + "ixCertificateAuthorities": {}, + "ixCertificates": { + "1": { + "CA_type_existing": false, + "CA_type_intermediate": false, + "CA_type_internal": false, + "CSR": "", + "DN": "/C=US/O=iXsystems/CN=localhost/emailAddress=info@ixsystems.com/ST=Tennessee/L=Maryville/subjectAltName=DNS:localhost", + "cert_type": "CERTIFICATE", + "cert_type_CSR": false, + "cert_type_existing": true, + "cert_type_internal": false, + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n", + "certificate_path": "/etc/certificates/freenas_default.crt", + "chain": false, + "chain_list": [ + "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n" + ], + "city": "Maryville", + "common": "localhost", + "country": "US", + "csr_path": "/etc/certificates/freenas_default.csr", + "digest_algorithm": "SHA256", + "email": "info@ixsystems.com", + "extensions": { + "ExtendedKeyUsage": "TLS Web Server Authentication", + "SubjectAltName": "DNS:localhost" + }, + "fingerprint": "9C:5A:1D:1B:E7:9E:0B:89:2B:37:F4:19:83:ED:3C:6B:D8:14:0D:9B", + "from": "Fri Sep 25 16:05:38 2020", + "id": 1, + "internal": "NO", + "issuer": "external", + "key_length": 2048, + "key_type": "RSA", + "lifetime": 825, + "name": "freenas_default", + "organization": "iXsystems", + "organizational_unit": "", + "parsed": true, + "privatekey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6aBpYooul/A3q\nBXS3Ee447HySJ95wvH9aUy0N0VER1DhMoT092ek5IWh3h6I/A+pIl0TociSat5MO\nTnqhmYrH6RkIZMY6cZH4fXwIZb4bi8Alh2jL0odU2k/offnh33Md7p+QiGh/G9Sm\nEQTB/o5ihaa+45DzZAVy0jAO4yiCGvKQ/UepReIALG6iWnwm090e26pHfcad5949\nmIakMxE1NpZruH62twT4qKHyuO5EpILlAuprZOlaw39vkLQipWNHbWxd3tmQTVqN\nWo/OrIwraBJqjgjLD0S3P18EHHxKh2OF32n18KpNBtFMVdnHtfMSqEf6TdzKSwWe\nuTcz56Z9AgMBAAECggEARwcb4uIs7BZbBu0FSCyg5TfXT6m5bKOmszg2VqmHho+i\n1DAsMcEyyP4d3E3mWLSZNQfOzfOQVxPUCQOGXsUuyHXdgAFGN0bHJDRMara59a0O\njj5GhEO4JXD6OdCmwpZuOt2OF3iiuKxWHuElOvZQMuJSYzI7LULTgKjufv23lbsf\nxMO/v9yi57c5EGgnQ8siLKOy/FQZapn4Z9qKn+lVyk5gfaKP0pDsvV4d7nGYMDD2\nYijfkSyNecApFdtWiLE5zLUlvF6oNj8o66z3YrVNKrCPzhA/5Rkkwwk32SNxvKU3\nVZFSNPeOZ60BicxYcWO+b2aAa0WF+uazJAZ4q52gUQKBgQDu88R+0wm76secYkzE\nQglteLNZKFcvth0kI5xH42Hmk9IXkGimFoDJCIrLAuopyGnfNmqmh2is3QUMUPdR\n/wDLnKc4MCezEidNoD2RBC+bzM1hB9oye/b5sOZUDFXSa0k4XSLu1UEuy1yWhkuS\n6JjY1KQfc4FN0K0Fjqqo7UCTCwKBgQDHtKQh/NvMJ2ok4YW+/QAsus4mEK9eCyUy\nOuyDszQYrGvjkS7STKJVNxGLhWb0XKSIAxMZ66b1MwOt+71h7xNn6pcancfVdK7F\n1Xl5J+76SwbXSgQwTZuoMDxPIvZn7v/2ep5Ni/BcOhMcPIcobWb/OmXrFN1brBvo\nlFNQyWWhlwKBgFDAyPMjVvLO0U6kWdUpjA4W8GV9IJnbLdX8wt/4lClcY2/bOcKH\ncFaAMIeTIJemR0FMHpbQxCtHNmGHK03mo9orwsdWXtRBmk69jJDpnT1F5VKZWMAe\n7MRNaEmXMZm+8CvALgIQx8qMp2mnUPsA6Ea+9gg6/MPTdeWe5UXZiC0pAoGAGtSt\nPJfBXBNrklruYjORo3DRo5GYThVHQRFjl2orNKltsVxfIwgCw1ortEgPBgOwY0mu\ndkwP2V+qPeTVk+PQAqUk+gF6yLXtiUzeDiYMWHpeB+y81VSH9jfM0oELA/m7T/03\naYnEmE+BI8kKC6dvMBlDeisKdneQJFZRP0hfrC8CgYEAgYIyCGwcydKpe2Nkj0Fz\nKTtCMC/k4DvJfd5Kb9AbmrPUfKgA9Xj4GT6yPG6uBMi8r5etvLCKJ2x2NtN024a8\nQJLATYPrSsaZkE+9zM0j5nYAgbKpxBhlDzDAzn//3ByVzfgJ25S80XhTI2lfbLH/\nU07ssxdZaQCo+WuD82OvNcg=\n-----END PRIVATE KEY-----\n", + "privatekey_path": "/etc/certificates/freenas_default.key", + "revoked": false, + "revoked_date": "", + "root_path": "/etc/certificates", + "san": [ + "DNS:localhost" + ], + "serial": 1, + "signedby": "", + "state": "Tennessee", + "subject_name_hash": 3193428416, + "type": 8, + "until": "Thu Dec 29 15:05:38 2022" + } + }, + ingress: { + main: { + enabled: true, + tls: [ + { + hosts: [ 'hostname' ], + scaleCert: 1 + } + ] + } + } + } + chart.value values + refute_nil(resource('Secret')) + secret = chart.resources(kind: "Secret").first + assert_equal("common-test-main-tls-0-ixcert-1", secret["metadata"]["name"]) + refute_nil(secret["data"]["tls.crt"]) + refute_nil(secret["data"]["tls.key"]) + + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal("common-test-main-tls-0-ixcert-1", ingress["spec"]["tls"][0]["secretName"]) + end + it 'multiple tls sections generate multiple secrets' do + values = { + "ixCertificateAuthorities": {}, + "ixCertificates": { + "2": { + "CA_type_existing": false, + "CA_type_intermediate": false, + "CA_type_internal": false, + "CSR": "", + "DN": "/C=US/O=iXsystems/CN=localhost/emailAddress=info@ixsystems.com/ST=Tennessee/L=Maryville/subjectAltName=DNS:localhost", + "cert_type": "CERTIFICATE", + "cert_type_CSR": false, + "cert_type_existing": true, + "cert_type_internal": false, + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n", + "certificate_path": "/etc/certificates/freenas_default.crt", + "chain": false, + "chain_list": [ + "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n" + ], + "city": "Maryville", + "common": "localhost", + "country": "US", + "csr_path": "/etc/certificates/freenas_default.csr", + "digest_algorithm": "SHA256", + "email": "info@ixsystems.com", + "extensions": { + "ExtendedKeyUsage": "TLS Web Server Authentication", + "SubjectAltName": "DNS:localhost" + }, + "fingerprint": "9C:5A:1D:1B:E7:9E:0B:89:2B:37:F4:19:83:ED:3C:6B:D8:14:0D:9B", + "from": "Fri Sep 25 16:05:38 2020", + "id": 2, + "internal": "NO", + "issuer": "external", + "key_length": 2048, + "key_type": "RSA", + "lifetime": 825, + "name": "freenas_default", + "organization": "iXsystems", + "organizational_unit": "", + "parsed": true, + "privatekey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6aBpYooul/A3q\nBXS3Ee447HySJ95wvH9aUy0N0VER1DhMoT092ek5IWh3h6I/A+pIl0TociSat5MO\nTnqhmYrH6RkIZMY6cZH4fXwIZb4bi8Alh2jL0odU2k/offnh33Md7p+QiGh/G9Sm\nEQTB/o5ihaa+45DzZAVy0jAO4yiCGvKQ/UepReIALG6iWnwm090e26pHfcad5949\nmIakMxE1NpZruH62twT4qKHyuO5EpILlAuprZOlaw39vkLQipWNHbWxd3tmQTVqN\nWo/OrIwraBJqjgjLD0S3P18EHHxKh2OF32n18KpNBtFMVdnHtfMSqEf6TdzKSwWe\nuTcz56Z9AgMBAAECggEARwcb4uIs7BZbBu0FSCyg5TfXT6m5bKOmszg2VqmHho+i\n1DAsMcEyyP4d3E3mWLSZNQfOzfOQVxPUCQOGXsUuyHXdgAFGN0bHJDRMara59a0O\njj5GhEO4JXD6OdCmwpZuOt2OF3iiuKxWHuElOvZQMuJSYzI7LULTgKjufv23lbsf\nxMO/v9yi57c5EGgnQ8siLKOy/FQZapn4Z9qKn+lVyk5gfaKP0pDsvV4d7nGYMDD2\nYijfkSyNecApFdtWiLE5zLUlvF6oNj8o66z3YrVNKrCPzhA/5Rkkwwk32SNxvKU3\nVZFSNPeOZ60BicxYcWO+b2aAa0WF+uazJAZ4q52gUQKBgQDu88R+0wm76secYkzE\nQglteLNZKFcvth0kI5xH42Hmk9IXkGimFoDJCIrLAuopyGnfNmqmh2is3QUMUPdR\n/wDLnKc4MCezEidNoD2RBC+bzM1hB9oye/b5sOZUDFXSa0k4XSLu1UEuy1yWhkuS\n6JjY1KQfc4FN0K0Fjqqo7UCTCwKBgQDHtKQh/NvMJ2ok4YW+/QAsus4mEK9eCyUy\nOuyDszQYrGvjkS7STKJVNxGLhWb0XKSIAxMZ66b1MwOt+71h7xNn6pcancfVdK7F\n1Xl5J+76SwbXSgQwTZuoMDxPIvZn7v/2ep5Ni/BcOhMcPIcobWb/OmXrFN1brBvo\nlFNQyWWhlwKBgFDAyPMjVvLO0U6kWdUpjA4W8GV9IJnbLdX8wt/4lClcY2/bOcKH\ncFaAMIeTIJemR0FMHpbQxCtHNmGHK03mo9orwsdWXtRBmk69jJDpnT1F5VKZWMAe\n7MRNaEmXMZm+8CvALgIQx8qMp2mnUPsA6Ea+9gg6/MPTdeWe5UXZiC0pAoGAGtSt\nPJfBXBNrklruYjORo3DRo5GYThVHQRFjl2orNKltsVxfIwgCw1ortEgPBgOwY0mu\ndkwP2V+qPeTVk+PQAqUk+gF6yLXtiUzeDiYMWHpeB+y81VSH9jfM0oELA/m7T/03\naYnEmE+BI8kKC6dvMBlDeisKdneQJFZRP0hfrC8CgYEAgYIyCGwcydKpe2Nkj0Fz\nKTtCMC/k4DvJfd5Kb9AbmrPUfKgA9Xj4GT6yPG6uBMi8r5etvLCKJ2x2NtN024a8\nQJLATYPrSsaZkE+9zM0j5nYAgbKpxBhlDzDAzn//3ByVzfgJ25S80XhTI2lfbLH/\nU07ssxdZaQCo+WuD82OvNcg=\n-----END PRIVATE KEY-----\n", + "privatekey_path": "/etc/certificates/freenas_default.key", + "revoked": false, + "revoked_date": "", + "root_path": "/etc/certificates", + "san": [ + "DNS:localhost" + ], + "serial": 1, + "signedby": "", + "state": "Tennessee", + "subject_name_hash": 3193428416, + "type": 8, + "until": "Thu Dec 29 15:05:38 2022" + }, + "1": { + "CA_type_existing": false, + "CA_type_intermediate": false, + "CA_type_internal": false, + "CSR": "", + "DN": "/C=US/O=iXsystems/CN=localhost/emailAddress=info@ixsystems.com/ST=Tennessee/L=Maryville/subjectAltName=DNS:localhost", + "cert_type": "CERTIFICATE", + "cert_type_CSR": false, + "cert_type_existing": true, + "cert_type_internal": false, + "certificate": "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n", + "certificate_path": "/etc/certificates/freenas_default.crt", + "chain": false, + "chain_list": [ + "-----BEGIN CERTIFICATE-----\nMIIDqjCCApKgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgDELMAkGA1UEBhMCVVMx\nEjAQBgNVBAoMCWlYc3lzdGVtczESMBAGA1UEAwwJbG9jYWxob3N0MSEwHwYJKoZI\nhvcNAQkBFhJpbmZvQGl4c3lzdGVtcy5jb20xEjAQBgNVBAgMCVRlbm5lc3NlZTES\nMBAGA1UEBwwJTWFyeXZpbGxlMB4XDTIwMDkyNTE0MDUzOFoXDTIyMTIyOTE0MDUz\nOFowgYAxCzAJBgNVBAYTAlVTMRIwEAYDVQQKDAlpWHN5c3RlbXMxEjAQBgNVBAMM\nCWxvY2FsaG9zdDEhMB8GCSqGSIb3DQEJARYSaW5mb0BpeHN5c3RlbXMuY29tMRIw\nEAYDVQQIDAlUZW5uZXNzZWUxEjAQBgNVBAcMCU1hcnl2aWxsZTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBALpoGliii6X8DeoFdLcR7jjsfJIn3nC8f1pT\nLQ3RURHUOEyhPT3Z6TkhaHeHoj8D6kiXROhyJJq3kw5OeqGZisfpGQhkxjpxkfh9\nfAhlvhuLwCWHaMvSh1TaT+h9+eHfcx3un5CIaH8b1KYRBMH+jmKFpr7jkPNkBXLS\nMA7jKIIa8pD9R6lF4gAsbqJafCbT3R7bqkd9xp3n3j2YhqQzETU2lmu4fra3BPio\nofK47kSkguUC6mtk6VrDf2+QtCKlY0dtbF3e2ZBNWo1aj86sjCtoEmqOCMsPRLc/\nXwQcfEqHY4XfafXwqk0G0UxV2ce18xKoR/pN3MpLBZ65NzPnpn0CAwEAAaMtMCsw\nFAYDVR0RBA0wC4IJbG9jYWxob3N0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMA0GCSqG\nSIb3DQEBCwUAA4IBAQBFW1R037y7wllg/gRk9p2T1stiG8iIXosblmL4Ak1YToTQ\n/0to5GY2ZYW29+rbA4SDTS5eeu2YqZ0A/fF3wey7ggzMS7KyNBOvx5QBJRw3PJGn\n+THfhXvdfkOyeUC6KWRGLgl+/zBFvgh6vFDq3jmv0NI4ehVBTBMCJn7r6577S16T\nwtgKMCooizII0Odu5HIF10gTieFIH3PQYm9JBji9iyemb9Ht3wn7fXQptfGadz/l\nWz/Dv9+a6IOr7JVJMHnqAIvPzpkav4efuVPOX1zbhjg4K5g+nRYfjr5F5upOd0Y3\nznWTUBUyI7CXRkpHtSDXfEqKgnk/8uv7GWw+hyKr\n-----END CERTIFICATE-----\n" + ], + "city": "Maryville", + "common": "localhost", + "country": "US", + "csr_path": "/etc/certificates/freenas_default.csr", + "digest_algorithm": "SHA256", + "email": "info@ixsystems.com", + "extensions": { + "ExtendedKeyUsage": "TLS Web Server Authentication", + "SubjectAltName": "DNS:localhost" + }, + "fingerprint": "9C:5A:1D:1B:E7:9E:0B:89:2B:37:F4:19:83:ED:3C:6B:D8:14:0D:9B", + "from": "Fri Sep 25 16:05:38 2020", + "id": 1, + "internal": "NO", + "issuer": "external", + "key_length": 2048, + "key_type": "RSA", + "lifetime": 825, + "name": "freenas_default", + "organization": "iXsystems", + "organizational_unit": "", + "parsed": true, + "privatekey": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC6aBpYooul/A3q\nBXS3Ee447HySJ95wvH9aUy0N0VER1DhMoT092ek5IWh3h6I/A+pIl0TociSat5MO\nTnqhmYrH6RkIZMY6cZH4fXwIZb4bi8Alh2jL0odU2k/offnh33Md7p+QiGh/G9Sm\nEQTB/o5ihaa+45DzZAVy0jAO4yiCGvKQ/UepReIALG6iWnwm090e26pHfcad5949\nmIakMxE1NpZruH62twT4qKHyuO5EpILlAuprZOlaw39vkLQipWNHbWxd3tmQTVqN\nWo/OrIwraBJqjgjLD0S3P18EHHxKh2OF32n18KpNBtFMVdnHtfMSqEf6TdzKSwWe\nuTcz56Z9AgMBAAECggEARwcb4uIs7BZbBu0FSCyg5TfXT6m5bKOmszg2VqmHho+i\n1DAsMcEyyP4d3E3mWLSZNQfOzfOQVxPUCQOGXsUuyHXdgAFGN0bHJDRMara59a0O\njj5GhEO4JXD6OdCmwpZuOt2OF3iiuKxWHuElOvZQMuJSYzI7LULTgKjufv23lbsf\nxMO/v9yi57c5EGgnQ8siLKOy/FQZapn4Z9qKn+lVyk5gfaKP0pDsvV4d7nGYMDD2\nYijfkSyNecApFdtWiLE5zLUlvF6oNj8o66z3YrVNKrCPzhA/5Rkkwwk32SNxvKU3\nVZFSNPeOZ60BicxYcWO+b2aAa0WF+uazJAZ4q52gUQKBgQDu88R+0wm76secYkzE\nQglteLNZKFcvth0kI5xH42Hmk9IXkGimFoDJCIrLAuopyGnfNmqmh2is3QUMUPdR\n/wDLnKc4MCezEidNoD2RBC+bzM1hB9oye/b5sOZUDFXSa0k4XSLu1UEuy1yWhkuS\n6JjY1KQfc4FN0K0Fjqqo7UCTCwKBgQDHtKQh/NvMJ2ok4YW+/QAsus4mEK9eCyUy\nOuyDszQYrGvjkS7STKJVNxGLhWb0XKSIAxMZ66b1MwOt+71h7xNn6pcancfVdK7F\n1Xl5J+76SwbXSgQwTZuoMDxPIvZn7v/2ep5Ni/BcOhMcPIcobWb/OmXrFN1brBvo\nlFNQyWWhlwKBgFDAyPMjVvLO0U6kWdUpjA4W8GV9IJnbLdX8wt/4lClcY2/bOcKH\ncFaAMIeTIJemR0FMHpbQxCtHNmGHK03mo9orwsdWXtRBmk69jJDpnT1F5VKZWMAe\n7MRNaEmXMZm+8CvALgIQx8qMp2mnUPsA6Ea+9gg6/MPTdeWe5UXZiC0pAoGAGtSt\nPJfBXBNrklruYjORo3DRo5GYThVHQRFjl2orNKltsVxfIwgCw1ortEgPBgOwY0mu\ndkwP2V+qPeTVk+PQAqUk+gF6yLXtiUzeDiYMWHpeB+y81VSH9jfM0oELA/m7T/03\naYnEmE+BI8kKC6dvMBlDeisKdneQJFZRP0hfrC8CgYEAgYIyCGwcydKpe2Nkj0Fz\nKTtCMC/k4DvJfd5Kb9AbmrPUfKgA9Xj4GT6yPG6uBMi8r5etvLCKJ2x2NtN024a8\nQJLATYPrSsaZkE+9zM0j5nYAgbKpxBhlDzDAzn//3ByVzfgJ25S80XhTI2lfbLH/\nU07ssxdZaQCo+WuD82OvNcg=\n-----END PRIVATE KEY-----\n", + "privatekey_path": "/etc/certificates/freenas_default.key", + "revoked": false, + "revoked_date": "", + "root_path": "/etc/certificates", + "san": [ + "DNS:localhost" + ], + "serial": 1, + "signedby": "", + "state": "Tennessee", + "subject_name_hash": 3193428416, + "type": 8, + "until": "Thu Dec 29 15:05:38 2022" + } + }, + ingress: { + main: { + enabled: true, + tls: [ + { + hosts: [ 'hostname1' ], + scaleCert: 1 + }, + { + hosts: [ 'hostname2' ], + scaleCert: 2 + } + ] + } + } + } + chart.value values + refute_nil(resource('Secret')) + secret1 = chart.resources(kind: "Secret").first + assert_equal("common-test-main-tls-0-ixcert-1", secret1["metadata"]["name"]) + refute_nil(secret1["data"]["tls.crt"]) + refute_nil(secret1["data"]["tls.key"]) + secret2 = chart.resources(kind: "Secret").find{ |s| s["metadata"]["name"] == "common-test-main-tls-1-ixcert-2" } + refute_nil(secret2) + refute_nil(secret2["data"]["tls.crt"]) + refute_nil(secret2["data"]["tls.key"]) + + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal("common-test-main-tls-0-ixcert-1", ingress["spec"]["tls"][0]["secretName"]) + assert_equal("common-test-main-tls-1-ixcert-2", ingress["spec"]["tls"][1]["secretName"]) + end + end + end +end diff --git a/tests/library/common/container_resources_spec.rb b/tests/library/common/container_resources_spec.rb new file mode 100644 index 00000000000..f91d4116b9d --- /dev/null +++ b/tests/library/common/container_resources_spec.rb @@ -0,0 +1,90 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'container::resources' do + it 'no resources added by default' do + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{}}, mainContainer["resources"]) + end + it 'resources can be added' do + values = { + resources: { + testresourcename: "testresourcevalue" + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{}, "testresourcename"=>"testresourcevalue"}, mainContainer["resources"]) + end + it 'resources.limits can be added' do + values = { + resources: { + limits: { + testlimitkey: "testlimitvalue" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{"testlimitkey"=>"testlimitvalue"}}, mainContainer["resources"]) + end + it 'resources and resources.limits can both be added' do + values = { + resources: { + testresourcekey: "testresourcevalue", + limits: { + testlimitkey: "testlimitvalue" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{"testlimitkey"=>"testlimitvalue"}, "testresourcekey"=>"testresourcevalue"}, mainContainer["resources"]) + end + end + describe 'container::resources-scaleGPU' do + it 'scaleGPU can be set' do + values = { + scaleGPU: { + intelblabla: 1 + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{"intelblabla"=>1}}, mainContainer["resources"]) + end + it 'scaleGPU can be combined with resources and resource values' do + values = { + resources: { + testresourcekey: "testresourcevalue", + limits: { + testlimitkey: "testlimitvalue" + } + }, + scaleGPU: { + intelblabla: 1 + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal({"limits"=>{"intelblabla"=>1, "testlimitkey"=>"testlimitvalue"}, "testresourcekey"=>"testresourcevalue"}, mainContainer["resources"]) + end + end + end +end diff --git a/tests/library/common/container_spec.rb b/tests/library/common/container_spec.rb new file mode 100644 index 00000000000..bb1decec3a1 --- /dev/null +++ b/tests/library/common/container_spec.rb @@ -0,0 +1,380 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'container::command' do + it 'defaults to nil' do + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_nil(mainContainer["command"]) + end + + it 'accepts a single string' do + values = { + command: "/bin/sh" + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:command], mainContainer["command"]) + end + + it 'accepts a list of strings' do + values = { + command: [ + "/bin/sh", + "-c" + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:command], mainContainer["command"]) + end + end + + describe 'container::arguments' do + it 'defaults to nil' do + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_nil(mainContainer["args"]) + end + + it 'accepts a single string' do + values = { + args: "sleep infinity" + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:args], mainContainer["args"]) + end + + it 'accepts a list of strings' do + values = { + args: [ + "sleep", + "infinity" + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:args], mainContainer["args"]) + end + end + + describe 'container::environment settings' do + it 'Check no environment variables' do + values = {} + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_nil(mainContainer["env"]) + end + + it 'set "static" environment variables' do + values = { + env: { + STATIC_ENV: 'value_of_env', + TRUTHY_ENV: '0', + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:env].keys[0].to_s, mainContainer["env"][0]["name"]) + assert_equal(values[:env].values[0].to_s, mainContainer["env"][0]["value"]) + assert_equal(values[:env].keys[1].to_s, mainContainer["env"][1]["name"]) + assert_equal(values[:env].values[1].to_s, mainContainer["env"][1]["value"]) + end + + it 'set "list" of "static" environment variables' do + values = { + envList: [ + { + name: 'STATIC_ENV_FROM_LIST', + value: 'STATIC_ENV_VALUE_FROM_LIST' + } + + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:envList][0][:name].to_s, mainContainer["env"][0]["name"]) + assert_equal(values[:envList][0][:value].to_s, mainContainer["env"][0]["value"]) + end + + it 'set both "list" AND "dict" of "static" environment variables' do + values = { + env: { + STATIC_ENV: 'value_of_env' + }, + envList: [ + { + name: 'STATIC_ENV_FROM_LIST', + value: 'STATIC_ENV_VALUE_FROM_LIST' + } + + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:envList][0][:name].to_s, mainContainer["env"][0]["name"]) + assert_equal(values[:envList][0][:value].to_s, mainContainer["env"][0]["value"]) + assert_equal(values[:env].keys[0].to_s, mainContainer["env"][1]["name"]) + assert_equal(values[:env].values[0].to_s, mainContainer["env"][1]["value"]) + end + + it 'set "valueFrom" environment variables' do + values = { + envValueFrom: { + NODE_NAME: { + fieldRef: { + fieldPath: "spec.nodeName" + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:envValueFrom].keys[0].to_s, mainContainer["env"][0]["name"]) + assert_equal(values[:envValueFrom].values[0][:fieldRef][:fieldPath], mainContainer["env"][0]["valueFrom"]["fieldRef"]["fieldPath"]) + end + + it 'set "static" and "Dynamic/Tpl" environment variables' do + values = { + env: { + STATIC_ENV: 'value_of_env' + }, + envTpl: { + DYN_ENV: "{{ .Release.Name }}-admin" + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:env].keys[0].to_s, mainContainer["env"][0]["name"]) + assert_equal(values[:env].values[0].to_s, mainContainer["env"][0]["value"]) + assert_equal(values[:envTpl].keys[0].to_s, mainContainer["env"][1]["name"]) + assert_equal("common-test-admin", mainContainer["env"][1]["value"]) + end + + it 'set "Dynamic/Tpl" environment variables' do + values = { + envTpl: { + DYN_ENV: "{{ .Release.Name }}-admin" + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:envTpl].keys[0].to_s, mainContainer["env"][0]["name"]) + assert_equal("common-test-admin", mainContainer["env"][0]["value"]) + end + + it 'set "static" secret variables' do + expectedSecretName = 'common-test' + values = { + secret: { + STATIC_SECRET: 'value_of_secret' + } + } + chart.value values + secret = chart.resources(kind: "Secret").find{ |s| s["metadata"]["name"] == expectedSecretName } + refute_nil(secret) + assert_equal(values[:secret].values[0].to_s, secret["stringData"]["STATIC_SECRET"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(expectedSecretName, mainContainer["envFrom"][0]["secretRef"]["name"]) + end + end + + describe 'container::persistence' do + it 'supports multiple volumeMounts' do + values = { + persistence: { + cache: { + enabled: true, + emptyDir: { + enabled: true + } + }, + config: { + enabled: true, + existingClaim: "configClaim" + }, + data: { + enabled: true, + existingClaim: "dataClaim" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + # Check that all persistent volumes have mounts + values[:persistence].each { |key, value| + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == key.to_s } + refute_nil(volumeMount) + } + end + + it 'defaults mountPath to persistence key' do + values = { + persistence: { + data: { + enabled: true, + existingClaim: "dataClaim" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "data" } + refute_nil(volumeMount) + assert_equal("/data", volumeMount["mountPath"]) + end + + it 'supports setting custom mountPath' do + values = { + persistence: { + data: { + enabled: true, + existingClaim: "dataClaim", + mountPath: "/myMountPath" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "data" } + refute_nil(volumeMount) + assert_equal("/myMountPath", volumeMount["mountPath"]) + end + + it 'supports setting subPath' do + values = { + persistence: { + data: { + enabled: true, + existingClaim: "dataClaim", + subPath: "mySubPath" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "data" } + refute_nil(volumeMount) + assert_equal("mySubPath", volumeMount["subPath"]) + end + end + + describe 'container::hostPathMounts' do + it 'supports multiple hostPathMounts' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + mountPath: "/data", + hostPath: "/tmp" + }, + { + name: "config", + enabled: true, + mountPath: "/config", + hostPath: "/tmp" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + # Check that all hostPathMounts volumes have mounts + values[:hostPathMounts].each { |value| + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "hostpathmounts-" + value[:name].to_s } + refute_nil(volumeMount) + } + end + + it 'supports setting mountPath' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + mountPath: "/data", + hostPath: "/tmp" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "hostpathmounts-data" } + refute_nil(volumeMount) + assert_equal("/data", volumeMount["mountPath"]) + end + + it 'supports setting subPath' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + mountPath: "/data", + hostPath: "/tmp", + subPath: "mySubPath" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "hostpathmounts-data" } + refute_nil(volumeMount) + assert_equal("mySubPath", volumeMount["subPath"]) + end + end + end +end diff --git a/tests/library/common/controller_spec.rb b/tests/library/common/controller_spec.rb new file mode 100644 index 00000000000..37fe729d75a --- /dev/null +++ b/tests/library/common/controller_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'controller::type' do + it 'defaults to "Deployment"' do + assert_nil(resource('StatefulSet')) + assert_nil(resource('DaemonSet')) + refute_nil(resource('Deployment')) + end + + it 'accepts "statefulset"' do + chart.value controllerType: 'statefulset' + assert_nil(resource('Deployment')) + assert_nil(resource('DaemonSet')) + refute_nil(resource('StatefulSet')) + end + + it 'accepts "daemonset"' do + chart.value controllerType: 'daemonset' + assert_nil(resource('Deployment')) + assert_nil(resource('StatefulSet')) + refute_nil(resource('DaemonSet')) + end + end + + describe 'controller::statefulset::volumeClaimTemplates' do + it 'volumeClaimTemplates should be empty by default' do + chart.value controllerType: 'statefulset' + statefulset = chart.resources(kind: "StatefulSet").first + assert_nil(statefulset['spec']['volumeClaimTemplates']) + end + + it 'can set values for volumeClaimTemplates' do + values = { + controllerType: 'statefulset', + volumeClaimTemplates: [ + { + name: 'storage', + accessMode: 'ReadWriteOnce', + size: '10Gi', + storageClass: 'storage' + } + ] + } + + chart.value values + statefulset = chart.resources(kind: "StatefulSet").first + volumeClaimTemplate = statefulset["spec"]["volumeClaimTemplates"].find{ |v| v["metadata"]["name"] == values[:volumeClaimTemplates][0][:name]} + refute_nil(volumeClaimTemplate) + assert_equal(values[:volumeClaimTemplates][0][:accessMode], volumeClaimTemplate["spec"]["accessModes"][0]) + assert_equal(values[:volumeClaimTemplates][0][:size], volumeClaimTemplate["spec"]["resources"]["requests"]["storage"]) + assert_equal(values[:volumeClaimTemplates][0][:storageClass], volumeClaimTemplate["spec"]["storageClassName"]) + end + end + end +end diff --git a/tests/library/common/hpa_spec.rb b/tests/library/common/hpa_spec.rb new file mode 100644 index 00000000000..7a859dc31d9 --- /dev/null +++ b/tests/library/common/hpa_spec.rb @@ -0,0 +1,120 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + + describe 'hpa::defaults' do + it 'does not exist by default' do + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_nil(hpa) + end + + it 'can be enabled' do + values = { + autoscaling: { + enabled: true + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + refute_nil(hpa) + end + + it 'default target is common.names.fullname ' do + values = { + autoscaling: { + enabled: true + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal("common-test",hpa["spec"]["scaleTargetRef"]["name"]) + end + + it 'default numer of replicas is min 1 max 3' do + values = { + autoscaling: { + enabled: true + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal(1,hpa["spec"]["minReplicas"]) + assert_equal(3,hpa["spec"]["maxReplicas"]) + end + end + + describe 'hpa::customsettings' do + it 'can override target' do + values = { + autoscaling: { + enabled: true, + target: "targetname" + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal(values[:autoscaling][:target],hpa["spec"]["scaleTargetRef"]["name"]) + end + + it 'can change min and max replicas' do + values = { + autoscaling: { + enabled: true, + minReplicas: 4, + maxReplicas: 8 + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal(values[:autoscaling][:minReplicas],hpa["spec"]["minReplicas"]) + assert_equal(values[:autoscaling][:maxReplicas],hpa["spec"]["maxReplicas"]) + end + + it 'can set targetCPUUtilizationPercentage' do + values = { + autoscaling: { + enabled: true, + targetCPUUtilizationPercentage: 60 + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal("cpu",hpa["spec"]["metrics"][0]["resource"]["name"]) + assert_equal(values[:autoscaling][:targetCPUUtilizationPercentage],hpa["spec"]["metrics"][0]["resource"]["targetAverageUtilization"]) + end + + it 'can set targetMemoryUtilizationPercentage' do + values = { + autoscaling: { + enabled: true, + targetMemoryUtilizationPercentage: 70 + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal("memory",hpa["spec"]["metrics"][0]["resource"]["name"]) + assert_equal(values[:autoscaling][:targetMemoryUtilizationPercentage],hpa["spec"]["metrics"][0]["resource"]["targetAverageUtilization"]) + end + + it 'can set both targetCPU and targetMemoryUtilizationPercentage' do + values = { + autoscaling: { + enabled: true, + targetCPUUtilizationPercentage: 60, + targetMemoryUtilizationPercentage: 70 + } + } + chart.value values + hpa = chart.resources(kind: "HorizontalPodAutoscaler").first + assert_equal("cpu",hpa["spec"]["metrics"][0]["resource"]["name"]) + assert_equal(values[:autoscaling][:targetCPUUtilizationPercentage],hpa["spec"]["metrics"][0]["resource"]["targetAverageUtilization"]) + assert_equal("memory",hpa["spec"]["metrics"][1]["resource"]["name"]) + assert_equal(values[:autoscaling][:targetMemoryUtilizationPercentage],hpa["spec"]["metrics"][1]["resource"]["targetAverageUtilization"]) + end + end + end +end diff --git a/tests/library/common/ingress_spec.rb b/tests/library/common/ingress_spec.rb new file mode 100644 index 00000000000..339c837091f --- /dev/null +++ b/tests/library/common/ingress_spec.rb @@ -0,0 +1,281 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'ingress' do + it 'disabled when ingress.main.enabled: false' do + values = { + ingress: { + main: { + enabled: false + } + } + } + chart.value values + assert_nil(resource('Ingress')) + end + + it 'enabled when ingress.main.enabled: true' do + values = { + ingress: { + main: { + enabled: true + } + } + } + + chart.value values + refute_nil(resource('Ingress')) + end + + it 'tls can be provided' do + expectedPath = 'common-test.path' + values = { + ingress: { + main: { + enabled: true, + tls: [ + { + hosts: [ 'hostname' ], + secretName: 'secret-name' + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal(values[:ingress][:main][:tls][0][:hosts][0], ingress["spec"]["tls"][0]["hosts"][0]) + assert_equal(values[:ingress][:main][:tls][0][:secretName], ingress["spec"]["tls"][0]["secretName"]) + end + + it 'tls secret can be left empty' do + expectedPath = 'common-test.path' + values = { + ingress: { + main: { + enabled: true, + tls: [ + { + hosts: [ 'hostname' ] + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal(values[:ingress][:main][:tls][0][:hosts][0], ingress["spec"]["tls"][0]["hosts"][0]) + assert_equal(false, ingress["spec"]["tls"][0].key?("secretName")) + assert_nil(ingress["spec"]["tls"][0]["secretName"]) + end + + it 'tls secret template can be provided' do + expectedPath = 'common-test.path' + values = { + ingress: { + main: { + enabled: true, + tls: [ + { + secretNameTpl: '{{ .Release.Name }}-secret' + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal('common-test-secret', ingress["spec"]["tls"][0]["secretName"]) + end + + it 'path template can be provided' do + expectedPath = 'common-test.path' + values = { + ingress: { + main: { + enabled: true, + hosts: [ + { + paths: [ + { + pathTpl: '{{ .Release.Name }}.path' + } + ] + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal(expectedPath, ingress["spec"]["rules"][0]["http"]["paths"][0]["path"]) + end + + it 'hosts can be provided' do + values = { + ingress: { + main: { + enabled: true, + hosts: [ + { + host: 'hostname' + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal(values[:ingress][:main][:hosts][0][:host], ingress["spec"]["rules"][0]["host"]) + end + + it 'hosts template can be provided' do + expectedHostName = 'common-test.hostname' + values = { + ingress: { + main: { + enabled: true, + hosts: [ + { + hostTpl: '{{ .Release.Name }}.hostname' + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + refute_nil(ingress) + assert_equal(expectedHostName, ingress["spec"]["rules"][0]["host"]) + end + + it 'custom service name / port can optionally be set on path level' do + values = { + ingress: { + main: { + enabled: true, + hosts: [ + { + paths: [ + { + path: '/' + }, + { + path: '/second', + serviceName: 'pathService', + servicePort: 1234 + } + ] + } + ] + } + } + } + + chart.value values + ingress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-main" } + firstPath = ingress["spec"]["rules"][0]["http"]["paths"][0] + secondPath = ingress["spec"]["rules"][0]["http"]["paths"][1] + assert_equal("common-test", firstPath["backend"]["service"]["name"]) + assert_equal(8080, firstPath["backend"]["service"]["port"]["number"]) + assert_equal("pathService", secondPath["backend"]["service"]["name"]) + assert_equal(1234, secondPath["backend"]["service"]["port"]["number"]) + end + end + + describe 'additionalIngress' do + ingressValues = { + ingress: { + extra: { + enabled: true, + hosts: [ + { + paths: [ + { + path: '/' + } + ] + } + ] + } + } + } + + it 'can be specified' do + values = ingressValues + chart.value values + additionalIngress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-extra" } + refute_nil(additionalIngress) + end + + it 'refers to main Service by default' do + values = ingressValues + chart.value values + additionalIngress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-extra" } + assert_equal("common-test", additionalIngress["spec"]["rules"][0]["http"]["paths"][0]["backend"]["service"]["name"]) + assert_equal(8080, additionalIngress["spec"]["rules"][0]["http"]["paths"][0]["backend"]["service"]["port"]["number"]) + end + + it 'custom service name / port can be set on Ingress level' do + values = ingressValues.deep_merge_override({ + ingress: { + extra: { + serviceName: "customService", + servicePort: 8081 + } + } + }) + chart.value values + additionalIngress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-extra" } + assert_equal("customService", additionalIngress["spec"]["rules"][0]["http"]["paths"][0]["backend"]["service"]["name"]) + assert_equal(8081, additionalIngress["spec"]["rules"][0]["http"]["paths"][0]["backend"]["service"]["port"]["number"]) + end + + it 'custom service name / port can optionally be set on path level' do + values = ingressValues.deep_merge_override({ + ingress: { + extra: { + hosts: [ + { + paths: [ + { + path: '/' + }, + { + path: '/second', + serviceName: 'pathService', + servicePort: 1234 + } + ] + } + ] + } + } + }) + chart.value values + additionalIngress = chart.resources(kind: "Ingress").find{ |s| s["metadata"]["name"] == "common-test-extra" } + firstPath = additionalIngress["spec"]["rules"][0]["http"]["paths"][0] + secondPath = additionalIngress["spec"]["rules"][0]["http"]["paths"][1] + assert_equal("common-test", firstPath["backend"]["service"]["name"]) + assert_equal(8080, firstPath["backend"]["service"]["port"]["number"]) + assert_equal("pathService", secondPath["backend"]["service"]["name"]) + assert_equal(1234, secondPath["backend"]["service"]["port"]["number"]) + end + end + end +end diff --git a/tests/library/common/job_permissions_spec.rb b/tests/library/common/job_permissions_spec.rb new file mode 100644 index 00000000000..8de52e46e27 --- /dev/null +++ b/tests/library/common/job_permissions_spec.rb @@ -0,0 +1,347 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'job::permissions' do + it 'no job exists by default' do + job = chart.resources(kind: "Job").first + assert_nil(job) + end + + it 'hostPathMounts do not affect permissions job by default' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + mountPath: "/data", + hostPath: "/tmp" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + assert_nil(job["spec"]["template"]["spec"]["volumes"]) + assert_nil(job["spec"]["template"]["spec"]["containers"][0]["volumeMounts"]) + end + it 'hostPathMounts.setPermissions adds volume(mounts)' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + assert_equal("hostpathmounts-data", job["spec"]["template"]["spec"]["volumes"][0]["name"]) + assert_equal("hostpathmounts-data", job["spec"]["template"]["spec"]["containers"][0]["volumeMounts"][0]["name"]) + end + it 'supports multiple hostPathMounts' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + + # Check that all hostPathMounts volumes have mounts + values[:hostPathMounts].each { |value| + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "hostpathmounts-" + value[:name].to_s } + refute_nil(volumeMount) + } + end + + it 'supports setting mountPath' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + + volumeMount = mainContainer["volumeMounts"].find{ |v| v["name"] == "hostpathmounts-data" } + refute_nil(volumeMount) + assert_equal("/data", volumeMount["mountPath"]) + end + + it 'could mount multiple volumes' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + volumes = job["spec"]["template"]["spec"]["volumes"] + + volume = volumes.find{ |v| v["name"] == "hostpathmounts-data"} + refute_nil(volume) + assert_equal('/tmp1', volume["hostPath"]["path"]) + + volume = volumes.find{ |v| v["name"] == "hostpathmounts-config"} + refute_nil(volume) + assert_equal('/tmp2', volume["hostPath"]["path"]) + end + + it 'emptyDir can be enabled' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + emptyDir: true, + mountPath: "/data" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + volumes = job["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "hostpathmounts-data"} + refute_nil(volume) + assert_equal(Hash.new, volume["emptyDir"]) + end + + it 'can process default (568:568) permissions for multiple volumes' do + results= { + command: ["/bin/sh", "-c", "chown -R 568:568 /data +chown -R 568:568 /config +"] + } + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + + it 'outputs default permissions with irrelevant podSecurityContext' do + results= { + command: ["/bin/sh", "-c", "chown -R 568:568 /data +chown -R 568:568 /config +"] + } + values = { + podSecurityContext: { + allowPrivilegeEscalation: false + }, + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + + it 'outputs fsgroup permissions for multiple volumes when set' do + results= { + command: ["/bin/sh", "-c", "chown -R 568:666 /data +chown -R 568:666 /config +"] + } + values = { + podSecurityContext: { + fsGroup: 666 + }, + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + + it 'outputs runAsUser permissions for multiple volumes when set' do + results= { + command: ["/bin/sh", "-c", "chown -R 999:568 /data +chown -R 999:568 /config +"] + } + values = { + podSecurityContext: { + runAsUser: 999 + }, + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + + it 'outputs fsGroup AND runAsUser permissions for multiple volumes when both are set' do + results= { + command: ["/bin/sh", "-c", "chown -R 999:666 /data +chown -R 999:666 /config +"] + } + values = { + podSecurityContext: { + fsGroup: 666, + runAsUser: 999 + }, + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + it 'outputs PUID AND PGID permissions for multiple volumes when both are set' do + results= { + command: ["/bin/sh", "-c", "chown -R 999:666 /data +chown -R 999:666 /config +"] + } + values = { + env: { + PGID: 666, + PUID: 999 + }, + hostPathMounts: [ + { + name: "data", + enabled: true, + setPermissions: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + setPermissions: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + job = chart.resources(kind: "Job").first + mainContainer = job["spec"]["template"]["spec"]["containers"][0] + assert_equal(results[:command], mainContainer["command"]) + end + end + end +end diff --git a/tests/library/common/pod_spec.rb b/tests/library/common/pod_spec.rb new file mode 100644 index 00000000000..65657c979f4 --- /dev/null +++ b/tests/library/common/pod_spec.rb @@ -0,0 +1,316 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'pod::replicas' do + it 'defaults to 1' do + deployment = chart.resources(kind: "Deployment").first + assert_equal(1, deployment["spec"]["replicas"]) + end + + it 'accepts integer as value' do + chart.value replicas: 3 + deployment = chart.resources(kind: "Deployment").first + assert_equal(3, deployment["spec"]["replicas"]) + end + end + + describe 'pod::hostNetwork' do + it 'defaults to nil' do + deployment = chart.resources(kind: "Deployment").first + assert_nil(deployment["spec"]["template"]["spec"]["hostNetwork"]) + end + + it 'can be enabled' do + values = { + hostNetwork: true + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + assert_equal(true, deployment["spec"]["template"]["spec"]["hostNetwork"]) + end + end + + describe 'pod::dnsPolicy' do + it 'defaults to "ClusterFirst" without hostNetwork' do + deployment = chart.resources(kind: "Deployment").first + assert_equal("ClusterFirst", deployment["spec"]["template"]["spec"]["dnsPolicy"]) + end + + it 'defaults to "ClusterFirst" when hostNetwork: false' do + values = { + hostNetwork: false + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + assert_equal("ClusterFirst", deployment["spec"]["template"]["spec"]["dnsPolicy"]) + end + + it 'defaults to "ClusterFirstWithHostNet" when hostNetwork: true' do + values = { + hostNetwork: true + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + assert_equal("ClusterFirstWithHostNet", deployment["spec"]["template"]["spec"]["dnsPolicy"]) + end + + it 'accepts manual override' do + values = { + dnsPolicy: "None" + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + assert_equal("None", deployment["spec"]["template"]["spec"]["dnsPolicy"]) + end + end + + describe 'pod::additional containers' do + it 'accepts static additionalContainers' do + values = { + additionalContainers: [ + { + name: "template-test" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + additionalContainer = containers.find{ |c| c["name"] == values[:additionalContainers][0][:name] } + refute_nil(additionalContainer) + end + + it 'accepts "Dynamic/Tpl" additionalContainers' do + expectedContainerName = "common-test-container" + values = { + additionalContainers: [ + { + name: "{{ .Release.Name }}-container", + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + additionalContainer = containers.find{ |c| c["name"] == expectedContainerName } + refute_nil(additionalContainer) + end + end + + describe 'pod::persistence' do + it 'multiple volumes' do + values = { + persistence: { + cache: { + enabled: true, + emptyDir: { + enabled: true + } + }, + config: { + enabled: true, + existingClaim: "configClaim", + emptyDir: { + enabled: false + } + }, + data: { + enabled: true, + existingClaim: "dataClaim" + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + + volume = volumes.find{ |v| v["name"] == "cache"} + refute_nil(volume) + + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal('configClaim', volume["persistentVolumeClaim"]["claimName"]) + + volume = volumes.find{ |v| v["name"] == "data"} + refute_nil(volume) + assert_equal('dataClaim', volume["persistentVolumeClaim"]["claimName"]) + end + + it 'default nameSuffix' do + values = { + persistence: { + config: { + enabled: true, + emptyDir: { + enabled: false + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal('common-test-config', volume["persistentVolumeClaim"]["claimName"]) + end + + it 'custom nameSuffix' do + values = { + persistence: { + config: { + enabled: true, + nameSuffix: "test", + emptyDir: { + enabled: false + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal('common-test-test', volume["persistentVolumeClaim"]["claimName"]) + end + + it 'no nameSuffix' do + values = { + persistence: { + config: { + enabled: true, + nameSuffix: "-", + emptyDir: { + enabled: false + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal('common-test', volume["persistentVolumeClaim"]["claimName"]) + end + end + + describe 'pod::persistence::emptyDir' do + it 'can be configured' do + values = { + persistence: { + config: { + enabled: true, + emptyDir: { + enabled: true + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal(Hash.new, volume["emptyDir"]) + end + + it 'medium can be configured' do + values = { + persistence: { + config: { + enabled: true, + emptyDir: { + enabled: true, + medium: "memory" + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal("memory", volume["emptyDir"]["medium"]) + end + + it 'sizeLimit can be configured' do + values = { + persistence: { + config: { + enabled: true, + emptyDir: { + enabled: true, + medium: "memory", + sizeLimit: "1Gi" + } + } + } + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "config"} + refute_nil(volume) + assert_equal("1Gi", volume["emptyDir"]["sizeLimit"]) + end + end + + describe 'pod::hostPathMounts' do + it 'multiple volumes' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + mountPath: "/data", + hostPath: "/tmp1" + }, + { + name: "config", + enabled: true, + mountPath: "/config", + hostPath: "/tmp2" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + + volume = volumes.find{ |v| v["name"] == "hostpathmounts-data"} + refute_nil(volume) + assert_equal('/tmp1', volume["hostPath"]["path"]) + + volume = volumes.find{ |v| v["name"] == "hostpathmounts-config"} + refute_nil(volume) + assert_equal('/tmp2', volume["hostPath"]["path"]) + end + + it 'emptyDir can be enabled' do + values = { + hostPathMounts: [ + { + name: "data", + enabled: true, + emptyDir: true, + mountPath: "/data" + } + ] + } + chart.value values + deployment = chart.resources(kind: "Deployment").first + volumes = deployment["spec"]["template"]["spec"]["volumes"] + volume = volumes.find{ |v| v["name"] == "hostpathmounts-data"} + refute_nil(volume) + assert_equal(Hash.new, volume["emptyDir"]) + end + end + end +end diff --git a/tests/library/common/portal_spec.rb b/tests/library/common/portal_spec.rb new file mode 100644 index 00000000000..8a76e4419fd --- /dev/null +++ b/tests/library/common/portal_spec.rb @@ -0,0 +1,313 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'configmap::portal-defaults' do + it 'no configmap exists by default' do + configmap = chart.resources(kind: "ConfigMap").first + assert_nil(configmap) + end + + it 'creates configmap whe enabled' do + values = { + portal: { + enabled: true + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + refute_nil(configmap) + end + + it 'is named "portal"' do + values = { + portal: { + enabled: true + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("portal", configmap["metadata"]["name"]) + end + + it 'uses "$node_ip" by default' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("$node_ip", configmap["data"]["host"]) + end + + it 'uses port "443" by default' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("443", configmap["data"]["port"]) + end + + it 'uses protocol "https" by default' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("https", configmap["data"]["protocol"]) + end + + it 'uses path "/" by default' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("/", configmap["data"]["path"]) + end + end + + describe 'configmap::portal-overrides' do + it 'ingressPort can be overridden' do + values = { + portal: { + enabled: true, + ingressPort: "666" + }, + ingress: { + main: { + enabled: true + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal(values[:portal][:ingressPort], configmap["data"]["port"]) + end + + it 'nodePort Host can be overridden' do + values = { + portal: { + enabled: true, + host: "test.host" + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal(values[:portal][:host], configmap["data"]["host"]) + end + + it 'path can be overridden' do + values = { + portal: { + enabled: true, + path: "/path" + }, + ingress: { + main: { + enabled: false + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal(values[:portal][:path], configmap["data"]["path"]) + end + end + + describe 'configmap::portal-nodePort' do + it 'nodePort host defaults to "$node_ip"' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + }, + services: { + main: { + type: "NodePort", + port: { + nodePort: 666 + } + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("$node_ip", configmap["data"]["host"]) + end + + it 'nodePort port defaults to the nodePort' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + }, + services: { + main: { + type: "NodePort", + port: { + nodePort: 666 + } + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("666", configmap["data"]["port"]) + end + + it 'uses nodeport port protocol as protocol (HTTPS)' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + }, + services: { + main: { + type: "NodePort", + port: { + nodePort: 666, + protocol: "HTTPS" + } + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal(values[:services][:main][:port][:protocol], configmap["data"]["protocol"]) + end + + it 'uses nodeport port protocol as protocol (HTTP)' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: false + } + }, + services: { + main: { + type: "NodePort", + port: { + nodePort: 666, + protocol: "HTTP" + } + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal(values[:services][:main][:port][:protocol], configmap["data"]["protocol"]) + end + end + + describe 'configmap::portal-Ingress' do + it 'uses ingress host' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: true, + hosts: [ + { + host: "test.domain", + paths: + [ + { + path: "/test" + } + ] + + } + ] + } + } + } + chart.value values + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("test.domain", configmap["data"]["host"]) + end + + it 'uses ingress path' do + values = { + portal: { + enabled: true + }, + ingress: { + main: { + enabled: true, + hosts: [ + { + host: "test.domain", + paths: + [ + { + path: "/test" + } + ] + + } + ] + } + } + } + chart.value values + configmap = chart.resources(kind: "ConfigMap").first + assert_equal("/test", configmap["data"]["path"]) + end + end + end +end diff --git a/tests/library/common/pvc_spec.rb b/tests/library/common/pvc_spec.rb new file mode 100644 index 00000000000..2baede12708 --- /dev/null +++ b/tests/library/common/pvc_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'pvc' do + it 'nameSuffix defaults to persistence key' do + values = { + persistence: { + config: { + enabled: true + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test-config" } + refute_nil(pvc) + end + + it 'nameSuffix can be overridden' do + values = { + persistence: { + config: { + enabled: true, + nameSuffix: 'customSuffix' + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test-customSuffix" } + refute_nil(pvc) + end + + it 'name can be overridden by nameOverride' do + values = { + persistence: { + config: { + enabled: true, + nameOverride: 'customname' + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "customname" } + refute_nil(pvc) + end + + it 'nameSuffix can be skipped' do + values = { + persistence: { + config: { + enabled: true, + nameSuffix: '-' + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(pvc) + end + + it 'storageClass can be set' do + values = { + persistence: { + config: { + enabled: true, + storageClass: "test" + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test-config" } + refute_nil(pvc) + assert_equal('test', pvc["spec"]["storageClassName"]) + end + + it 'can generate TrueNAS SCALE zfs storageClass' do + values = { + persistence: { + config: { + enabled: true, + storageClass: "SCALE-ZFS" + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test-config" } + refute_nil(pvc) + assert_equal('ix-storage-class-common-test', pvc["spec"]["storageClassName"]) + end + + it 'storageClass can be set to an empty value' do + values = { + persistence: { + config: { + enabled: true, + storageClass: "-" + } + } + } + chart.value values + pvc = chart.resources(kind: "PersistentVolumeClaim").find{ |s| s["metadata"]["name"] == "common-test-config" } + refute_nil(pvc) + assert_equal('', pvc["spec"]["storageClassName"]) + end + end + end +end diff --git a/tests/library/common/service_spec.rb b/tests/library/common/service_spec.rb new file mode 100644 index 00000000000..e17952c5417 --- /dev/null +++ b/tests/library/common/service_spec.rb @@ -0,0 +1,223 @@ +# frozen_string_literal: true +require_relative '../../test_helper' + +class Test < ChartTest + @@chart = Chart.new('charts/library/common-test') + + describe @@chart.name do + describe 'service::ports settings' do + default_name = 'main' + default_port = 8080 + + it 'defaults to name "servicename" on port 8080' do + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal(default_port, service["spec"]["ports"].first["port"]) + assert_equal(default_name, service["spec"]["ports"].first["targetPort"]) + assert_equal(default_name, service["spec"]["ports"].first["name"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(default_port, mainContainer["ports"].first["containerPort"]) + assert_equal(default_name, mainContainer["ports"].first["name"]) + end + + it 'port name can be overridden' do + values = { + services: { + main: { + port: { + name: "server", + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal(default_port, service["spec"]["ports"].first["port"]) + assert_equal(values[:services][:main][:port][:name], service["spec"]["ports"].first["targetPort"]) + assert_equal(values[:services][:main][:port][:name], service["spec"]["ports"].first["name"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(default_port, mainContainer["ports"].first["containerPort"]) + assert_equal(values[:services][:main][:port][:name], mainContainer["ports"].first["name"]) + end + + it 'targetPort can be overridden' do + values = { + services: { + main: { + port: { + targetPort: 80, + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal(default_port, service["spec"]["ports"].first["port"]) + assert_equal(values[:services][:main][:port][:targetPort], service["spec"]["ports"].first["targetPort"]) + assert_equal(default_name, service["spec"]["ports"].first["name"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal(values[:services][:main][:port][:targetPort], mainContainer["ports"].first["containerPort"]) + assert_equal(default_name, mainContainer["ports"].first["name"]) + end + + it 'targetPort cannot be a named port' do + values = { + services: { + main: { + port: { + targetPort: "test", + }, + }, + }, + } + chart.value values + exception = assert_raises HelmCompileError do + chart.execute_helm_template! + end + assert_match("Our charts do not support named ports for targetPort. (port name #{default_name}, targetPort #{values[:services][:main][:port][:targetPort]})", exception.message) + end + + it 'protocol defaults to TCP' do + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("TCP", service["spec"]["ports"].first["protocol"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal("TCP", mainContainer["ports"].first["protocol"]) + end + + it 'protocol is TCP when set to TCP explicitly' do + values = { + services: { + main: { + port: { + protocol: "TCP", + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("TCP", service["spec"]["ports"].first["protocol"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal("TCP", mainContainer["ports"].first["protocol"]) + end + + it 'protocol is TCP when set to HTTP explicitly' do + values = { + services: { + main: { + port: { + protocol: "HTTP", + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("TCP", service["spec"]["ports"].first["protocol"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal("TCP", mainContainer["ports"].first["protocol"]) + end + + it 'protocol is TCP when set to HTTPS explicitly' do + values = { + services: { + main: { + port: { + protocol: "HTTPS", + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("TCP", service["spec"]["ports"].first["protocol"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal("TCP", mainContainer["ports"].first["protocol"]) + end + + it 'protocol is UDP when set to UDP explicitly' do + values = { + services: { + main: { + port: { + protocol: "UDP", + }, + }, + }, + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("UDP", service["spec"]["ports"].first["protocol"]) + + deployment = chart.resources(kind: "Deployment").first + containers = deployment["spec"]["template"]["spec"]["containers"] + mainContainer = containers.find{ |c| c["name"] == "common-test" } + assert_equal("UDP", mainContainer["ports"].first["protocol"]) + end + + it 'No annotations get set by default' do + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_nil(service["metadata"]["annotations"]) + end + it 'TCP port protocol does not set annotations' do + values = { + services: { + main: { + port: { + protocol: 'TCP' + } + } + } + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_nil(service["metadata"]["annotations"]) + end + it 'HTTPS port protocol sets traefik HTTPS annotation' do + values = { + services: { + main: { + port: { + protocol: 'HTTPS' + } + } + } + } + chart.value values + service = chart.resources(kind: "Service").find{ |s| s["metadata"]["name"] == "common-test" } + refute_nil(service) + assert_equal("https", service["metadata"]["annotations"]["traefik.ingress.kubernetes.io/service.serversscheme"]) + end + end + end +end diff --git a/.tools/tests/test_helper.rb b/tests/test_helper.rb similarity index 67% rename from .tools/tests/test_helper.rb rename to tests/test_helper.rb index 2deecf2f3bc..6170486bdbb 100644 --- a/.tools/tests/test_helper.rb +++ b/tests/test_helper.rb @@ -4,7 +4,6 @@ require 'json' require 'yaml' require 'open3' -require 'jq/extend' require 'minitest-implicit-subject' require "minitest/reporters" require 'minitest/autorun' @@ -105,10 +104,6 @@ class ChartTest < ExtendedMinitest def resource(name) chart.resources(kind: name).first end - - def jq(matcher, object) - value(object.jq(matcher)[0]) - end end class Minitest::Result @@ -117,3 +112,35 @@ class Minitest::Result test_name.to_s.gsub /\Atest_\d{4,}_/, "" end end + +class ::Hash + def deep_merge_override(second) + merger = proc do |key, original, override| + if original.instance_of?(Hash) && override.instance_of?(Hash) + original.merge(override, &merger) + else + if original.instance_of?(Array) && override.instance_of?(Array) + # if the lengths are different, prefer the override + if original.length != override.length + override + else + # if the first element in the override's Array is a Hash, then we assume they all are + if override[0].instance_of?(Hash) + original.map.with_index do |v, i| + # deep merge everything between the two arrays + original[i].merge(override[i], &merger) + end + else + # if we don't have a Hash in the override, + # override the whole array with our new one + override + end + end + else + override + end + end + end + self.merge(second.to_h, &merger) + end +end