diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index b3d0e9ad52e..d7db0d3f1dc 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,26 +1,36 @@ -# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.154.0/containers/ruby/.devcontainer/base.Dockerfile - -# [Choice] Ruby version: 2, 2.7, 2.6, 2.5 -ARG VARIANT="2" -FROM mcr.microsoft.com/vscode/devcontainers/ruby:0-${VARIANT} +ARG VARIANT="1.16" +FROM mcr.microsoft.com/vscode/devcontainers/go:0-${VARIANT} +ARG HELM_VERSION="3.5.4" +ARG CT_VERSION=3.3.1 ENV DEBIAN_FRONTEND=noninteractive -COPY Gemfile /tmp/Gemfile - RUN \ apt-get update \ && \ apt-get -y install --no-install-recommends \ - jq \ - libjq-dev \ libonig-dev \ gnupg2 \ + python3-pip \ + python3-setuptools \ && \ sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d -b /usr/local/bin \ && \ - curl -fsSL https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | /bin/bash - \ + curl -o /tmp/helm.tar.gz "https://get.helm.sh/helm-v${HELM_VERSION}-linux-$(dpkg --print-architecture).tar.gz" \ + && tar xvzf /tmp/helm.tar.gz -C /usr/local/bin --strip-components 1 "linux-$(dpkg --print-architecture)/helm" \ + && chmod +x /usr/local/bin/helm \ && \ - bundle config set system 'true' \ - && bundle install --gemfile /tmp/Gemfile \ - && rm /tmp/Gemfile + curl -o /tmp/ct.tar.gz -L "https://github.com/helm/chart-testing/releases/download/v${CT_VERSION}/chart-testing_${CT_VERSION}_linux_$(dpkg --print-architecture).tar.gz" \ + && mkdir -p /etc/ct \ + && tar xvzf /tmp/ct.tar.gz -C /usr/local/bin "ct" \ + && tar xvzf /tmp/ct.tar.gz --strip-components=1 -C /etc/ct "etc/" \ + && chmod +x /usr/local/bin/ct \ + && \ + pip3 install \ + pre-commit \ + yamale \ + yamllint \ + && \ + rm \ + /tmp/helm.tar.gz \ + /tmp/ct.tar.gz diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3f6e29e4ff6..70d29ccb93d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,33 +1,32 @@ // For format details, see https://aka.ms/devcontainer.json. For config options, see the README at: // https://github.com/microsoft/vscode-dev-containers/tree/v0.154.0/containers/ruby { - "name": "Ruby", - "build": { - "context": "..", - "dockerfile": "Dockerfile", - "args": { - // Update 'VARIANT' to pick a Ruby version: 2, 2.7, 2.6, 2.5 - "VARIANT": "2.7", - } - }, + "name": "Go", + "build": { + "context": "..", + "dockerfile": "Dockerfile", + "args": { + "VARIANT": "1.16", + } + }, - // Set *default* container specific settings.json values on container create. - "settings": { - "terminal.integrated.shell.linux": "/bin/bash" - }, + // Set *default* container specific settings.json values on container create. + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, - // Add the IDs of extensions you want installed when the container is created. - "extensions": [ - "ms-kubernetes-tools.vscode-kubernetes-tools", - "rebornix.Ruby" - ], + // Add the IDs of extensions you want installed when the container is created. + "extensions": [ + "ms-kubernetes-tools.vscode-kubernetes-tools", + "golang.go" + ], - // Use 'forwardPorts' to make a list of ports inside the container available locally. - // "forwardPorts": [], + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // "forwardPorts": [], - // Use 'postCreateCommand' to run commands after the container is created. - "postCreateCommand": "export RUBYJQ_USE_SYSTEM_LIBRARIES=1 && bundle install", + // Use 'postCreateCommand' to run commands after the container is created. + // "postCreateCommand": "export RUBYJQ_USE_SYSTEM_LIBRARIES=1 && bundle install", - // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. - "remoteUser": "vscode" + // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. + "remoteUser": "vscode" } diff --git a/.github/workflows/apps.yaml b/.github/workflows/apps.yaml index c647203934e..0d160a3ced5 100644 --- a/.github/workflows/apps.yaml +++ b/.github/workflows/apps.yaml @@ -59,6 +59,80 @@ jobs: echo "::set-output name=empty_matrix::false" fi + app-unit-tests: + needs: [changes] + if: ${{ needs.changes.outputs.empty_matrix == 'false' }} + name: App Unit Tests + runs-on: ubuntu-latest + strategy: + matrix: ${{ fromJson(needs.changes.outputs.matrix) }} + fail-fast: false + steps: + - name: Checkout + if: ${{ matrix.app != '.gitkee' }} + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Prepare-Lint + if: ${{ matrix.app != '.gitkee' }} + id: prep-lint + run: | + if test -f "./charts/stable/${{ matrix.app }}/Chart.yaml"; then + train="stable" + elif test -f "./charts/incubator/${{ matrix.app }}/Chart.yaml"; then + train="incubator" + elif test -f "./charts/deprecated/${{ matrix.app }}/Chart.yaml"; then + train="deprecated" + elif test -f "./charts/non-free/${{ matrix.app }}/Chart.yaml"; then + train="non-free" + elif test -f "./charts/library/${{ matrix.app }}/Chart.yaml"; then + train="library" + else + train="develop" + fi + echo ::set-output name=train::${train} + if test -d "./charts/${train}/${{ matrix.app }}/tests/"; then + unittests='true' + echo "::set-output name=unittests::true" + else + unittests="false" + echo "::set-output name=unittests::false" + fi + + - uses: actions/setup-go@v2 + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + with: + go-version: '^1.16' + + # Get values for cache paths to be used in later steps + - id: go-cache-paths + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + run: | + echo "::set-output name=go-build::$(go env GOCACHE)" + echo "::set-output name=go-mod::$(go env GOMODCACHE)" + # Cache go build cache, used to speedup go test + - name: Go Build Cache + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + uses: actions/cache@v2 + with: + path: ${{ steps.go-cache-paths.outputs.go-build }} + key: ${{ runner.os }}-go-build-${{ hashFiles('**/go.sum') }} + + - name: Download modules + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + run: | + go mod download + - name: Run tests + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + run: | + go test ./charts/.../tests -json | tee test.json + - name: Annotate tests + if: ${{ steps.prep-lint.outputs.unittests == 'true' }} + uses: guyarb/golang-test-annotations@v0.3.0 + with: + test-results: test.json + app-tests: needs: [changes] if: ${{ needs.changes.outputs.empty_matrix == 'false' }} @@ -104,16 +178,6 @@ jobs: with: python-version: 3.7 - - name: Install Dev tools for unittests - if: ${{ matrix.app == 'common' && matrix.app != '.gitkee' }} - run: sudo apt-get update && sudo apt-get install -y jq libjq-dev - - - name: Install Ruby for unittests - if: ${{ matrix.app == 'common' && matrix.app != '.gitkee' }} - uses: ruby/setup-ruby@v1 - with: - ruby-version: 2.7 - - name: Set up chart-testing if: ${{ matrix.app != '.gitkee' }} uses: helm/chart-testing-action@v2.0.1 @@ -123,17 +187,6 @@ jobs: id: lint run: ct lint --config .github/ct-lint.yaml --charts 'charts/${{ steps.prep-lint.outputs.train }}/${{ matrix.app }}' - - name: Install dependencies - if: ${{ matrix.app == 'common' && matrix.app != '.gitkee' }} - run: | - export RUBYJQ_USE_SYSTEM_LIBRARIES=1 - bundle install - - - name: Run common unit tests - if: ${{ matrix.app == 'common' && matrix.app != '.gitkee' }} - run: | - bundle exec m -r tests - - name: Create k3d cluster if: ${{ matrix.app != 'common' && matrix.app != '.gitkee' }} uses: nolar/setup-k3d-k3s@v1 @@ -146,7 +199,7 @@ jobs: run: ct install --config .github/ct-install.yaml --charts 'charts/${{ steps.prep-lint.outputs.train }}/${{ matrix.app }}' app-tests-complete: - needs: [app-tests] + needs: [app-tests, app-unit-tests] name: Apps Test Complete runs-on: ubuntu-latest steps: @@ -154,7 +207,7 @@ jobs: run: echo "App Tests Completed Successfully" pre-release: - needs: [app-tests] + needs: [app-tests, app-unit-tests] runs-on: ubuntu-latest outputs: release: ${{ steps.prep.outputs.release }} diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 26c6fd7562e..106cee591d4 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,6 +1,6 @@ { "recommendations": [ "ms-vscode-remote.remote-containers", - "rebornix.ruby" + "golang.go" ] } diff --git a/.vscode/launch.json b/.vscode/launch.json index b619b7ba712..8792e00ecef 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,34 +1,18 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { - "name": "UnitTest - active spec file only", - "type": "Ruby", + "name": "Common", + "type": "go", "request": "launch", - "cwd": "${workspaceRoot}", - "program": "/usr/local/bin/bundle", - "args": [ - "exec", - "m", - "-r", - "${relativeFile}" - ] - }, - { - "name": "UnitTest - all spec files", - "type": "Ruby", - "request": "launch", - "cwd": "${workspaceRoot}", - "program": "/usr/local/bin/bundle", - "args": [ - "exec", - "m", - "-r", - "${workspaceFolder}/tests" - ] + "mode": "test", + "remotePath": "", + "port": 2345, + "host": "127.0.0.1", + "program": "${workspaceRoot}/charts/library/common/tests/", + "env": {}, + "args": ["-test.v"], + "showLog": true } ] } diff --git a/Gemfile b/Gemfile deleted file mode 100644 index ac5b8e7319a..00000000000 --- a/Gemfile +++ /dev/null @@ -1,12 +0,0 @@ -# frozen_string_literal: true - -source 'https://rubygems.org' - -group :test do - gem 'm' - gem 'minitest' - gem 'minitest-implicit-subject' - gem 'minitest-reporters' - gem 'pry' - gem 'ruby-jq' -end diff --git a/Gemfile.lock b/Gemfile.lock deleted file mode 100644 index 48ddc30d7c9..00000000000 --- a/Gemfile.lock +++ /dev/null @@ -1,42 +0,0 @@ -GEM - remote: https://rubygems.org/ - specs: - ansi (1.5.0) - builder (3.2.4) - coderay (1.1.3) - m (1.5.1) - method_source (>= 0.6.7) - rake (>= 0.9.2.2) - method_source (1.0.0) - mini_portile2 (2.5.0) - minitest (5.14.4) - minitest-implicit-subject (1.4.0) - minitest - minitest-reporters (1.4.3) - ansi - builder - minitest (>= 5.0) - ruby-progressbar - multi_json (1.15.0) - pry (0.14.0) - coderay (~> 1.1) - method_source (~> 1.0) - rake (13.0.3) - ruby-jq (0.2.1) - mini_portile2 (>= 2.2.0) - multi_json - ruby-progressbar (1.11.0) - -PLATFORMS - ruby - -DEPENDENCIES - m - minitest - minitest-implicit-subject - minitest-reporters - pry - ruby-jq - -BUNDLED WITH - 2.1.4 diff --git a/charts/library/common/Chart.yaml b/charts/library/common/Chart.yaml index 05ec648fc50..2fbe311de89 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: 4.0.1 +version: 4.1.0 diff --git a/charts/library/common/templates/_all.tpl b/charts/library/common/templates/_all.tpl index 28391d77e00..644d7cb3b3f 100644 --- a/charts/library/common/templates/_all.tpl +++ b/charts/library/common/templates/_all.tpl @@ -7,26 +7,31 @@ Main entrypoint for the common library chart. It will render all underlying temp {{- /* Build the templates */ -}} {{- include "common.pvc" . }} - {{- print "---" | nindent 0 -}} + {{- if .Values.serviceAccount.create -}} {{- include "common.serviceAccount" . }} - {{- print "---" | nindent 0 -}} {{- end -}} - {{- if eq .Values.controllerType "deployment" }} + + {{- if eq .Values.controller.type "deployment" }} {{- include "common.deployment" . | nindent 0 }} - {{ else if eq .Values.controllerType "daemonset" }} + {{ else if eq .Values.controller.type "daemonset" }} {{- include "common.daemonset" . | nindent 0 }} - {{ else if eq .Values.controllerType "statefulset" }} + {{ else if eq .Values.controller.type "statefulset" }} {{- include "common.statefulset" . | nindent 0 }} + {{ else }} + {{- fail (printf "Not a valid controller.type (%s)" .Values.controller.type) }} {{- end -}} + {{ include "common.classes.hpa" . | nindent 0 }} - {{ include "common.services" . | nindent 0 }} + + {{ include "common.service" . | nindent 0 }} + {{ include "common.ingress" . | 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 }} + {{ include "common.class.mountPermissions" . | nindent 0 }} {{- end -}} diff --git a/charts/library/common/templates/_daemonset.tpl b/charts/library/common/templates/_daemonset.tpl index 91bb0a4fafd..0f0670cf40a 100644 --- a/charts/library/common/templates/_daemonset.tpl +++ b/charts/library/common/templates/_daemonset.tpl @@ -1,52 +1,35 @@ -{{/* -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. -*/}} - - {{/* This template serves as the blueprint for the DaemonSet objects that are created within the common library. */}} -{{- define "common.daemonset" -}} -apiVersion: {{ include "common.capabilities.daemonset.apiVersion" . }} +{{- define "common.daemonset" }} +--- +apiVersion: apps/v1 kind: DaemonSet metadata: name: {{ include "common.names.fullname" . }} labels: {{- include "common.labels" . | nindent 4 }} - {{- with .Values.controllerLabels }} - {{- toYaml . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.controllerAnnotations }} + {{- with .Values.controller.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} selector: matchLabels: - {{- include "common.labels.selectorLabels" . | nindent 6 }} + {{- include "common.labels.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "common.labels.selectorLabels" . | nindent 8 }} + {{- include "common.labels.selectorLabels" . | nindent 8 }} spec: {{- include "common.controller.pod" . | nindent 6 }} {{- end }} diff --git a/charts/library/common/templates/_deployment.tpl b/charts/library/common/templates/_deployment.tpl index caa9464359b..4cb645b58cf 100644 --- a/charts/library/common/templates/_deployment.tpl +++ b/charts/library/common/templates/_deployment.tpl @@ -1,56 +1,53 @@ -{{/* -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. -*/}} - {{/* This template serves as the blueprint for the Deployment objects that are created within the common library. */}} -{{- define "common.deployment" -}} -apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} +{{- define "common.deployment" }} +--- +apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "common.names.fullname" . }} labels: {{- include "common.labels" . | nindent 4 }} - {{- with .Values.controllerLabels }} - {{- toYaml . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} {{- end }} - {{- with .Values.controllerAnnotations }} + {{- with .Values.controller.annotations }} annotations: {{- toYaml . | nindent 4 }} {{- end }} spec: - replicas: {{ .Values.replicas }} - {{- with .Values.strategy }} - strategy: - {{- toYaml . | nindent 4 }} + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + replicas: {{ .Values.controller.replicas }} + {{- $strategy := default "Recreate" .Values.controller.strategy }} + {{- if and (ne $strategy "Recreate") (ne $strategy "RollingUpdate") }} + {{- fail (printf "Not a valid strategy type for Deployment (%s)" $strategy) }} {{- end }} + strategy: + type: {{ $strategy }} + {{- with .Values.controller.rollingUpdate }} + {{- if and (eq $strategy "RollingUpdate") (or .surge .unavailable) }} + rollingUpdate: + {{- with .unavailable }} + maxUnavailable: {{ . }} + {{- end }} + {{- with .surge }} + maxSurge: {{ . }} + {{- end }} + {{- end }} + {{- end }} selector: matchLabels: - {{- include "common.labels.selectorLabels" . | nindent 6 }} + {{- include "common.labels.selectorLabels" . | nindent 6 }} template: metadata: {{- with .Values.podAnnotations }} annotations: - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "common.labels.selectorLabels" . | nindent 8 }} + {{- include "common.labels.selectorLabels" . | nindent 8 }} spec: {{- include "common.controller.pod" . | nindent 6 }} {{- end }} diff --git a/charts/library/common/templates/_ingress.tpl b/charts/library/common/templates/_ingress.tpl index e4bec46807b..71eb165b5d9 100644 --- a/charts/library/common/templates/_ingress.tpl +++ b/charts/library/common/templates/_ingress.tpl @@ -1,34 +1,48 @@ -{{/* -Renders the Ingress objects required by the chart by returning a concatinated list -of the main Ingress and any additionalIngresses. -*/}} +{{/* Renders the Ingress objects required by the chart */}} {{- define "common.ingress" -}} - {{- /* Generate named ingresses as required */ -}} - {{- range $name, $ingress := .Values.ingress }} - {{- if $ingress.enabled -}} - {{- print ("---\n") | nindent 0 -}} - {{- $ingressValues := $ingress -}} + {{- /* Generate named ingresses as required */ -}} + {{- range $name, $ingress := .Values.ingress }} + {{- if $ingress.enabled -}} + {{- $ingressValues := $ingress -}} - {{/* set defaults */}} - {{- if not $ingressValues.nameSuffix -}} - {{- $_ := set $ingressValues "nameSuffix" $name -}} - {{ end -}} + {{/* set defaults */}} + {{- if and (not $ingressValues.nameOverride) (ne $name (include "common.ingress.primary" $)) -}} + {{- $_ := set $ingressValues "nameOverride" $name -}} + {{- end -}} - {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} - {{- include "common.classes.ingress" $ }} + {{- $_ := set $ "ObjectValues" (dict "ingress" $ingressValues) -}} + {{- include "common.classes.ingress" $ }} - - {{- 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 }} + {{- range $name, $tlsValues := $ingressValues.tls }} + {{- if .scaleCert }} + {{- $nameOverride := ( printf "%v-%v-%v" $ingressValues.nameOverride "tls" $name ) -}} + {{- $_ := set $tlsValues "nameOverride" $nameOverride -}} + {{- $_ := set $ "ObjectValues" (dict "certHolder" $tlsValues) -}} + {{- include "common.cert.secret" $ -}} {{- end }} - - {{- end }} {{- end }} + {{- end }} {{- end }} + +{{/* Return the name of the primary ingress object */}} +{{- define "common.ingress.primary" -}} + {{- $enabledIngresses := dict -}} + {{- range $name, $ingress := .Values.ingress -}} + {{- if $ingress.enabled -}} + {{- $_ := set $enabledIngresses $name . -}} + {{- end -}} + {{- end -}} + + {{- $result := "" -}} + {{- range $name, $ingress := $enabledIngresses -}} + {{- if and (hasKey $ingress "primary") $ingress.primary -}} + {{- $result = $name -}} + {{- end -}} + {{- end -}} + + {{- if not $result -}} + {{- $result = keys $enabledIngresses | first -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/charts/library/common/templates/_pvc.tpl b/charts/library/common/templates/_pvc.tpl index 4f2af2f3e64..e6322e4a8ce 100644 --- a/charts/library/common/templates/_pvc.tpl +++ b/charts/library/common/templates/_pvc.tpl @@ -32,11 +32,10 @@ of all the entries of the persistence key. {{- if and $PVC.enabled (not (or $emptyDir $PVC.existingClaim)) -}} {{- $persistenceValues := $PVC -}} - {{- if not $persistenceValues.nameSuffix -}} - {{- $_ := set $persistenceValues "nameSuffix" $index -}} + {{- if not $persistenceValues.nameOverride -}} + {{- $_ := set $persistenceValues "nameOverride" $index -}} {{- end -}} {{- $_ := set $ "ObjectValues" (dict "persistence" $persistenceValues) -}} - {{- print ("---") | nindent 0 -}} {{- include "common.classes.pvc" $ | nindent 0 -}} {{- end }} {{- end }} diff --git a/charts/library/common/templates/_secret.tpl b/charts/library/common/templates/_secret.tpl index 34d10d9c87f..1a6df463d7f 100644 --- a/charts/library/common/templates/_secret.tpl +++ b/charts/library/common/templates/_secret.tpl @@ -1,7 +1,8 @@ {{/* The Secret object to be created. */}} -{{- define "common.secret" -}} +{{- define "common.secret" }} +--- apiVersion: v1 kind: Secret metadata: diff --git a/charts/library/common/templates/_service.tpl b/charts/library/common/templates/_service.tpl new file mode 100644 index 00000000000..07e2a2a2b0a --- /dev/null +++ b/charts/library/common/templates/_service.tpl @@ -0,0 +1,43 @@ +{{/* +Renders the Service objects required by the chart. +*/}} +{{- define "common.service" -}} + {{- /* Generate named services as required */ -}} + {{- range $name, $service := .Values.service }} + {{- if $service.enabled -}} + {{- $serviceValues := $service -}} + + {{/* set the default nameOverride to the service name */}} + {{- if and (not $serviceValues.nameOverride) (ne $name (include "common.service.primary" $)) -}} + {{- $_ := set $serviceValues "nameOverride" $name -}} + {{ end -}} + + {{- $_ := set $ "ObjectValues" (dict "service" $serviceValues) -}} + {{- include "common.classes.service" $ }} + {{- end }} + {{- end }} +{{- end }} + +{{/* +Return the name of the primary service object +*/}} +{{- define "common.service.primary" -}} + {{- $enabledServices := dict -}} + {{- range $name, $service := .Values.service -}} + {{- if $service.enabled -}} + {{- $_ := set $enabledServices $name . -}} + {{- end -}} + {{- end -}} + + {{- $result := "" -}} + {{- range $name, $service := $enabledServices -}} + {{- if and (hasKey $service "primary") $service.primary -}} + {{- $result = $name -}} + {{- end -}} + {{- end -}} + + {{- if not $result -}} + {{- $result = keys $enabledServices | first -}} + {{- end -}} + {{- $result -}} +{{- end -}} diff --git a/charts/library/common/templates/_serviceaccount.tpl b/charts/library/common/templates/_serviceaccount.tpl index a8c0e7903ba..0cca83c05bd 100644 --- a/charts/library/common/templates/_serviceaccount.tpl +++ b/charts/library/common/templates/_serviceaccount.tpl @@ -1,7 +1,8 @@ {{/* The ServiceAccount object to be created. */}} -{{- define "common.serviceAccount" -}} +{{- define "common.serviceAccount" }} +--- apiVersion: v1 kind: ServiceAccount metadata: diff --git a/charts/library/common/templates/_services.tpl b/charts/library/common/templates/_services.tpl deleted file mode 100644 index 18a39cf9d3c..00000000000 --- a/charts/library/common/templates/_services.tpl +++ /dev/null @@ -1,21 +0,0 @@ -{{/* -Renders the Service objects required by the chart by returning a concatinated list -of the main Service and any additionalservice. -*/}} -{{- define "common.services" -}} - {{- if .Values.services -}} - {{- range $name, $service := .Values.services }} - {{- if $service.enabled -}} - {{- print ("---\n") | nindent 0 -}} - {{- $serviceValues := $service -}} - - {{- if $serviceValues.nameSuffix -}} - {{- $_ := 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/_statefulset.tpl b/charts/library/common/templates/_statefulset.tpl index 3b7915b3d92..24579fa06af 100644 --- a/charts/library/common/templates/_statefulset.tpl +++ b/charts/library/common/templates/_statefulset.tpl @@ -20,52 +20,60 @@ This file is considered to be modified by the TrueCharts Project. This template serves as the blueprint for the StatefulSet objects that are created within the common library. */}} -{{- define "common.statefulset" -}} -apiVersion: {{ include "common.capabilities.statefulset.apiVersion" . }} +{{- define "common.statefulset" }} +--- +apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ include "common.names.fullname" . }} labels: - {{- include "common.labels" . | nindent 4 }} - {{- with .Values.controllerLabels }} - {{- toYaml . | nindent 4 }} - {{- end }} - {{- with .Values.controllerAnnotations }} + {{- include "common.labels" . | nindent 4 }} + {{- with .Values.controller.labels }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- with .Values.controller.annotations }} annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: - replicas: {{ .Values.replicas }} - {{- with .Values.strategy }} - updateStrategy: {{- toYaml . | nindent 4 }} {{- end }} +spec: + revisionHistoryLimit: {{ .Values.controller.revisionHistoryLimit }} + replicas: {{ .Values.controller.replicas }} + {{- $strategy := default "RollingUpdate" .Values.controller.strategy }} + {{- if and (ne $strategy "OnDelete") (ne $strategy "RollingUpdate") }} + {{- fail (printf "Not a valid strategy type for StatefulSet (%s)" $strategy) }} + {{- end }} + updateStrategy: + type: {{ $strategy }} + {{- if and (eq $strategy "RollingUpdate") .Values.controller.rollingUpdate.partition }} + rollingUpdate: + partition: {{ .Values.controller.rollingUpdate.partition }} + {{- end }} selector: matchLabels: - {{- include "common.labels.selectorLabels" . | nindent 6 }} + {{- include "common.labels.selectorLabels" . | nindent 6 }} serviceName: {{ include "common.names.fullname" . }} template: metadata: {{- with .Values.podAnnotations }} annotations: - {{- toYaml . | nindent 8 }} + {{- toYaml . | nindent 8 }} {{- end }} labels: - {{- include "common.labels.selectorLabels" . | nindent 8 }} + {{- include "common.labels.selectorLabels" . | nindent 8 }} spec: {{- include "common.controller.pod" . | nindent 6 }} volumeClaimTemplates: - {{- range $index, $vct := .Values.volumeClaimTemplates }} - - metadata: - name: {{ $vct.name }} - spec: - accessModes: - - {{ required (printf "accessMode is required for vCT %v" $vct.name) $vct.accessMode | quote }} - resources: - requests: - storage: {{ required (printf "size is required for PVC %v" $vct.name) $vct.size | quote }} - {{- if $vct.storageClass }} - storageClassName: {{ if (eq "-" $vct.storageClass) }}""{{- else }}{{ $vct.storageClass | quote }}{{- end }} - {{- end }} -{{- end }} + {{- range $index, $vct := .Values.volumeClaimTemplates }} + - metadata: + name: {{ $vct.name }} + spec: + accessModes: + - {{ required (printf "accessMode is required for vCT %v" $vct.name) $vct.accessMode | quote }} + resources: + requests: + storage: {{ required (printf "size is required for PVC %v" $vct.name) $vct.size | quote }} + {{- if $vct.storageClass }} + storageClassName: {{ if (eq "-" $vct.storageClass) }}""{{- else }}{{ $vct.storageClass | quote }}{{- end }} + {{- end }} + {{- end }} {{- end }} diff --git a/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl b/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl index ae5769e2c26..1c448acd758 100644 --- a/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl +++ b/charts/library/common/templates/classes/_HorizontalPodAutoscaler.tpl @@ -3,12 +3,10 @@ This template serves as a blueprint for horizontal pod autoscaler objects that a 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" . -}} - + {{- if .Values.autoscaling.enabled -}} + {{- $hpaName := include "common.names.fullname" . -}} + {{- $targetName := include "common.names.fullname" . }} +--- apiVersion: autoscaling/v2beta1 kind: HorizontalPodAutoscaler metadata: @@ -18,27 +16,22 @@ metadata: spec: scaleTargetRef: apiVersion: apps/v1 - {{- if eq .Values.controllerType "statefulset" }} - kind: StatefulSet - {{- else }} - kind: Deployment - {{- end }} + kind: {{ include "common.names.controllerType" . }} name: {{ .Values.autoscaling.target | default $targetName }} minReplicas: {{ .Values.autoscaling.minReplicas | default 1 }} maxReplicas: {{ .Values.autoscaling.maxReplicas | default 3 }} metrics: - {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} - type: Resource resource: name: cpu targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} - {{- end }} - {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} - type: Resource resource: name: memory targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} - {{- end }} -{{- end }} -{{- end }} + {{- end }} + {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/classes/_ingress.tpl b/charts/library/common/templates/classes/_ingress.tpl index 8efc187a78a..6aa779658ef 100644 --- a/charts/library/common/templates/classes/_ingress.tpl +++ b/charts/library/common/templates/classes/_ingress.tpl @@ -3,23 +3,24 @@ 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) -}} + {{- $ingressName := include "common.names.fullname" . -}} + {{- $values := .Values.ingress -}} -{{- if hasKey . "ObjectValues" -}} - {{- with .ObjectValues.ingress -}} - {{- $values = . -}} + {{- if hasKey . "ObjectValues" -}} + {{- with .ObjectValues.ingress -}} + {{- $values = . -}} + {{- end -}} + {{ end -}} + + {{- if and (hasKey $values "nameOverride") $values.nameOverride -}} + {{- $ingressName = printf "%v-%v" $ingressName $values.nameOverride -}} {{- 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 -}} + {{- $primaryService := get .Values.service (include "common.service.primary" .) }} + {{- $primaryPort := get $primaryService.ports (include "common.classes.service.ports.primary" (dict "values" $primaryService)) -}} + {{- $name := include "common.names.name" . -}} + {{- $isStable := include "common.capabilities.ingress.isStable" . }} +--- apiVersion: {{ include "common.capabilities.ingress.apiVersion" . }} kind: Ingress metadata: @@ -31,60 +32,49 @@ metadata: {{- toYaml . | nindent 4 }} {{- end }} spec: - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} - {{- if $values.ingressClassName }} + {{- if and $isStable $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 }} + {{- else if .secretName }} + secretName: {{ tpl .secretName $ | quote}} {{- end }} {{- end }} {{- end }} rules: {{- range $values.hosts }} - {{- if .hostTpl }} - - host: {{ tpl .hostTpl $ | quote }} - {{- else }} - - host: {{ .host | quote }} - {{- end }} + - host: {{ tpl .host $ | quote }} http: paths: {{- range .paths }} - {{- if .pathTpl }} - - path: {{ tpl .pathTpl $ | quote }} - {{- else }} - - path: {{ .path | quote }} + {{- $service := $name -}} + {{- $port := $primaryPort.port -}} + {{- if .service -}} + {{- $service = default $name .service.name -}} + {{- $port = default $primaryPort.port .service.port -}} {{- end }} - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} + - path: {{ tpl .path $ | quote }} + {{- if $isStable }} pathType: {{ default "Prefix" .pathType }} {{- end }} backend: - {{- if eq (include "common.capabilities.ingress.apiVersion" $) "networking.k8s.io/v1" }} + {{- if $isStable }} service: - name: {{ .serviceName | default $svcName }} + name: {{ $service }} port: - number: {{ .servicePort | default $svcPort }} - {{- else }} - serviceName: {{ .serviceName | default $svcName }} - servicePort: {{ .servicePort | default $svcPort }} - {{- end }} + number: {{ $port }} + {{- else }} + serviceName: {{ $service }} + servicePort: {{ $port }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/library/common/templates/classes/_mountPermissions.tpl b/charts/library/common/templates/classes/_mountPermissions.tpl index a830b5dc7ea..2d043f7ea88 100644 --- a/charts/library/common/templates/classes/_mountPermissions.tpl +++ b/charts/library/common/templates/classes/_mountPermissions.tpl @@ -2,41 +2,37 @@ 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 -}} - +{{- define "common.class.mountPermissions" -}} + {{- if .Values.hostPathMounts -}} + {{- $jobName := include "common.names.fullname" . -}} + {{- $user := 568 -}} + {{- if .Values.env -}} + {{- $user = dig "PUID" $user .Values.env -}} + {{- end -}} + {{- $user = dig "runAsUser" $user .Values.podSecurityContext -}} + {{- $group := 568 -}} + {{- if and .Values.env -}} + {{- $group = dig "PGID" $group .Values.env -}} + {{- end -}} + {{- $group = dig "fsGroup" $group .Values.podSecurityContext -}} + {{- $hostPathMounts := dict -}} + {{- range $name, $mount := .Values.hostPathMounts -}} + {{- if and $mount.enabled $mount.setPermissions -}} + {{- $name = default $name $mount.name -}} + {{- $_ := set $hostPathMounts $name $mount -}} + {{- end -}} + {{- end }} +--- apiVersion: batch/v1 kind: Job metadata: - name: {{ $jobName }}-autopermissions + name: {{ printf "%s-auto-permissions" $jobName }} 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 + "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: @@ -44,48 +40,31 @@ spec: restartPolicy: Never containers: - name: set-mount-permissions - image: "alpine:3.3" + 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: - # + - /bin/sh + - -c + - | + {{- range $_, $hpm := $hostPathMounts }} + chown -R {{ printf "%d:%d %s" (int $user) (int $group) $hpm.mountPath }} + {{- end }} 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 }} + {{- range $name, $hpm := $hostPathMounts }} + - name: {{ printf "hostpathmounts-%s" $name }} + mountPath: {{ $hpm.mountPath }} + {{- if $hpm.subPath }} + subPath: {{ $hpm.subPath }} + {{- 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 }} + {{- range $name, $hpm := $hostPathMounts }} + - name: {{ printf "hostpathmounts-%s" $name }} + {{- if $hpm.emptyDir }} + emptyDir: {} + {{- else }} + hostPath: + path: {{ required "hostPath not set" $hpm.hostPath }} + {{- end }} + {{- end }} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/classes/_pvc.tpl b/charts/library/common/templates/classes/_pvc.tpl index 038ed3de5c1..b2e4064aac5 100644 --- a/charts/library/common/templates/classes/_pvc.tpl +++ b/charts/library/common/templates/classes/_pvc.tpl @@ -28,13 +28,12 @@ within the common library. {{- end -}} {{ end -}} {{- $pvcName := include "common.names.fullname" . -}} -{{- if hasKey $values "nameOverride" -}} - {{- $pvcName = $values.nameOverride -}} -{{- else if hasKey $values "nameSuffix" -}} - {{- if not (eq $values.nameSuffix "-") -}} - {{- $pvcName = printf "%v-%v" $pvcName $values.nameSuffix -}} +{{- if and (hasKey $values "nameOverride") $values.nameOverride -}} + {{- if not (eq $values.nameOverride "-") -}} + {{- $pvcName = printf "%v-%v" $pvcName $values.nameOverride -}} {{ end -}} -{{ end -}} +{{ end }} +--- kind: PersistentVolumeClaim apiVersion: v1 metadata: diff --git a/charts/library/common/templates/classes/_service.tpl b/charts/library/common/templates/classes/_service.tpl index cfaec8bc46a..09e49a43fb4 100644 --- a/charts/library/common/templates/classes/_service.tpl +++ b/charts/library/common/templates/classes/_service.tpl @@ -21,17 +21,20 @@ This template serves as a blueprint for all Service objects that are created within the common library. */}} {{- define "common.classes.service" -}} -{{- $values := index .Values.services (keys .Values.services | first) -}} +{{- $values := .Values.service -}} {{- 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 -}} +{{- if and (hasKey $values "nameOverride") $values.nameOverride -}} + {{- $serviceName = printf "%v-%v" $serviceName $values.nameOverride -}} {{ end -}} {{- $svcType := $values.type | default "" -}} +{{- $primaryPort := get $values.ports (include "common.classes.service.ports.primary" (dict "values" $values)) }} +--- apiVersion: v1 kind: Service metadata: @@ -42,7 +45,7 @@ metadata: {{ toYaml $values.labels | nindent 4 }} {{- end }} annotations: - {{- if eq ( $values.port.protocol | default "" ) "HTTPS" }} + {{- if eq ( $primaryPort.protocol | default "" ) "HTTPS" }} traefik.ingress.kubernetes.io/service.serversscheme: https {{- end }} {{- with $values.annotations }} @@ -83,7 +86,26 @@ spec: {{- if $values.publishNotReadyAddresses }} publishNotReadyAddresses: {{ $values.publishNotReadyAddresses }} {{- end }} - {{- include "common.classes.service.ports" (dict "svcType" $svcType "values" $values ) | trim | nindent 2 }} + ports: + {{- range $name, $port := $values.ports }} + {{- if $port.enabled }} + - port: {{ $port.port }} + targetPort: {{ $port.targetPort | default $name }} + {{- if $port.protocol }} + {{- if or ( eq $port.protocol "HTTP" ) ( eq $port.protocol "HTTPS" ) ( eq $port.protocol "TCP" ) }} + protocol: TCP + {{- else }} + protocol: {{ $port.protocol }} + {{- end }} + {{- else }} + protocol: TCP + {{- end }} + name: {{ $name }} + {{- if (and (eq $svcType "NodePort") (not (empty $port.nodePort))) }} + nodePort: {{ $port.nodePort }} + {{ end }} + {{- end }} + {{- end }} selector: {{- include "common.labels.selectorLabels" . | nindent 4 }} {{- end }} diff --git a/charts/library/common/templates/classes/_service_ports.tpl b/charts/library/common/templates/classes/_service_ports.tpl index 7a9f62b70da..3eaaa9e1bc4 100644 --- a/charts/library/common/templates/classes/_service_ports.tpl +++ b/charts/library/common/templates/classes/_service_ports.tpl @@ -17,33 +17,29 @@ This file is considered to be modified by the TrueCharts Project. */}} {{/* -Render all the ports and additionalPorts for a Service object. +Return the name of the primary port for a given Service object. */}} -{{- define "common.classes.service.ports" -}} - {{- $ports := list -}} - {{- $values := .values -}} - {{- $ports = mustAppend $ports $values.port -}} - {{- range $_ := $values.additionalPorts -}} - {{- $ports = mustAppend $ports . -}} +{{- define "common.classes.service.ports.primary" -}} + {{- $enabledPorts := dict -}} + {{- range $name, $port := .values.ports -}} + {{- if $port.enabled -}} + {{- $_ := set $enabledPorts $name . -}} + {{- end -}} + {{- end -}} + + {{- if eq 0 (len $enabledPorts) }} + {{- fail (printf "No ports are enabled for service \"%s\"!" .serviceName) }} {{- end }} - {{- if $ports -}} - ports: - {{- range $_ := $ports }} - - port: {{ .port }} - targetPort: {{ .targetPort | default .name | default "http" }} - {{- 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 }} - {{ end }} + + {{- $result := "" -}} + {{- range $name, $port := $enabledPorts -}} + {{- if and (hasKey $port "primary") $port.primary -}} + {{- $result = $name -}} + {{- end -}} {{- end -}} + + {{- if not $result -}} + {{- $result = keys $enabledPorts | first -}} {{- end -}} -{{- end }} + {{- $result -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/cert/_certSecret.yaml b/charts/library/common/templates/lib/cert/_certSecret.yaml index fe133800f37..fe15636491e 100644 --- a/charts/library/common/templates/lib/cert/_certSecret.yaml +++ b/charts/library/common/templates/lib/cert/_certSecret.yaml @@ -14,6 +14,7 @@ {{ end -}} {{- if eq (include "common.cert.available" $ ) "true" -}} +--- apiVersion: v1 kind: Secret metadata: diff --git a/charts/library/common/templates/lib/chart/_capabilities.tpl b/charts/library/common/templates/lib/chart/_capabilities.tpl index 809dcae467d..96de3c104d9 100644 --- a/charts/library/common/templates/lib/chart/_capabilities.tpl +++ b/charts/library/common/templates/lib/chart/_capabilities.tpl @@ -1,110 +1,19 @@ -{{/* -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. -*/}} - -{{/* -Return the appropriate apiVersion for DaemonSet objects. -*/}} -{{- define "common.capabilities.daemonset.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} +{{/* Allow KubeVersion to be overridden. */}} +{{- define "common.capabilities.ingress.kubeVersion" -}} + {{- default .Capabilities.KubeVersion.Version .Values.kubeVersionOverride -}} {{- end -}} -{{/* -Waiting on https://github.com/helm/helm/pull/8608 -{{- define "common.capabilities.daemonset.apiVersion" -}} -{{- if .Capabilities.APIVersions.Has "apps/v1/DaemonSet" -}} -{{- print "apps/v1" -}} -{{- else -}} -{{- print "extensions/v1beta1" -}} -{{- end -}} -{{- end -}} -*/}} - -{{/* -Return the appropriate apiVersion for Deployment objects. -*/}} -{{- define "common.capabilities.deployment.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "extensions/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Waiting on https://github.com/helm/helm/pull/8608 -{{- define "common.capabilities.deployment.apiVersion" -}} -{{- if .Capabilities.APIVersions.Has "apps/v1/Deployment" -}} -{{- print "apps/v1" -}} -{{- else -}} -{{- print "extensions/v1beta1" -}} -{{- end -}} -{{- end -}} -*/}} - -{{/* -Return the appropriate apiVersion for StatefulSet objects. -*/}} -{{- define "common.capabilities.statefulset.apiVersion" -}} -{{- if semverCompare "<1.14-0" .Capabilities.KubeVersion.GitVersion -}} -{{- print "apps/v1beta1" -}} -{{- else -}} -{{- print "apps/v1" -}} -{{- end -}} -{{- end -}} - -{{/* -Waiting on https://github.com/helm/helm/pull/8608 -{{- define "common.capabilities.statefulset.apiVersion" -}} -{{- if .Capabilities.APIVersions.Has "apps/v1/StatefulSet" -}} -{{- print "apps/v1" -}} -{{- else -}} -{{- print "apps/v1beta1" -}} -{{- end -}} -{{- end -}} -*/}} - -{{/* -Return the appropriate apiVersion for Ingress objects. -*/}} - +{{/* Return the appropriate apiVersion for Ingress objects */}} {{- define "common.capabilities.ingress.apiVersion" -}} -{{- 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" -}} -{{- else -}} -{{- print "networking.k8s.io/v1" -}} -{{- end }} + {{- print "networking.k8s.io/v1" -}} + {{- if semverCompare "<1.19" (include "common.capabilities.ingress.kubeVersion" .) -}} + {{- print "beta1" -}} + {{- end -}} {{- end -}} -{{/* -Waiting on https://github.com/helm/helm/pull/8608 -{{- define "common.capabilities.ingress.apiVersion" -}} -{{- if .Capabilities.APIVersions.Has "networking.k8s.io/v1/Ingress" -}} -{{- print "networking.k8s.io/v1" -}} -{{- else if .Capabilities.APIVersions.Has "networking.k8s.io/v1beta1/Ingress" -}} -{{- print "networking.k8s.io/v1beta1" -}} -{{- else -}} -{{- print "extensions/v1beta1" -}} -{{- end }} +{{/* Check Ingress stability */}} +{{- define "common.capabilities.ingress.isStable" -}} + {{- if eq (include "common.capabilities.ingress.apiVersion" .) "networking.k8s.io/v1" -}} + {{- true -}} + {{- end -}} {{- end -}} -*/}} diff --git a/charts/library/common/templates/lib/chart/_errors.tpl b/charts/library/common/templates/lib/chart/_errors.tpl deleted file mode 100644 index 2985af443df..00000000000 --- a/charts/library/common/templates/lib/chart/_errors.tpl +++ /dev/null @@ -1,38 +0,0 @@ -{{/* -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. -*/}} - -{{/* vim: set filetype=mustache: */}} -{{/* -Through error when upgrading using empty passwords values that must not be empty. - -Usage: -{{- $validationError00 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password00" "secret" "secretName" "field" "password-00") -}} -{{- $validationError01 := include "common.validations.values.single.empty" (dict "valueKey" "path.to.password01" "secret" "secretName" "field" "password-01") -}} -{{ include "common.errors.upgrade.passwords.empty" (dict "validationErrors" (list $validationError00 $validationError01) "context" $) }} - -Required password params: - - validationErrors - String - Required. List of validation strings to be return, if it is empty it won't throw error. - - context - Context - Required. Parent context. -*/}} -{{- define "common.errors.upgrade.passwords.empty" -}} - {{- $validationErrors := join "" .validationErrors -}} - {{- if and $validationErrors .context.Release.IsUpgrade -}} - {{- $errorString := "\nPASSWORDS ERROR: you must provide your current passwords when upgrade the release%s" -}} - {{- printf $errorString $validationErrors | fail -}} - {{- end -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_images.tpl b/charts/library/common/templates/lib/chart/_images.tpl deleted file mode 100644 index 12c8ea13608..00000000000 --- a/charts/library/common/templates/lib/chart/_images.tpl +++ /dev/null @@ -1,65 +0,0 @@ -{{/* -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. -*/}} - -{{/* vim: set filetype=mustache: */}} -{{/* -Return the proper image name -{{ include "common.images.image" ( dict "imageRoot" .Values.path.to.the.image "global" $) }} -*/}} -{{- define "common.images.image" -}} -{{- $registryName := .imageRoot.registry -}} -{{- $repositoryName := .imageRoot.repository -}} -{{- $tag := .imageRoot.tag | toString -}} -{{- if .global }} - {{- if .global.imageRegistry }} - {{- $registryName = .global.imageRegistry -}} - {{- end -}} -{{- end -}} -{{- if $registryName }} -{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}} -{{- else -}} -{{- printf "%s:%s" $repositoryName $tag -}} -{{- end -}} -{{- end -}} - -{{/* -Return the proper Docker Image Registry Secret Names -{{ include "common.images.pullSecrets" ( dict "images" (list .Values.path.to.the.image1, .Values.path.to.the.image2) "global" .Values.global) }} -*/}} -{{- define "common.images.pullSecrets" -}} - {{- $pullSecrets := list }} - - {{- if .global }} - {{- range .global.imagePullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- range .images -}} - {{- range .pullSecrets -}} - {{- $pullSecrets = append $pullSecrets . -}} - {{- end -}} - {{- end -}} - - {{- if (not (empty $pullSecrets)) }} -imagePullSecrets: - {{- range $pullSecrets }} - - name: {{ . }} - {{- end }} - {{- end }} -{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_labels.tpl b/charts/library/common/templates/lib/chart/_labels.tpl index 760bdd65db9..8a1e11aa807 100644 --- a/charts/library/common/templates/lib/chart/_labels.tpl +++ b/charts/library/common/templates/lib/chart/_labels.tpl @@ -1,37 +1,15 @@ -{{/* -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. -*/}} - -{{/* -Common labels shared across objects. -*/}} +{{/* Common labels shared across objects */}} {{- define "common.labels" -}} helm.sh/chart: {{ include "common.names.chart" . }} {{ include "common.labels.selectorLabels" . }} -{{- if .Chart.AppVersion }} + {{- if .Chart.AppVersion }} app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} + {{- end }} app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} +{{- end -}} -{{/* -Selector labels shared across objects. -*/}} +{{/* Selector labels shared across objects */}} {{- define "common.labels.selectorLabels" -}} app.kubernetes.io/name: {{ include "common.names.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} +{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_names.tpl b/charts/library/common/templates/lib/chart/_names.tpl index 0112cc3b3f0..d0587cddf24 100644 --- a/charts/library/common/templates/lib/chart/_names.tpl +++ b/charts/library/common/templates/lib/chart/_names.tpl @@ -16,13 +16,10 @@ limitations under the License. This file is considered to be modified by the TrueCharts Project. */}} -{{/* vim: set filetype=mustache: */}} -{{/* -Expand the name of the chart. -*/}} +{{/* Expand the name of the chart */}} {{- define "common.names.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} + {{- default .Chart.Name (default .Values.nameOverride .Values.global.nameOverride) | trunc 63 | trimSuffix "-" -}} +{{- end -}} {{/* Create a default fully qualified app name. @@ -30,32 +27,42 @@ 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 }} + {{- $name := include "common.names.name" . -}} + {{- if or .Values.fullnameOverride .Values.global.fullnameOverride -}} + {{- $name = default .Values.fullnameOverride .Values.global.fullnameOverride -}} + {{- else -}} + {{- if contains $name .Release.Name -}} + {{- $name := .Release.Name -}} + {{- else -}} + {{- $name := printf "%s-%s" .Release.Name $name -}} + {{- end -}} + {{- end -}} + {{- trunc 63 $name | trimSuffix "-" -}} +{{- end -}} -{{/* -Create chart name and version as used by the chart label. -*/}} +{{/* Create chart name and version as used by the chart label */}} {{- define "common.names.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} -{{/* -Create the name of the ServiceAccount to use. -*/}} +{{/* Create the name of the ServiceAccount to use */}} {{- define "common.names.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} - {{- default (include "common.names.fullname" .) .Values.serviceAccount.name }} -{{- else }} - {{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} + {{- if .Values.serviceAccount.create -}} + {{- default (include "common.names.fullname" .) .Values.serviceAccount.name -}} + {{- else -}} + {{- default "default" .Values.serviceAccount.name -}} + {{- end -}} +{{- end -}} + +{{/* Return the properly cased version of the controller type */}} +{{- define "common.names.controllerType" -}} + {{- if eq .Values.controller.type "deployment" -}} + {{- print "Deployment" -}} + {{- else if eq .Values.controller.type "daemonset" -}} + {{- print "DaemonSet" -}} + {{- else if eq .Values.controller.type "statefulset" -}} + {{- print "StatefulSet" -}} + {{- else -}} + {{- fail (printf "Not a valid controller.type (%s)" .Values.controller.type) -}} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_utils.tpl b/charts/library/common/templates/lib/chart/_utils.tpl deleted file mode 100644 index c8cec118629..00000000000 --- a/charts/library/common/templates/lib/chart/_utils.tpl +++ /dev/null @@ -1,80 +0,0 @@ -{{/* -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. -*/}} - -{{/* vim: set filetype=mustache: */}} -{{/* -Print instructions to get a secret value. -Usage: -{{ include "common.utils.secret.getvalue" (dict "secret" "secret-name" "field" "secret-value-field" "context" $) }} -*/}} -{{- define "common.utils.secret.getvalue" -}} -{{- $varname := include "common.utils.fieldToEnvVar" . -}} -export {{ $varname }}=$(kubectl get secret --namespace {{ .context.Release.Namespace | quote }} {{ .secret }} -o jsonpath="{.data.{{ .field }}}" | base64 --decode) -{{- end -}} - -{{/* -Build env var name given a field -Usage: -{{ include "common.utils.fieldToEnvVar" dict "field" "my-password" }} -*/}} -{{- define "common.utils.fieldToEnvVar" -}} - {{- $fieldNameSplit := splitList "-" .field -}} - {{- $upperCaseFieldNameSplit := list -}} - - {{- range $fieldNameSplit -}} - {{- $upperCaseFieldNameSplit = append $upperCaseFieldNameSplit ( upper . ) -}} - {{- end -}} - - {{ join "_" $upperCaseFieldNameSplit }} -{{- end -}} - -{{/* -Gets a value from .Values given -Usage: -{{ include "common.utils.getValueFromKey" (dict "key" "path.to.key" "context" $) }} -*/}} -{{- define "common.utils.getValueFromKey" -}} -{{- $splitKey := splitList "." .key -}} -{{- $value := "" -}} -{{- $latestObj := $.context.Values -}} -{{- range $splitKey -}} - {{- if not $latestObj -}} - {{- printf "please review the entire path of '%s' exists in values" $.key | fail -}} - {{- end -}} - {{- $value = ( index $latestObj . ) -}} - {{- $latestObj = $value -}} -{{- end -}} -{{- printf "%v" (default "" $value) -}} -{{- end -}} - -{{/* -Returns first .Values key with a defined value or first of the list if all non-defined -Usage: -{{ include "common.utils.getKeyFromList" (dict "keys" (list "path.to.key1" "path.to.key2") "context" $) }} -*/}} -{{- define "common.utils.getKeyFromList" -}} -{{- $key := first .keys -}} -{{- $reverseKeys := reverse .keys }} -{{- range $reverseKeys }} - {{- $value := include "common.utils.getValueFromKey" (dict "key" . "context" $.context ) }} - {{- if $value -}} - {{- $key = . }} - {{- end -}} -{{- end -}} -{{- printf "%s" $key -}} -{{- end -}} diff --git a/charts/library/common/templates/lib/chart/_values.tpl b/charts/library/common/templates/lib/chart/_values.tpl index af6b4658fdf..d3c8413c8f7 100644 --- a/charts/library/common/templates/lib/chart/_values.tpl +++ b/charts/library/common/templates/lib/chart/_values.tpl @@ -1,29 +1,9 @@ -{{/* -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. -*/}} - -{{/* -Merge the local chart values and the common chart defaults. -*/}} +{{/* Merge the local chart values and the common chart defaults */}} {{- define "common.values.setup" -}} {{- if .Values.common -}} {{- $defaultValues := deepCopy .Values.common -}} {{- $userValues := deepCopy (omit .Values "common") -}} {{- $mergedValues := mustMergeOverwrite $defaultValues $userValues -}} {{- $_ := set . "Values" (deepCopy $mergedValues) -}} - {{- end }} -{{- end }} + {{- end -}} +{{- end -}} diff --git a/charts/library/common/templates/lib/controller/_container.tpl b/charts/library/common/templates/lib/controller/_container.tpl index fabfeaa2e50..4e61b6571f4 100644 --- a/charts/library/common/templates/lib/controller/_container.tpl +++ b/charts/library/common/templates/lib/controller/_container.tpl @@ -1,44 +1,23 @@ -{{/* -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. -*/}} - - -{{- /* -The main container included in the controller. -*/ -}} +{{- /* The main container included in the controller */ -}} {{- define "common.controller.mainContainer" -}} - name: {{ include "common.names.fullname" . }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + image: {{ printf "%s:%s" .Values.image.repository (default .Chart.AppVersion .Values.image.tag) | quote }} imagePullPolicy: {{ .Values.image.pullPolicy }} {{- with .Values.command }} - {{- if kindIs "string" . }} - command: {{ . }} - {{- else }} command: - {{ toYaml . | nindent 2 }} - {{- end }} + {{- if kindIs "string" . }} + - {{ . }} + {{- else }} + {{ toYaml . | nindent 4 }} + {{- end }} {{- end }} {{- with .Values.args }} - {{- if kindIs "string" . }} - args: {{ . }} - {{- else }} args: - {{ toYaml . | nindent 2 }} - {{- end }} + {{- if kindIs "string" . }} + - {{ . }} + {{- else }} + {{ toYaml . | nindent 4 }} + {{- end }} {{- end }} {{- with .Values.securityContext }} securityContext: @@ -46,53 +25,68 @@ The main container included in the controller. {{- end }} {{- with .Values.lifecycle }} lifecycle: - {{- toYaml . | nindent 2 }} + {{- toYaml . | nindent 4 }} {{- end }} + env: - {{- if .Values.timezone }} - - name: TZ - value: {{ .Values.timezone | quote }} - {{- end }} - {{- if or .Values.env .Values.envTpl .Values.envValueFrom .Values.envVariable .Values.envList }} + {{- range $key, $value := .Values.envTpl }} + - name: {{ $key }} + value: {{ tpl $value $ | quote }} + {{- end }} + {{- range $key, $value := .Values.envValueFrom }} + - name: {{ $key }} + valueFrom: + {{- $value | toYaml | nindent 6 }} + {{- end }} {{- range $envList := .Values.envList }} - {{- if and $envList.name $envList.value }} - - name: {{ $envList.name }} - value: {{ $envList.value | quote }} - {{- else }} + {{- if and $envList.name $envList.value }} + - name: {{ $envList.name }} + value: {{ $envList.value | quote }} + {{- else }} {{- fail "Please specify name/value for environment variable" }} - {{- end }} + {{- end }} {{- end}} - {{- range $key, $value := .Values.env }} - - name: {{ $key }} - value: {{ $value | quote }} - {{- end }} - {{- range $key, $value := .Values.envTpl }} - - name: {{ $key }} - value: {{ tpl $value $ | quote }} - {{- end }} - {{- range $key, $value := .Values.envValueFrom }} - - name: {{ $key }} - valueFrom: - {{- $value | toYaml | nindent 6 }} - {{- end }} + {{- with .Values.env }} + {{- range $k, $v := . }} + {{- $name := $k }} + {{- $value := $v }} + {{- if kindIs "int" $name }} + {{- $name = required "environment variables as a list of maps require a name field" $value.name }} + {{- end }} + - name: {{ quote $name }} + {{- if kindIs "map" $value -}} + {{- if hasKey $value "value" }} + {{- $value = $value.value -}} + {{- else if hasKey $value "valueFrom" }} + {{- toYaml $value | nindent 6 }} + {{- else }} + {{- dict "valueFrom" $value | toYaml | nindent 6 }} + {{- end }} + {{- end }} + {{- if not (kindIs "map" $value) }} + {{- if kindIs "string" $value }} + {{- $value = tpl $value $ }} + {{- end }} + value: {{ quote $value }} + {{- end }} + {{- end }} {{- end }} {{- if or .Values.envFrom .Values.secret }} envFrom: - {{- with .Values.envFrom }} - {{- toYaml . | nindent 2 }} - {{- end }} - {{- if or .Values.secret }} - - secretRef: - name: {{ include "common.names.fullname" . }} - {{- end }} + {{- with .Values.envFrom }} + {{- toYaml . | nindent 4 }} + {{- end }} + {{- if .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 }} + {{ nindent 4 . }} {{- end }} - {{- include "common.controller.probes" . | nindent 2 }} - + {{- include "common.controller.probes" . | trim | nindent 2 }} {{/* Merges the TrueNAS SCALE generated GPU info with the .Values.resources dict */}} diff --git a/charts/library/common/templates/lib/controller/_pod.tpl b/charts/library/common/templates/lib/controller/_pod.tpl index 5a053a41827..76bd45a84fb 100644 --- a/charts/library/common/templates/lib/controller/_pod.tpl +++ b/charts/library/common/templates/lib/controller/_pod.tpl @@ -2,66 +2,66 @@ The pod definition included in the controller. */ -}} {{- define "common.controller.pod" -}} -{{- with .Values.imagePullSecrets }} + {{- with .Values.imagePullSecrets }} imagePullSecrets: - {{- toYaml . | nindent 2 }} -{{- end }} -serviceAccountName: {{ include "common.names.serviceAccountName" . }} -{{- with .Values.podSecurityContext }} -securityContext: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.priorityClassName }} -priorityClassName: {{ . }} -{{- end }} -{{- with .Values.schedulerName }} -schedulerName: {{ . }} -{{- end }} -{{- with .Values.hostNetwork }} -hostNetwork: {{ . }} -{{- end }} -{{- with .Values.hostname }} -hostname: {{ . }} -{{- end }} -{{- if .Values.dnsPolicy }} -dnsPolicy: {{ .Values.dnsPolicy }} -{{- else if .Values.hostNetwork }} -dnsPolicy: "ClusterFirstWithHostNet" -{{- else }} -dnsPolicy: ClusterFirst -{{- end }} -{{- with .Values.dnsConfig }} -dnsConfig: - {{- toYaml . | nindent 2 }} -{{- end }} -enableServiceLinks: {{ .Values.enableServiceLinks }} -{{- with .Values.initContainers }} -initContainers: - {{- toYaml . | nindent 2 }} -{{- end }} -containers: - {{- include "common.controller.mainContainer" . | nindent 0 }} - {{- with .Values.additionalContainers }} - {{- tpl (toYaml .) $ | nindent 0 }} + {{- toYaml . | nindent 2 }} {{- end }} -{{- with (include "common.controller.volumes" . | trim) }} +serviceAccountName: {{ include "common.names.serviceAccountName" . }} + {{- with .Values.podSecurityContext }} +securityContext: + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.priorityClassName }} +priorityClassName: {{ . }} + {{- end }} + {{- with .Values.schedulerName }} +schedulerName: {{ . }} + {{- end }} + {{- with .Values.hostNetwork }} +hostNetwork: {{ . }} + {{- end }} + {{- with .Values.hostname }} +hostname: {{ . }} + {{- end }} + {{- if .Values.dnsPolicy }} +dnsPolicy: {{ .Values.dnsPolicy }} + {{- else if .Values.hostNetwork }} +dnsPolicy: ClusterFirstWithHostNet + {{- else }} +dnsPolicy: ClusterFirst + {{- end }} + {{- with .Values.dnsConfig }} +dnsConfig: + {{- toYaml . | nindent 2 }} + {{- end }} +enableServiceLinks: {{ .Values.enableServiceLinks }} + {{- with .Values.initContainers }} +initContainers: + {{- toYaml . | nindent 2 }} + {{- end }} +containers: + {{- include "common.controller.mainContainer" . | nindent 2 }} + {{- with .Values.additionalContainers }} + {{- tpl (toYaml .) $ | nindent 2 }} + {{- end }} + {{- with (include "common.controller.volumes" . | trim) }} volumes: - {{- . | nindent 0 }} -{{- end }} -{{- with .Values.hostAliases }} + {{- nindent 2 . }} + {{- end }} + {{- with .Values.hostAliases }} hostAliases: -{{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.nodeSelector }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.nodeSelector }} nodeSelector: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.affinity }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.affinity }} affinity: - {{- toYaml . | nindent 2 }} -{{- end }} -{{- with .Values.tolerations }} + {{- toYaml . | nindent 2 }} + {{- end }} + {{- with .Values.tolerations }} tolerations: - {{- toYaml . | nindent 2 }} -{{- end }} + {{- toYaml . | nindent 2 }} + {{- end }} {{- end -}} diff --git a/charts/library/common/templates/lib/controller/_ports.tpl b/charts/library/common/templates/lib/controller/_ports.tpl index 13b1e8e0185..39e4e9300b4 100644 --- a/charts/library/common/templates/lib/controller/_ports.tpl +++ b/charts/library/common/templates/lib/controller/_ports.tpl @@ -2,41 +2,36 @@ Ports included by the controller. */}} {{- define "common.controller.ports" -}} -{{- $ports := list -}} - {{/* append the ports for each service */}} - {{- if $.Values.services -}} - {{- range $name, $_ := $.Values.services }} - {{- if .enabled -}} - {{- if kindIs "string" $name -}} - {{- $_ := set .port "name" (default .port.name | default $name) -}} - {{- else -}} - {{- $_ := set .port "name" (required "Missing port.name" .port.name) -}} - {{- end -}} - {{- $ports = mustAppend $ports .port -}} - {{- range $_ := .additionalPorts -}} - {{/* append the additonalPorts for each additional service */}} - {{- $ports = mustAppend $ports . -}} - {{- end }} - {{- end }} + {{- $ports := list -}} + {{- range .Values.service -}} + {{- if .enabled -}} + {{- range $name, $port := .ports -}} + {{- $_ := set $port "name" $name -}} + {{- $ports = mustAppend $ports $port -}} {{- end }} {{- end }} + {{- end }} {{/* export/render the list of ports */}} {{- if $ports -}} ports: {{- range $_ := $ports }} -{{- $protocol := "" -}} -{{- if or ( eq .protocol "HTTP" ) ( eq .protocol "HTTPS" ) }} - {{- $protocol = "TCP" -}} -{{- else }} - {{- $protocol = .protocol | default "TCP" -}} -{{- end }} -- name: {{ required "The port's 'name' is not defined" .name }} +{{- if .enabled }} +- name: {{ .name }} {{- if and .targetPort (kindIs "string" .targetPort) }} {{- fail (printf "Our charts do not support named ports for targetPort. (port name %s, targetPort %s)" .name .targetPort) }} {{- end }} containerPort: {{ .targetPort | default .port }} - 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 }} +{{- end}} {{- end -}} {{- end -}} {{- end -}} diff --git a/charts/library/common/templates/lib/controller/_probes.tpl b/charts/library/common/templates/lib/controller/_probes.tpl index 0083fb65b4b..f8eaa26cb80 100644 --- a/charts/library/common/templates/lib/controller/_probes.tpl +++ b/charts/library/common/templates/lib/controller/_probes.tpl @@ -21,8 +21,12 @@ This file is considered to be modified by the TrueCharts Project. Probes selection logic. */}} {{- define "common.controller.probes" -}} -{{- $svc := index .Values.services (keys .Values.services | first) -}} -{{- $svcPort := $svc.port.name -}} +{{- $primaryService := get .Values.service (include "common.service.primary" .) -}} +{{- $primaryPort := "" -}} +{{- if $primaryService -}} + {{- $primaryPort = get $primaryService.ports (include "common.classes.service.ports.primary" (dict "serviceName" (include "common.service.primary" .) "values" $primaryService)) -}} +{{- end -}} + {{- range $probeName, $probe := .Values.probes }} {{- if $probe.enabled -}} {{- "" | nindent 0 }} @@ -30,12 +34,14 @@ Probes selection logic. {{- if $probe.custom -}} {{- $probe.spec | toYaml | nindent 2 }} {{- else }} - {{- "tcpSocket:" | nindent 2 }} - {{- printf "port: %v" $svcPort | nindent 4 }} - {{- printf "initialDelaySeconds: %v" $probe.spec.initialDelaySeconds | nindent 2 }} - {{- printf "failureThreshold: %v" $probe.spec.failureThreshold | nindent 2 }} - {{- printf "timeoutSeconds: %v" $probe.spec.timeoutSeconds | nindent 2 }} - {{- printf "periodSeconds: %v" $probe.spec.periodSeconds | nindent 2 }} + {{- if and $primaryService $primaryPort -}} + {{- "tcpSocket:" | nindent 2 }} + {{- printf "port: %v" $primaryPort.port | nindent 4 }} + {{- printf "initialDelaySeconds: %v" $probe.spec.initialDelaySeconds | nindent 2 }} + {{- printf "failureThreshold: %v" $probe.spec.failureThreshold | nindent 2 }} + {{- printf "timeoutSeconds: %v" $probe.spec.timeoutSeconds | nindent 2 }} + {{- printf "periodSeconds: %v" $probe.spec.periodSeconds | nindent 2 }} + {{- end }} {{- end }} {{- end }} {{- end }} diff --git a/charts/library/common/templates/lib/controller/_volumeMounts.tpl b/charts/library/common/templates/lib/controller/_volumeMounts.tpl index 98dd4af3f42..f0badf21818 100644 --- a/charts/library/common/templates/lib/controller/_volumeMounts.tpl +++ b/charts/library/common/templates/lib/controller/_volumeMounts.tpl @@ -1,17 +1,14 @@ -{{/* -Volumes included by the controller. -*/}} +{{/* Volumes included by the controller */}} {{- define "common.controller.volumeMounts" -}} - -{{- range $index, $PVC := .Values.persistence }} -{{- if $PVC.enabled }} + {{- range $index, $PVC := .Values.persistence }} + {{- if $PVC.enabled }} - mountPath: {{ $PVC.mountPath | default (printf "/%v" $index) }} name: {{ $index }} -{{- if $PVC.subPath }} + {{- if $PVC.subPath }} subPath: {{ $PVC.subPath }} -{{- end }} -{{- end }} -{{- end }} + {{- end }} + {{- end }} + {{- end }} {{/* Creates mountpoints to mount devices directly to the same path inside the container @@ -28,38 +25,32 @@ Creates mountpoints to mount devices directly to the same path inside the contai {{ end }} {{- end -}} {{ end }} + {{- if .Values.additionalVolumeMounts }} + {{- toYaml .Values.additionalVolumeMounts | nindent 0 }} + {{- end }} -{{/* -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: hostpathmounts-{{ $name }} - mountPath: {{ $hpm.mountPath }} - {{ if $hpm.subPath }} - subPath: {{ $hpm.subPath }} - {{ end }} - {{ if $hpm.readOnly }} - readOnly: {{ $hpm.readOnly }} - {{ end }} -{{- end -}} -{{ end }} - -{{- if .Values.additionalVolumeMounts }} -{{- toYaml .Values.additionalVolumeMounts | nindent 0 }} -{{- end }} - -{{- if eq .Values.controllerType "statefulset" }} -{{- range $index, $vct := .Values.volumeClaimTemplates }} + {{- if eq .Values.controller.type "statefulset" }} + {{- range $index, $vct := .Values.volumeClaimTemplates }} - mountPath: {{ $vct.mountPath }} name: {{ $vct.name }} -{{- if $vct.subPath }} + {{- if $vct.subPath }} subPath: {{ $vct.subPath }} -{{- end }} -{{- end }} -{{- end }} + {{- end }} + {{- end }} + {{- end }} + {{/* Creates mountpoints to mount hostPaths directly to the container */}} + {{- range $name, $hpm := .Values.hostPathMounts }} + {{- if $hpm.enabled }} + {{- $name = default $name $hpm.name }} +- name: hostpathmounts-{{ $name }} + mountPath: {{ $hpm.mountPath }} + {{- if $hpm.subPath }} + subPath: {{ $hpm.subPath }} + {{- end }} + {{- if $hpm.readOnly }} + readOnly: {{ $hpm.readOnly }} + {{- end }} + {{- end }} + {{ end }} {{- end -}} diff --git a/charts/library/common/templates/lib/controller/_volumes.tpl b/charts/library/common/templates/lib/controller/_volumes.tpl index ccb602d00d7..f8cd0990c03 100644 --- a/charts/library/common/templates/lib/controller/_volumes.tpl +++ b/charts/library/common/templates/lib/controller/_volumes.tpl @@ -1,22 +1,3 @@ -{{/* -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. -*/}} - - {{/* Volumes included by the controller. */}} @@ -52,10 +33,8 @@ Volumes included by the controller. {{- /* Otherwise refer to the PVC name */}} {{- $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) -}} + {{- if not (eq $persistence.nameOverride "-") -}} + {{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $persistence.nameOverride) -}} {{- end -}} {{- else -}} {{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $index) -}} diff --git a/charts/library/common/tests/container_test.go b/charts/library/common/tests/container_test.go new file mode 100644 index 00000000000..1342a8e03bd --- /dev/null +++ b/charts/library/common/tests/container_test.go @@ -0,0 +1,346 @@ +package common + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/truecharts/apps/tests/helmunit" +) + +type ContainerTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *ContainerTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestContainer(t *testing.T) { + suite.Run(t, new(ContainerTestSuite)) +} + +func (suite *ContainerTestSuite) TestCommand() { + tests := map[string]struct { + values []string + expectedCommand []string + }{ + "Default": {values: nil, expectedCommand: nil}, + "SingleString": {values: []string{"command=/bin/sh"}, expectedCommand: []string{"/bin/sh"}}, + "StringList": {values: []string{"command={/bin/sh,-c}"}, expectedCommand: []string{"/bin/sh", "-c"}}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerCommand := containers[0].Path("command") + + if tc.expectedCommand == nil { + suite.Assertions.Empty(containerCommand) + } else { + var actualDataList []string + actualData, _ := containerCommand.Children() + for _, key := range actualData { + actualDataList = append(actualDataList, key.Data().(string)) + } + suite.Assertions.EqualValues(tc.expectedCommand, actualDataList) + } + }) + } +} + +func (suite *ContainerTestSuite) TestArgs() { + tests := map[string]struct { + values []string + expectedArgs []string + }{ + "Default": {values: nil, expectedArgs: nil}, + "SingleString": {values: []string{"args=sleep infinity"}, expectedArgs: []string{"sleep infinity"}}, + "StringList": {values: []string{"args={sleep,infinity}"}, expectedArgs: []string{"sleep", "infinity"}}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerArgs := containers[0].Path("args") + + if tc.expectedArgs == nil { + suite.Assertions.Empty(containerArgs) + } else { + var actualDataList []string + actualData, _ := containerArgs.Children() + for _, key := range actualData { + actualDataList = append(actualDataList, key.Data().(string)) + } + suite.Assertions.EqualValues(tc.expectedArgs, actualDataList) + } + }) + } +} + +func (suite *ContainerTestSuite) TestEnv() { + tests := map[string]struct { + values []string + expectedEnv map[string]string + }{ + "Default": {values: nil, expectedEnv: nil}, + "KeyValueString": {values: []string{"env.string=value_of_env"}, expectedEnv: map[string]string{"string": "value_of_env"}}, + "KeyValueFloat": {values: []string{"env.float=4.2"}, expectedEnv: map[string]string{"float": "4.2"}}, + "KeyValueBool": {values: []string{"env.bool=false"}, expectedEnv: map[string]string{"bool": "false"}}, + "KeyValueInt": {values: []string{"env.int=42"}, expectedEnv: map[string]string{"int": "42"}}, + "List": {values: []string{"env[0].name=STATIC_ENV_FROM_LIST", "env[0].value=STATIC_ENV_VALUE_FROM_LIST"}, expectedEnv: map[string]string{"STATIC_ENV_FROM_LIST": "STATIC_ENV_VALUE_FROM_LIST"}}, + "ValueFrom": {values: []string{"env[0].name=STATIC_ENV_FROM_LIST", "env[0].valueFrom.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"STATIC_ENV_FROM_LIST": "spec.nodeName"}}, + "KeyValue+ExplicitValueFrom": {values: []string{"env.STATIC_ENV=value_of_env", "env.STATIC_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"STATIC_ENV": "value_of_env", "STATIC_ENV_FROM": "spec.nodeName"}}, + "ImplicitValueFrom": {values: []string{"env.NODE_NAME.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"NODE_NAME": "spec.nodeName"}}, + "Templated": {values: []string{`env.DYN_ENV=\{\{ .Release.Name \}\}-admin`}, expectedEnv: map[string]string{"DYN_ENV": "common-test-admin"}}, + "Mixed": { + values: []string{ + `env.DYN_ENV=\{\{ .Release.Name \}\}-admin`, + "env.STATIC_ENV=value_of_env", + "env.STATIC_EXPLICIT_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName", + "env.STATIC_IMPLICIT_ENV_FROM.fieldRef.fieldPath=spec.nodeName", + }, + expectedEnv: map[string]string{ + "DYN_ENV": "common-test-admin", + "STATIC_ENV": "value_of_env", + "STATIC_EXPLICIT_ENV_FROM": "spec.nodeName", + "STATIC_IMPLICIT_ENV_FROM": "spec.nodeName", + }, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerEnv := containers[0].Path("env") + + if tc.expectedEnv == nil { + suite.Assertions.Empty(containerEnv) + } else { + actualDataMap := make(map[string]string) + actualData, _ := containerEnv.Children() + for _, value := range actualData { + envVar, _ := value.ChildrenMap() + envName := envVar["name"].Data().(string) + var envValue string + if _, ok := envVar["valueFrom"]; ok { + envValue = value.Path("valueFrom.fieldRef.fieldPath").Data().(string) + } else { + envValue = value.Path("value").Data().(string) + } + actualDataMap[envName] = envValue + } + suite.Assertions.EqualValues(tc.expectedEnv, actualDataMap) + } + }) + } +} + +func (suite *ContainerTestSuite) TestEnvFrom() { + tests := map[string]struct { + values []string + expectSecret bool + expectedSecretName string + }{ + "Default": {values: nil, expectSecret: false, expectedSecretName: ""}, + "FromSecret": {values: []string{"secret.STATIC_SECRET=value_of_secret"}, expectSecret: true, expectedSecretName: "common-test"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + secretManifest := suite.Chart.Manifests.Get("Secret", tc.expectedSecretName) + if tc.expectSecret { + suite.Assertions.NotEmpty(secretManifest) + } else { + suite.Assertions.Empty(secretManifest) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerEnvFrom, _ := containers[0].Path("envFrom").Children() + + if !tc.expectSecret { + suite.Assertions.Empty(containerEnvFrom) + } else { + suite.Assertions.EqualValues(tc.expectedSecretName, containerEnvFrom[0].Path("secretRef.name").Data().(string)) + } + }) + } +} + +func (suite *ContainerTestSuite) TestPorts() { + tests := map[string]struct { + values []string + expectedPortName string + expectedPort int + expectedProtocol string + }{ + "Default": {values: nil, expectedPortName: "http", expectedPort: 0, expectedProtocol: "TCP"}, + "CustomName": {values: []string{"service.main.ports.http.enabled=false", "service.main.ports.server.enabled=true", "service.main.ports.server.port=8080"}, expectedPortName: "server", expectedPort: 8080, expectedProtocol: "TCP"}, + "ProtocolHTTP": {values: []string{"service.main.ports.http.protocol=HTTP"}, expectedPortName: "http", expectedPort: 0, expectedProtocol: "TCP"}, + "ProtocolHTTPS": {values: []string{"service.main.ports.http.protocol=HTTP"}, expectedPortName: "http", expectedPort: 0, expectedProtocol: "TCP"}, + "ProtocolUDP": {values: []string{"service.main.ports.http.protocol=UDP"}, expectedPortName: "http", expectedPort: 0, expectedProtocol: "UDP"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerPorts, _ := containers[0].Path("ports").Children() + suite.Assertions.NotEmpty(containerPorts[0]) + suite.Assertions.EqualValues(tc.expectedPortName, containerPorts[0].Path("name").Data()) + suite.Assertions.EqualValues(tc.expectedProtocol, containerPorts[0].Path("protocol").Data()) + + if tc.expectedPort == 0 { + suite.Assertions.Empty(containerPorts[0].Path("containerPort").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedPort, containerPorts[0].Path("containerPort").Data()) + } + }) + } +} + +func (suite *ContainerTestSuite) TestPersistenceVolumeMounts() { + values := ` + persistence: + config: + enabled: true + cache: + enabled: true + emptyDir: + enabled: true + claimWithCustomMountPath: + enabled: true + mountPath: /custom + accessMode: ReadWriteMany + size: 1G + claimWithSubPath: + enabled: true + existingClaim: myClaim + subPath: "mySubPath" + ` + tests := map[string]struct { + values *string + volumeToTest string + expectedMountPath string + expectedSubPath string + }{ + "MountWithoutMountPath": {values: &values, volumeToTest: "config", expectedMountPath: "/config"}, + "EmptyDir": {values: &values, volumeToTest: "cache", expectedMountPath: "/cache"}, + "MountWithCustomMountPath": {values: &values, volumeToTest: "claimWithCustomMountPath", expectedMountPath: "/custom"}, + "MountWithSubPath": {values: &values, volumeToTest: "claimWithSubPath", expectedMountPath: "/claimWithSubPath", expectedSubPath: "mySubPath"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerVolumeMounts, _ := containers[0].Path("volumeMounts").Children() + suite.Assertions.NotEmpty(containerVolumeMounts) + + for _, volumeMount := range containerVolumeMounts { + volumeMountName := volumeMount.Path("name").Data().(string) + if volumeMountName == tc.volumeToTest { + suite.Assertions.EqualValues(tc.expectedMountPath, volumeMount.Path("mountPath").Data()) + + if tc.expectedSubPath == "" { + suite.Assertions.Empty(volumeMount.Path("subPath").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedSubPath, volumeMount.Path("subPath").Data()) + } + break + } + } + }) + } +} + +func (suite *ContainerTestSuite) TestPersistenceHostpathMounts() { + values := ` + hostPathMounts: + - name: data + enabled: true + mountPath: /data + hostPath: /tmp + - name: config + enabled: true + hostPath: /tmp + mountPath: /config + subPath: mySubPath + ` + tests := map[string]struct { + values *string + volumeToTest string + expectedMountPath string + expectedSubPath string + }{ + "WithMountPath": {values: &values, volumeToTest: "hostpathmounts-data", expectedMountPath: "/data"}, + "WithSubPath": {values: &values, volumeToTest: "hostpathmounts-config", expectedMountPath: "/config", expectedSubPath: "mySubPath"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children() + containerVolumeMounts, _ := containers[0].Path("volumeMounts").Children() + suite.Assertions.NotEmpty(containerVolumeMounts) + + for _, volumeMount := range containerVolumeMounts { + volumeMountName := volumeMount.Path("name").Data().(string) + if volumeMountName == tc.volumeToTest { + suite.Assertions.EqualValues(tc.expectedMountPath, volumeMount.Path("mountPath").Data()) + + if tc.expectedSubPath == "" { + suite.Assertions.Empty(volumeMount.Path("subPath").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedSubPath, volumeMount.Path("subPath").Data()) + } + break + } + } + }) + } +} diff --git a/charts/library/common/tests/controller_test.go b/charts/library/common/tests/controller_test.go new file mode 100644 index 00000000000..02ee6be8973 --- /dev/null +++ b/charts/library/common/tests/controller_test.go @@ -0,0 +1,59 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type ControllerTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *ControllerTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestController(t *testing.T) { + suite.Run(t, new(ControllerTestSuite)) +} + +func (suite *ControllerTestSuite) TestTypes() { + tests := map[string]struct { + values []string + expectedRenderFailure bool + expectedController string + }{ + "Default": {values: nil, expectedRenderFailure: false, expectedController: "deployment"}, + "DaemonSet": {values: []string{"controller.type=daemonset"}, expectedRenderFailure: false, expectedController: "daemonset"}, + "Deployment": {values: []string{"controller.type=deployment"}, expectedRenderFailure: false, expectedController: "deployment"}, + "StatefulSet": {values: []string{"controller.type=statefulset"}, expectedRenderFailure: false, expectedController: "statefulset"}, + "Custom": {values: []string{"controller.type=custom"}, expectedRenderFailure: true, expectedController: ""}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if tc.expectedRenderFailure { + suite.Assertions.Error(err) + return + } + if err != nil { + suite.FailNow(err.Error()) + } + + manifest := suite.Chart.Manifests.Get(tc.expectedController, "common-test") + suite.Assertions.NotEmpty(manifest) + + types := map[string]interface{}{"deployment": nil, "statefulset": nil, "daemonset": nil} + delete(types, tc.expectedController) + for k := range types { + suite.Assertions.Empty(suite.Chart.Manifests.Get(k, "common-test")) + } + }) + } +} diff --git a/charts/library/common/tests/horizontal_pod_autoscaler_test.go b/charts/library/common/tests/horizontal_pod_autoscaler_test.go new file mode 100644 index 00000000000..0fc5bed120c --- /dev/null +++ b/charts/library/common/tests/horizontal_pod_autoscaler_test.go @@ -0,0 +1,107 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type HorizontalPodAutoscalerTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *HorizontalPodAutoscalerTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestHorizontalPodAutoscaler(t *testing.T) { + suite.Run(t, new(HorizontalPodAutoscalerTestSuite)) +} + +func (suite *HorizontalPodAutoscalerTestSuite) TestValues() { + baseValues := []string{"autoscaling.enabled=true"} + tests := map[string]struct { + values []string + expectedHorizontalPodAutoscaler bool + expectedTarget string + expectedMinReplicas int + expectedMaxReplicas int + }{ + "Default": { + values: nil, + expectedHorizontalPodAutoscaler: false, + }, + "Enabled": { + values: baseValues, + expectedHorizontalPodAutoscaler: true, expectedTarget: "common-test", expectedMinReplicas: 1, expectedMaxReplicas: 3, + }, + "CustomSettings": { + values: append(baseValues, "autoscaling.target=common-custom", "autoscaling.minReplicas=4", "autoscaling.maxReplicas=8"), + expectedHorizontalPodAutoscaler: true, expectedTarget: "common-custom", expectedMinReplicas: 4, expectedMaxReplicas: 8, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + manifest := suite.Chart.Manifests.Get("HorizontalPodAutoscaler", "common-test") + if tc.expectedHorizontalPodAutoscaler { + suite.Assertions.NotEmpty(manifest) + suite.Assertions.EqualValues(tc.expectedTarget, manifest.Path("spec.scaleTargetRef.name").Data()) + suite.Assertions.EqualValues(tc.expectedMinReplicas, manifest.Path("spec.minReplicas").Data()) + suite.Assertions.EqualValues(tc.expectedMaxReplicas, manifest.Path("spec.maxReplicas").Data()) + } else { + suite.Assertions.Empty(manifest) + } + }) + } +} + +func (suite *HorizontalPodAutoscalerTestSuite) TestMetrics() { + baseValues := []string{"autoscaling.enabled=true"} + tests := map[string]struct { + values []string + expectedResources map[string]int + }{ + "targetCPUUtilizationPercentage": { + values: append(baseValues, "autoscaling.targetCPUUtilizationPercentage=60"), + expectedResources: map[string]int{"cpu": 60}, + }, + "targetMemoryUtilizationPercentage": { + values: append(baseValues, "autoscaling.targetMemoryUtilizationPercentage=70"), + expectedResources: map[string]int{"memory": 70}, + }, + "Combined": { + values: append(baseValues, "autoscaling.targetCPUUtilizationPercentage=60", "autoscaling.targetMemoryUtilizationPercentage=70"), + expectedResources: map[string]int{"cpu": 60, "memory": 70}, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + manifest := suite.Chart.Manifests.Get("HorizontalPodAutoscaler", "common-test") + suite.Assertions.NotEmpty(manifest) + + manifestMetrics, _ := manifest.Path("spec.metrics").Children() + + metricsMap := make(map[string]int) + for _, manifestMetric := range manifestMetrics { + metricsMap[manifestMetric.Path("resource.name").Data().(string)] = int(manifestMetric.Path("resource.targetAverageUtilization").Data().(float64)) + } + + suite.Assertions.EqualValues(tc.expectedResources, metricsMap) + }) + } +} diff --git a/charts/library/common/tests/ingress_test.go b/charts/library/common/tests/ingress_test.go new file mode 100644 index 00000000000..cd9edc00c88 --- /dev/null +++ b/charts/library/common/tests/ingress_test.go @@ -0,0 +1,222 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type IngressTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *IngressTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestIngress(t *testing.T) { + suite.Run(t, new(IngressTestSuite)) +} + +func (suite *IngressTestSuite) TestValues() { + tests := map[string]struct { + values []string + expectedIngress bool + expectedHostName string + expectedPath string + }{ + "Default": { + values: nil, + expectedIngress: false, + }, + "Disabled": { + values: []string{"ingress.main.enabled=false"}, + expectedIngress: false, + }, + "CustomHostAndPath": { + values: []string{ + "ingress.main.enabled=true", + "ingress.main.hosts[0].host=chart-test.local", + "ingress.main.hosts[0].paths[0].path=/test", + }, + expectedIngress: true, + expectedHostName: "chart-test.local", + expectedPath: "/test", + }, + "Multiple": { + values: []string{ + "ingress.main.enabled=true", + "ingress.secondary.enabled=true", + }, + expectedIngress: true, + }, + "PathTemplate": { + values: []string{ + "ingress.main.enabled=true", + "ingress.main.hosts[0].host=chart-example.local", + `ingress.main.hosts[0].paths[0].path=\{\{ .Release.Name \}\}.path`, + }, + expectedIngress: true, + expectedPath: "common-test.path", + }, + "HostTemplate": { + values: []string{ + "ingress.main.enabled=true", + `ingress.main.hosts[0].host=\{\{ .Release.Name \}\}.hostname`, + "ingress.main.hosts[0].paths[0].path=/", + }, + expectedIngress: true, + expectedHostName: "common-test.hostname", + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + ingressManifest := suite.Chart.Manifests.Get("Ingress", "common-test") + if tc.expectedIngress { + suite.Assertions.NotEmpty(ingressManifest) + + ingressRules, _ := ingressManifest.Path("spec.rules").Children() + if tc.expectedHostName != "" { + suite.Assertions.EqualValues(tc.expectedHostName, ingressRules[0].Path("host").Data()) + } + + if tc.expectedPath != "" { + paths, _ := ingressRules[0].Path("http.paths").Children() + suite.Assertions.EqualValues(tc.expectedPath, paths[0].Path("path").Data()) + } + } else { + suite.Assertions.Empty(ingressManifest) + } + }) + } +} + +func (suite *IngressTestSuite) TestPathServices() { + tests := map[string]struct { + values []string + expectedServiceName string + expectedServicePort int + }{ + "Default": { + values: []string{"ingress.main.enabled=true"}, + expectedServiceName: "common-test", + }, + "CustomService": { + values: []string{ + "service.main.ports.http.targetPort=80", + "ingress.main.enabled=true", + "ingress.main.hosts[0].host=test.local", + "ingress.main.hosts[0].paths[0].path=/second/", + "ingress.main.hosts[0].paths[0].service.name=pathService", + "ingress.main.hosts[0].paths[0].service.port=1234", + }, + expectedServiceName: "pathService", + expectedServicePort: 1234, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + ingressManifest := suite.Chart.Manifests.Get("Ingress", "common-test") + suite.Assertions.NotEmpty(ingressManifest) + + ingressRules, _ := ingressManifest.Path("spec.rules").Children() + paths, _ := ingressRules[0].Path("http.paths").Children() + primaryPath := paths[0] + + if tc.expectedServiceName == "" { + suite.Assertions.Empty(primaryPath.Path("backend.service.name").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedServiceName, primaryPath.Path("backend.service.name").Data()) + } + + if tc.expectedServicePort == 0 { + suite.Assertions.Empty(primaryPath.Path("backend.service.port.number").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedServicePort, primaryPath.Path("backend.service.port.number").Data()) + } + }) + } +} + +func (suite *IngressTestSuite) TestTLS() { + tests := map[string]struct { + values []string + expectedTLS bool + expectedHostName string + expectedSecretName string + }{ + "Default": { + values: nil, + expectedTLS: false, + }, + "Provided": { + values: []string{ + "ingress.main.enabled=true", + "ingress.main.tls[0].hosts[0]=hostname", + "ingress.main.tls[0].secretName=secret-name", + }, + expectedTLS: true, + expectedHostName: "hostname", + expectedSecretName: "secret-name", + }, + "NoSecret": { + values: []string{ + "ingress.main.enabled=true", + "ingress.main.tls[0].hosts[0]=hostname", + }, + expectedTLS: true, + expectedHostName: "hostname", + expectedSecretName: "", + }, + "SecretTemplate": { + values: []string{ + "ingress.main.enabled=true", + "ingress.main.tls[0].hosts[0]=hostname", + `ingress.main.tls[0].secretName=\{\{ .Release.Name \}\}-secret`, + }, + expectedTLS: true, + expectedHostName: "hostname", + expectedSecretName: "common-test-secret", + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + ingressManifest := suite.Chart.Manifests.Get("Ingress", "common-test") + + if tc.expectedTLS { + suite.Assertions.NotEmpty(ingressManifest.Path("spec.tls").Data()) + tlsSpec, _ := ingressManifest.Path("spec.tls").Children() + tlsHostsSpec, _ := tlsSpec[0].Path("hosts").Children() + suite.Assertions.EqualValues(tc.expectedHostName, tlsHostsSpec[0].Data()) + + if tc.expectedSecretName == "" { + suite.Assertions.Empty(tlsSpec[0].Path("secretName").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedSecretName, tlsSpec[0].Path("secretName").Data()) + } + } else { + suite.Assertions.Empty(ingressManifest.Path("spec.tls").Data()) + } + }) + } +} diff --git a/charts/library/common/tests/permissions_job_test.go b/charts/library/common/tests/permissions_job_test.go new file mode 100644 index 00000000000..3dc1b38e5bc --- /dev/null +++ b/charts/library/common/tests/permissions_job_test.go @@ -0,0 +1,216 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type PermissionsJobTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *PermissionsJobTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestPermissionsJob(t *testing.T) { + suite.Run(t, new(PermissionsJobTestSuite)) +} + +func (suite *PermissionsJobTestSuite) TestPresence() { + tests := map[string]struct { + values []string + expectedJob bool + }{ + "Default": { + values: nil, + expectedJob: false, + }, + "WithHostPathMount": { + values: []string{ + "hostPathMounts[0].name=data", + "hostPathMounts[0].enabled=true", + "hostPathMounts[0].mountPath=/data", + "hostPathMounts[0].hostPath=/tmp", + }, + expectedJob: true, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions") + if tc.expectedJob { + suite.Assertions.NotEmpty(jobManifest) + } else { + suite.Assertions.Empty(jobManifest) + } + }) + } +} + +func (suite *PermissionsJobTestSuite) TestVolumesAndMounts() { + tests := map[string]struct { + values []string + expectedVolumes []string + }{ + "Default": { + values: []string{ + "hostPathMounts[0].name=data", + "hostPathMounts[0].enabled=true", + "hostPathMounts[0].mountPath=/data", + "hostPathMounts[0].hostPath=/tmp", + }, + expectedVolumes: nil, + }, + "MultipleHostPathMounts": { + values: []string{ + "hostPathMounts[0].name=data", + "hostPathMounts[0].enabled=true", + "hostPathMounts[0].setPermissions=true", + "hostPathMounts[0].mountPath=/data", + "hostPathMounts[0].hostPath=/tmp", + "hostPathMounts[1].name=config", + "hostPathMounts[1].enabled=true", + "hostPathMounts[1].setPermissions=true", + "hostPathMounts[1].mountPath=/config", + "hostPathMounts[1].hostPath=/tmp", + }, + expectedVolumes: []string{"hostpathmounts-config", "hostpathmounts-data"}, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions") + suite.Assertions.NotEmpty(jobManifest) + + jobVolumes, _ := jobManifest.Path("spec.template.spec.volumes").Search("name").Children() + containers, _ := jobManifest.Path("spec.template.spec.containers").Children() + jobVolumeMounts, _ := containers[0].Path("volumeMounts").Search("name").Children() + if tc.expectedVolumes != nil { + actualVolumes := []string{} + actualVolumeMounts := []string{} + + for _, v := range jobVolumes { + actualVolumes = append(actualVolumes, v.Data().(string)) + } + for _, v := range jobVolumeMounts { + actualVolumeMounts = append(actualVolumeMounts, v.Data().(string)) + } + + suite.Assertions.EqualValues(tc.expectedVolumes, actualVolumeMounts) + suite.Assertions.EqualValues(tc.expectedVolumes, actualVolumes) + } else { + suite.Assertions.Empty(jobVolumes) + } + }) + } +} + +func (suite *PermissionsJobTestSuite) TestCommand() { + baseValues := []string{ + "hostPathMounts[0].name=data", + "hostPathMounts[0].enabled=true", + "hostPathMounts[0].setPermissions=true", + "hostPathMounts[0].mountPath=/data", + "hostPathMounts[0].hostPath=/tmp", + "hostPathMounts[1].name=config", + "hostPathMounts[1].enabled=true", + "hostPathMounts[1].setPermissions=true", + "hostPathMounts[1].mountPath=/config", + "hostPathMounts[1].hostPath=/tmp", + } + tests := map[string]struct { + values []string + expectedCommand []string + }{ + "DefaultPermissionsForMultipleMounts": { + values: baseValues, + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 568:568 /config\nchown -R 568:568 /data\n", + }, + }, + "DefaultPermissionsForDisabledpodSecurityContext": { + values: append(baseValues, + "podSecurityContext.allowPrivilegeEscalation=false", + ), + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 568:568 /config\nchown -R 568:568 /data\n", + }, + }, + "PermissionsForFsGroup": { + values: append(baseValues, + "podSecurityContext.fsGroup=666", + ), + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 568:666 /config\nchown -R 568:666 /data\n", + }, + }, + "PermissionsForRunAsUser": { + values: append(baseValues, + "podSecurityContext.runAsUser=999", + ), + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 999:568 /config\nchown -R 999:568 /data\n", + }, + }, + "PermissionsForRunAsUserAndFsGroup": { + values: append(baseValues, + "podSecurityContext.runAsUser=999", + "podSecurityContext.fsGroup=666", + ), + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 999:666 /config\nchown -R 999:666 /data\n", + }, + }, + "PermissionsForPgidPuid": { + values: append(baseValues, + "env.PUID=999", + "env.PGID=666", + ), + expectedCommand: []string{ + "/bin/sh", "-c", "chown -R 999:666 /config\nchown -R 999:666 /data\n", + }, + }, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions") + suite.Assertions.NotEmpty(jobManifest) + + containers, _ := jobManifest.Path("spec.template.spec.containers").Children() + command, _ := containers[0].Path("command").Children() + if tc.expectedCommand != nil { + actualCommand := []string{} + + for _, v := range command { + actualCommand = append(actualCommand, v.Data().(string)) + } + + suite.Assertions.EqualValues(tc.expectedCommand, actualCommand) + } else { + suite.Assertions.Empty(command) + } + }) + } +} diff --git a/charts/library/common/tests/persistentvolumeclaim_test.go b/charts/library/common/tests/persistentvolumeclaim_test.go new file mode 100644 index 00000000000..f698aa1137f --- /dev/null +++ b/charts/library/common/tests/persistentvolumeclaim_test.go @@ -0,0 +1,75 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type PersistenceVolumeClaimTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *PersistenceVolumeClaimTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestPersistenceVolumeClaim(t *testing.T) { + suite.Run(t, new(PersistenceVolumeClaimTestSuite)) +} + +func (suite *PersistenceVolumeClaimTestSuite) TestName() { + tests := map[string]struct { + values []string + expectedName string + }{ + "Default": {values: []string{"persistence.config.enabled=true"}, expectedName: "common-test-config"}, + "WithoutSuffix": {values: []string{"persistence.config.enabled=true", "persistence.config.nameOverride=-"}, expectedName: "common-test"}, + "WithNameOverride": {values: []string{"persistence.config.enabled=true", "persistence.config.nameOverride=custom"}, expectedName: "common-test-custom"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + pvcManifest := suite.Chart.Manifests.Get("PersistentVolumeClaim", tc.expectedName) + suite.Assertions.NotEmpty(pvcManifest) + }) + } +} + +func (suite *PersistenceVolumeClaimTestSuite) TestStorageClass() { + tests := map[string]struct { + values []string + expectedStorageClass string + }{ + "Default": {values: []string{"persistence.config.enabled=true"}, expectedStorageClass: "-"}, + "CustomClass": {values: []string{"persistence.config.enabled=true", "persistence.config.storageClass=custom"}, expectedStorageClass: "custom"}, + "ScaleZFS": {values: []string{"persistence.config.enabled=true", "persistence.config.storageClass=SCALE-ZFS"}, expectedStorageClass: "ix-storage-class-common-test"}, + "Empty": {values: []string{"persistence.config.enabled=true", "persistence.config.storageClass=-"}, expectedStorageClass: ""}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + pvcManifest := suite.Chart.Manifests.Get("PersistentVolumeClaim", "common-test-config") + suite.Assertions.NotEmpty(pvcManifest) + + if tc.expectedStorageClass == "-" { + suite.Assertions.Empty(pvcManifest.Path("spec.storageClassName").Data()) + } else { + suite.Assertions.EqualValues(tc.expectedStorageClass, pvcManifest.Path("spec.storageClassName").Data()) + } + }) + } +} diff --git a/charts/library/common/tests/pod_test.go b/charts/library/common/tests/pod_test.go new file mode 100644 index 00000000000..7a60a0b07de --- /dev/null +++ b/charts/library/common/tests/pod_test.go @@ -0,0 +1,407 @@ +package common + +import ( + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type PodTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *PodTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestPod(t *testing.T) { + suite.Run(t, new(PodTestSuite)) +} + +func (suite *PodTestSuite) TestReplicas() { + tests := map[string]struct { + values []string + expectedValue interface{} + }{ + "Default": {values: nil, expectedValue: 1}, + "Specified": {values: []string{"controller.replicas=3"}, expectedValue: 3}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + suite.Assertions.EqualValues(tc.expectedValue, deploymentManifest.Path("spec.replicas").Data()) + }) + } +} + +func (suite *PodTestSuite) TestHostNetwork() { + tests := map[string]struct { + values []string + expectedValue interface{} + }{ + "Default": {values: nil, expectedValue: nil}, + "SpecifiedTrue": {values: []string{"hostNetwork=true"}, expectedValue: true}, + "SpecifiedFalse": {values: []string{"hostNetwork=false"}, expectedValue: nil}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + suite.Assertions.EqualValues(tc.expectedValue, deploymentManifest.Path("spec.template.spec.hostNetwork").Data()) + }) + } +} + +func (suite *PodTestSuite) TestDnsPolicy() { + tests := map[string]struct { + values []string + expectedValue interface{} + }{ + "Default": {values: nil, expectedValue: "ClusterFirst"}, + "HostnetworkFalse": {values: []string{"hostNetwork=false"}, expectedValue: "ClusterFirst"}, + "HostnetworkTrue": {values: []string{"hostNetwork=true"}, expectedValue: "ClusterFirstWithHostNet"}, + "ManualOverride": {values: []string{"dnsPolicy=None"}, expectedValue: "None"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + suite.Assertions.NotEmpty(deploymentManifest) + suite.Assertions.EqualValues(tc.expectedValue, deploymentManifest.Path("spec.template.spec.dnsPolicy").Data()) + }) + } +} + +func (suite *PodTestSuite) TestAdditionalContainers() { + tests := map[string]struct { + values []string + expectedContainer interface{} + }{ + "Static": {values: []string{"additionalContainers[0].name=template-test"}, expectedContainer: "template-test"}, + "DynamicTemplate": {values: []string{`additionalContainers[0].name=\{\{ .Release.Name \}\}-container`}, expectedContainer: "common-test-container"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + containers := deploymentManifest.Path("spec.template.spec.containers") + suite.Assertions.Contains(containers.Search("name").Data(), tc.expectedContainer) + }) + } +} +func (suite *PodTestSuite) TestPersistenceItems() { + values := ` + persistence: + cache: + enabled: true + emptyDir: + enabled: true + config: + enabled: true + emptyDir: + enabled: false + data: + enabled: true + existingClaim: dataClaim + ` + + tests := map[string]struct { + values *string + expectedVolumes []string + }{ + "Default": {values: nil, expectedVolumes: nil}, + "MultipleItems": {values: &values, expectedVolumes: []string{"config", "cache", "data"}}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + volumes := deploymentManifest.Path("spec.template.spec.volumes") + + if tc.expectedVolumes == nil { + suite.Assertions.EqualValues(nil, volumes.Data()) + } else { + suite.Assertions.NotEmpty(volumes) + searchVolumes := volumes.Search("name").Data() + for _, expectedVolume := range tc.expectedVolumes { + suite.Assertions.Contains(searchVolumes, expectedVolume) + } + } + }) + } +} + +func (suite *PodTestSuite) TestPersistenceClaimNames() { + values := ` + persistence: + config: + enabled: true + existingClaim: + enabled: true + existingClaim: myClaim + claimWithoutSuffix: + enabled: true + nameOverride: "-" + accessMode: ReadWriteMany + size: 1G + claimWithNameOverride: + enabled: true + nameOverride: suffix + accessMode: ReadWriteMany + size: 1G + ` + tests := map[string]struct { + values *string + volumeToTest string + expectedClaimName string + }{ + "DefaultClaimName": {values: &values, volumeToTest: "config", expectedClaimName: "common-test-config"}, + "ClaimNameWithoutSuffix": {values: &values, volumeToTest: "claimWithoutSuffix", expectedClaimName: "common-test"}, + "ClaimNameWithNameOverride": {values: &values, volumeToTest: "claimWithNameOverride", expectedClaimName: "common-test-suffix"}, + "ExistingClaim": {values: &values, volumeToTest: "existingClaim", expectedClaimName: "myClaim"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + volumes, _ := deploymentManifest.Path("spec.template.spec.volumes").Children() + + for _, volume := range volumes { + volumeName := volume.Path("name").Data().(string) + if volumeName == tc.volumeToTest { + suite.Assertions.EqualValues(tc.expectedClaimName, volume.Path("persistentVolumeClaim.claimName").Data()) + break + } + } + }) + } +} + +func (suite *PodTestSuite) TestPersistenceEmptyDir() { + baseValues := ` + persistence: + config: + enabled: true + emptyDir: + enabled: true + ` + tests := map[string]struct { + values []string + expectedMedium string + expectedSizeLimit string + }{ + "Enabled": {values: nil, expectedMedium: "", expectedSizeLimit: ""}, + "WithMedium": {values: []string{"persistence.config.emptyDir.medium=memory"}, expectedMedium: "memory", expectedSizeLimit: ""}, + "WithSizeLimit": {values: []string{"persistence.config.emptyDir.medium=memory", "persistence.config.emptyDir.sizeLimit=1Gi"}, expectedMedium: "memory", expectedSizeLimit: "1Gi"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, &baseValues) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + volumes, _ := deploymentManifest.Path("spec.template.spec.volumes").Children() + volume := volumes[0] + suite.Assertions.NotEmpty(volume.Data()) + + if tc.expectedMedium == "" { + suite.Assertions.Nil(volume.Path("emptyDir.medium")) + } else { + suite.Assertions.EqualValues(tc.expectedMedium, volume.Path("emptyDir.medium").Data()) + } + + if tc.expectedSizeLimit == "" { + suite.Assertions.Nil(volume.Path("emptyDir.sizeLimit")) + } else { + suite.Assertions.EqualValues(tc.expectedSizeLimit, volume.Path("emptyDir.sizeLimit").Data()) + } + + }) + } +} + +func (suite *PodTestSuite) TestHostPathVolumes() { + values := ` + hostPathMounts: + - name: data + enabled: true + mountPath: "/data" + hostPath: "/tmp1" + - name: config + enabled: true + emptyDir: true + mountPath: "/data" + ` + tests := map[string]struct { + values *string + expectedVolumes []string + }{ + "Default": {values: nil, expectedVolumes: nil}, + "MultipleItems": {values: &values, expectedVolumes: []string{"hostpathmounts-data", "hostpathmounts-config"}}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + volumes := deploymentManifest.Path("spec.template.spec.volumes") + + if tc.expectedVolumes == nil { + suite.Assertions.EqualValues(nil, volumes.Data()) + } else { + suite.Assertions.NotEmpty(volumes) + searchVolumes := volumes.Search("name").Data() + for _, expectedVolume := range tc.expectedVolumes { + suite.Assertions.Contains(searchVolumes, expectedVolume) + } + } + }) + } +} + +func (suite *PodTestSuite) TestHostPathVolumePaths() { + values := ` + hostPathMounts: + - name: data + enabled: true + mountPath: "/data" + hostPath: "/tmp1" + - name: config + enabled: true + emptyDir: true + mountPath: "/data" + ` + tests := map[string]struct { + values *string + volumeToTest string + expectedPath string + emptyDir bool + }{ + "HostPath": {values: &values, volumeToTest: "hostpathmounts-data", expectedPath: "/tmp1", emptyDir: false}, + "EmptyDir": {values: &values, volumeToTest: "hostpathmounts-config", expectedPath: "", emptyDir: true}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, nil, tc.values) + if err != nil { + suite.FailNow(err.Error()) + } + + deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test") + volumes, _ := deploymentManifest.Path("spec.template.spec.volumes").Children() + + for _, volume := range volumes { + volumeName := volume.Path("name").Data().(string) + if volumeName == tc.volumeToTest { + if tc.expectedPath == "" { + suite.Assertions.Nil(volume.Path("hostPath.path")) + } else { + suite.Assertions.EqualValues(tc.expectedPath, volume.Path("hostPath.path").Data()) + } + + if tc.emptyDir == false { + suite.Assertions.Nil(volume.Path("emptyDir")) + } else { + suite.Assertions.NotNil(volume.Path("emptyDir")) + } + break + } + } + }) + } +} + +func (suite *PodTestSuite) TestVolumeClaimTemplates() { + values := ` + volumeClaimTemplates: + - name: 'storage' + accessMode: 'ReadWriteOnce' + size: '10Gi' + storageClass: 'storage' + ` + tests := map[string]struct { + values []string + volumeClaimToTest string + expectedAccessMode string + expectedSize string + expectedStorageClassName string + }{ + "StatefulSet": {values: []string{"controller.type=statefulset"}, volumeClaimToTest: "storage", expectedAccessMode: "ReadWriteOnce", expectedSize: "10Gi", expectedStorageClassName: "storage"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, &values) + if err != nil { + suite.FailNow(err.Error()) + } + + controllerManifest := suite.Chart.Manifests.Get("StatefulSet", "common-test") + suite.Assertions.NotEmpty(controllerManifest) + + volumeClaimTemplates, _ := controllerManifest.Path("spec.volumeClaimTemplates").Children() + suite.Assertions.NotEmpty(volumeClaimTemplates) + + for _, volumeClaimTemplate := range volumeClaimTemplates { + volumeClaimName := volumeClaimTemplate.Path("metadata.name").Data() + if volumeClaimName == tc.volumeClaimToTest { + if tc.expectedAccessMode == "" { + suite.Assertions.Empty(controllerManifest) + } else { + accessModes, _ := volumeClaimTemplate.Path("spec.accessModes").Children() + suite.Assertions.EqualValues(tc.expectedAccessMode, accessModes[0].Data()) + } + + if tc.expectedSize == "" { + suite.Assertions.Empty(controllerManifest) + } else { + suite.Assertions.EqualValues(tc.expectedSize, volumeClaimTemplate.Path("spec.resources.requests.storage").Data()) + } + + if tc.expectedStorageClassName == "" { + suite.Assertions.Empty(controllerManifest) + } else { + suite.Assertions.EqualValues(tc.expectedStorageClassName, volumeClaimTemplate.Path("spec.storageClassName").Data()) + } + break + } + } + }) + } +} diff --git a/charts/library/common/tests/service_test.go b/charts/library/common/tests/service_test.go new file mode 100644 index 00000000000..13a31a96c64 --- /dev/null +++ b/charts/library/common/tests/service_test.go @@ -0,0 +1,138 @@ +package common + +import ( + "fmt" + "testing" + + "github.com/truecharts/apps/tests/helmunit" + "github.com/stretchr/testify/suite" +) + +type ServiceTestSuite struct { + suite.Suite + Chart helmunit.HelmChart +} + +func (suite *ServiceTestSuite) SetupSuite() { + suite.Chart = helmunit.New("common-test", "../../common-test") + suite.Chart.UpdateDependencies() +} + +// We need this function to kick off the test suite, otherwise +// "go test" won't know about our tests +func TestService(t *testing.T) { + suite.Run(t, new(ServiceTestSuite)) +} + +func (suite *ServiceTestSuite) TestServiceName() { + tests := map[string]struct { + values []string + expectedName string + }{ + "Default": {values: nil, expectedName: "common-test"}, + "CustomName": {values: []string{"service.main.nameOverride=http"}, expectedName: "common-test-http"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + serviceManifest := suite.Chart.Manifests.Get("Service", tc.expectedName) + suite.Assertions.NotEmpty(serviceManifest) + }) + } +} + +func (suite *ServiceTestSuite) TestPortNames() { + tests := map[string]struct { + values []string + expectedRenderFailure bool + expectedName string + expectedTargetPort interface{} + }{ + "Default": {values: nil, expectedRenderFailure: false, expectedName: "http", expectedTargetPort: "http"}, + "CustomName": {values: []string{"service.main.ports.http.enabled=false", "service.main.ports.server.enabled=true", "service.main.ports.server.port=8080"}, expectedRenderFailure: false, expectedName: "server", expectedTargetPort: "server"}, + "CustomTargetPort": {values: []string{"service.main.ports.http.targetPort=80"}, expectedRenderFailure: false, expectedName: "http", expectedTargetPort: 80}, + "NamedTargetPort": {values: []string{"service.main.ports.http.targetPort=name"}, expectedRenderFailure: true, expectedName: "", expectedTargetPort: nil}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if tc.expectedRenderFailure { + suite.Assertions.Error(err) + return + } + if err != nil { + suite.FailNow(err.Error()) + } + + serviceManifest := suite.Chart.Manifests.Get("Service", "common-test") + suite.Assertions.NotEmpty(serviceManifest) + servicePorts, _ := serviceManifest.Path("spec.ports").Children() + suite.Assertions.EqualValues(tc.expectedName, servicePorts[0].Path("name").Data()) + suite.Assertions.EqualValues(tc.expectedTargetPort, servicePorts[0].Path("targetPort").Data()) + }) + } +} + +func (suite *ServiceTestSuite) TestPortProtocol() { + tests := map[string]struct { + values []string + expectedProtocol string + }{ + "Default": {values: nil, expectedProtocol: "TCP"}, + "ExplicitTCP": {values: []string{"service.main.ports.http.protocol=TCP"}, expectedProtocol: "TCP"}, + "ExplicitHTTP": {values: []string{"service.main.ports.http.protocol=HTTP"}, expectedProtocol: "TCP"}, + "ExplicitHTTPS": {values: []string{"service.main.ports.http.protocol=HTTPS"}, expectedProtocol: "TCP"}, + "ExplicitUDP": {values: []string{"service.main.ports.http.protocol=UDP"}, expectedProtocol: "UDP"}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + serviceManifest := suite.Chart.Manifests.Get("Service", "common-test") + suite.Assertions.NotEmpty(serviceManifest) + servicePorts, _ := serviceManifest.Path("spec.ports").Children() + suite.Assertions.EqualValues(tc.expectedProtocol, servicePorts[0].Path("protocol").Data()) + }) + } +} + +func (suite *ServiceTestSuite) TestAnnotations() { + tests := map[string]struct { + values []string + expectedAnnotations map[string]string + }{ + "Default": {values: nil, expectedAnnotations: nil}, + "ExplicitTCP": {values: []string{"service.main.ports.http.protocol=TCP"}, expectedAnnotations: nil}, + "ExplicitHTTP": {values: []string{"service.main.ports.http.protocol=HTTP"}, expectedAnnotations: nil}, + "ExplicitHTTPS": {values: []string{"service.main.ports.http.protocol=HTTPS"}, expectedAnnotations: map[string]string{"traefik.ingress.kubernetes.io/service.serversscheme": "https"}}, + "ExplicitUDP": {values: []string{"service.main.ports.http.protocol=UDP"}, expectedAnnotations: nil}, + } + for name, tc := range tests { + suite.Suite.Run(name, func() { + err := suite.Chart.Render(nil, tc.values, nil) + if err != nil { + suite.FailNow(err.Error()) + } + + serviceManifest := suite.Chart.Manifests.Get("Service", "common-test") + suite.Assertions.NotEmpty(serviceManifest) + serviceAnnotations, _ := serviceManifest.Path("metadata.annotations").Children() + if tc.expectedAnnotations == nil { + suite.Assertions.Empty(serviceAnnotations) + } else { + for annotation, value := range tc.expectedAnnotations { + serviceAnnotation := serviceManifest.Path("metadata.annotations").Search(annotation) + suite.Assertions.NotEmpty(serviceAnnotation, fmt.Sprintf("Annotation %s not found", annotation)) + suite.Assertions.EqualValues(value, serviceAnnotation.Data(), fmt.Sprintf("Invalid value for annotation %s", annotation)) + } + } + }) + } +} diff --git a/charts/library/common/values.yaml b/charts/library/common/values.yaml index 0b2c1332d8e..224d9dbc931 100644 --- a/charts/library/common/values.yaml +++ b/charts/library/common/values.yaml @@ -1,41 +1,89 @@ -# type: options are deployment, daemonset or statefulset -controllerType: deployment -# Set annotations on the deployment/statefulset/daemonset -controllerAnnotations: {} -# Set labels on the deployment/statefulset/daemonset -controllerLabels: {} +global: + # -- Set an override for the prefix of the fullname + nameOverride: + # -- Set the entire name definition + fullnameOverride: -replicas: 1 -strategy: - ## For Deployments, valid values are Recreate and RollingUpdate - ## For StatefulSets, valid values are OnDelete and RollingUpdate - ## DaemonSets ignore this - type: RollingUpdate +controller: + # -- Set the controller type. + # Valid options are deployment, daemonset or statefulset + type: deployment + # -- Set annotations on the deployment/statefulset/daemonset + annotations: {} + # -- Set labels on the deployment/statefulset/daemonset + labels: {} + # -- Number of desired pods + replicas: 1 + # -- Set the controller upgrade strategy + # For Deployments, valid values are Recreate (default) and RollingUpdate. + # For StatefulSets, valid values are OnDelete and RollingUpdate (default). + # DaemonSets ignore this. + strategy: + rollingUpdate: + # -- Set deployment RollingUpdate max unavailable + unavailable: + # -- Set deployment RollingUpdate max surge + surge: + # -- Set statefulset RollingUpdate partition + partition: + # -- ReplicaSet revision history limit + revisionHistoryLimit: 3 -# Override the default command +image: + # -- image repository + repository: + # -- image tag + tag: + # -- image pull policy + pullPolicy: + +# -- Override the command(s) for the default container command: [] -# Override the default args +# -- Override the args for the default container args: [] -nameOverride: "" -fullnameOverride: "" - -# Set annotations on the pod +# -- Set annotations on the pod podAnnotations: {} +# -- Add a Horizontal Pod Autoscaler +# @default -- +autoscaling: + enabled: false + target: # deploymentname + minReplicas: # 1 + maxReplicas: # 100 + targetCPUUtilizationPercentage: # 80 + targetMemoryUtilizationPercentage: # 80 + serviceAccount: - # Specifies whether a service account should be created + # -- Specifies whether a service account should be created create: false - # Annotations to add to the service account + + # -- Annotations to add to the service account annotations: {} - # The name of the service account to use. + + # -- The name of the service account to use. # If not set and create is true, a name is generated using the fullname template name: "" +# -- Use this to populate a secret with the values you specify. +# Be aware that these values are not encrypted by default, and could therefore visible +# to anybody with access to the values.yaml file. +secret: {} + # PASSWORD: my-password +# -- Main environment variables. Template enabled. +# Syntax options: +# A) TZ: UTC +# B) PASSWD: '{{ .Release.Name }}' +# C) PASSWD: +# envFrom: +# ... +# D) - name: TZ +# value: UTC +# E) - name: TZ +# value: '{{ .Release.Name }}' env: {} - # TZ: UTC - ## Variables with values set from templates, example ## With a release name of: demo, the example env value will be: demo-admin envTpl: {} @@ -53,170 +101,274 @@ envFrom: [] # name: config-map-name # - secretRef: # name: secret-name +# -- Custom priority class for different treatment by the scheduler +priorityClassName: # system-node-critical -# Custom priority class for different treatment by the scheduler -# priorityClassName: system-node-critical +# -- Allows specifying a custom scheduler name +schedulerName: # awkward-dangerous-scheduler -# Allow specifying a custom scheduler name -# schedulerName: awkward-dangerous-scheduler +# -- Allows specifying explicit hostname setting +hostname: -# Allow specifying explicit hostname setting -# hostname: - -# When using hostNetwork make sure you set dnsPolicy to ClusterFirstWithHostNet +# -- When using hostNetwork make sure you set dnsPolicy to `ClusterFirstWithHostNet` hostNetwork: false -## Default get based on hostNetwork setting -# dnsPolicy: ClusterFirst +# -- Defaults to "ClusterFirst" if hostNetwork is false and "ClusterFirstWithHostNet" if hostNetwork is true. +dnsPolicy: # ClusterFirst -# Optional DNS settings, configuring the ndots option may resolve -# nslookup issues on some Kubernetes setups. -# dnsConfig: +# -- Optional DNS settings, configuring the ndots option may resolve nslookup issues on some Kubernetes setups. +dnsConfig: {} # options: # - name: ndots # value: "1" -# Enable/disable the generation of environment variables for services. -# See https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#accessing-the-service -# for more information. +# -- Enable/disable the generation of environment variables for services. +# [[ref]](https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#accessing-the-service) enableServiceLinks: true -# Configure the Security Context for the Pod -# podSecurityContext: -# runAsNonRoot: true -# runAsUser: 568 -# runAsGroup: 568 -# fsGroup: 568 -# fsGroupChangePolicy: "OnRootMismatch" +# -- Configure the Security Context for the Pod +podSecurityContext: {} -# Configure the Security Context for the main container +# -- Configure the Security Context for the main container securityContext: {} +# -- Configure the lifecycle for the main container +lifecycle: {} +# -- Specify any initContainers here. Yaml will be passed in to the Pod as-is. initContainers: [] +# -- Specify any additional containers here. Yaml will be passed in to the Pod as-is. additionalContainers: [] -## Probes configuration +# -- Probe configuration +# -- [[ref]](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) +# @default -- See below probes: + # -- Liveness probe configuration + # @default -- See below liveness: + # -- Enable the liveness probe enabled: true - ## Set this to true if you wish to specify your own livenessProbe + # -- Set this to `true` if you wish to specify your own livenessProbe custom: false - ## The spec field contains the values for the default livenessProbe. - ## If you selected custom: true, this field holds the definition of the livenessProbe. + # -- The spec field contains the values for the default livenessProbe. + # If you selected `custom: true`, this field holds the definition of the livenessProbe. + # @default -- See below spec: initialDelaySeconds: 0 periodSeconds: 10 - timeoutSeconds: 10 - failureThreshold: 5 + timeoutSeconds: 1 + failureThreshold: 3 + # -- Redainess probe configuration + # @default -- See below readiness: + # -- Enable the readiness probe enabled: true - ## Set this to true if you wish to specify your own readinessProbe + # -- Set this to `true` if you wish to specify your own readinessProbe custom: false - ## The spec field contains the values for the default readinessProbe. - ## If you selected custom: true, this field holds the definition of the readinessProbe. + # -- The spec field contains the values for the default readinessProbe. + # If you selected `custom: true`, this field holds the definition of the readinessProbe. + # @default -- See below spec: initialDelaySeconds: 0 periodSeconds: 10 - timeoutSeconds: 10 - failureThreshold: 5 + timeoutSeconds: 1 + failureThreshold: 3 + # -- Startup probe configuration + # @default -- See below startup: + # -- Enable the startup probe enabled: true - ## Set this to true if you wish to specify your own startupProbe + # -- Set this to `true` if you wish to specify your own startupProbe custom: false - ## The spec field contains the values for the default startupProbe. - ## If you selected custom: true, this field holds the definition of the startupProbe. + # -- The spec field contains the values for the default startupProbe. + # If you selected `custom: true`, this field holds the definition of the startupProbe. + # @default -- See below spec: initialDelaySeconds: 0 - timeoutSeconds: 10 + timeoutSeconds: 1 ## This means it has a maximum of 5*30=150 seconds to start up before it fails - periodSeconds: 10 + periodSeconds: 5 failureThreshold: 30 -services: +# -- Configure the services for the chart here. +# Additional services can be added by adding a dictionary key similar to the 'main' service. +# @default -- See below +service: main: + # -- Enables or disables the service 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: - ## 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. - targetPort: - ## Specify the nodePort value for the LoadBalancer and NodePort service types. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport - ## - # nodePort: - additionalPorts: [] - ## Provide any additional annotations which may be required. This can be used to - ## set the LoadBalancer service type to internal only. - ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer - ## + # -- Make this the primary service (used in probes, notes, etc...). + # If there is more than 1 service, make sure that only 1 service is marked as primary. + primary: true + + # -- Override the name suffix that is used for this service + nameOverride: + + # -- Set the service type + type: ClusterIP + + # -- Provide additional annotations which may be required. annotations: {} + + # -- Provide additional labels which may be required. labels: {} - ## 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: {} + # -- Configure the Service port information here. + # Additional ports can be added by adding a dictionary key similar to the 'http' service. + # @default -- See below + ports: + http: + # -- Enables or disables the port + enabled: true -persistence: - config: + # -- Make this the primary port (used in probes, notes, etc...) + # If there is more than 1 service, make sure that only 1 port is marked as primary. + primary: true + + # -- The port number + port: + + # -- Port protocol. + # Support values are `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 + # the `port` value. Therefore named ports are not supported for this field. + targetPort: + + # -- Specify the nodePort value for the LoadBalancer and NodePort service types. + # [[ref]](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) + nodePort: + +# -- Configure the ingresses for the chart here. +# Additional ingresses can be added by adding a dictionary key similar to the 'main' ingress. +# @default -- See below +ingress: + main: + # -- Enables or disables the ingress enabled: false + + # -- Make this the primary ingress (used in probes, notes, etc...). + # If there is more than 1 ingress, make sure that only 1 ingress is marked as primary. + primary: true + + # -- Override the name suffix that is used for this ingress. + nameOverride: + + # -- Provide additional annotations which may be required. + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + + # -- Provide additional labels which may be required. + labels: {} + + # -- Set the ingressClass that is used for this ingress. + # Requires Kubernetes >=1.19 + ingressClassName: # "nginx" + + ## Configure the hosts for the ingress + hosts: + - # -- Host address. Helm template can be passed. + host: chart-example.local + ## Configure the paths for the host + paths: + - # -- Path. Helm template can be passed. + path: / + # -- Ignored if not kubeVersion >= 1.14-0 + pathType: Prefix + service: + # -- Overrides the service name reference for this path + name: + # -- Overrides the service port reference for this path + port: + + # -- Configure TLS for the ingress. Both secretName and hosts can process a Helm template. + tls: [] + # - secretName: chart-example-tls + # -- Create a secret from a GUI selected TrueNAS SCALE certificate + # scaleCert: true + # hosts: + # - chart-example.local + +# -- Configure the persistent volumes for the chart here. +# Additional items can be added by adding a dictionary key similar to the 'config' key. +# @default -- See below +persistence: + # -- Default persistence for configuration files. + # @default -- See below + config: + # -- Enables or disables the persistent volume + enabled: false + + # -- Where to mount the volume in the main container. mountPath: /config - ## configuration data Persistent Volume Storage Class - ## If defined, storageClassName: - ## If set to "-", storageClassName: "", which disables dynamic provisioning - ## If undefined (the default) or set to null, no storageClassName spec is - ## set, choosing the default provisioner. (gp2 on AWS, standard on - ## GKE, AWS & OpenStack) - ## - # storageClass: "-" - ## - ## If you want to reuse an existing claim, you can pass the name of the PVC using - ## the existingClaim variable - # existingClaim: your-claim - # subPath: some-subpath + + # -- Override the name suffix that is used for this volume. + nameOverride: + + emptyDir: + # -- Create an emptyDir volume instead of a persistent volume. + # [[ref]] (https://kubernetes.io/docs/concepts/storage/volumes/#emptydir) + enabled: false + + # -- Storage Class for the config volume. + # If set to `-`, dynamic provisioning is disabled. + # If set to `SCALE-ZFS`, the default provisioner for TrueNAS SCALE is used. + # If set to something else, the given storageClass is used. + # If undefined (the default) or set to null, no storageClassName spec is set, choosing the default provisioner. + storageClass: # "-" + + # -- If you want to reuse an existing claim, the name of the existing PVC can be passed here. + existingClaim: # your-claim + + # -- Used in conjunction with `existingClaim`. Specifies a sub-path inside the referenced volume instead of its root + subPath: # some-subpath + + # -- AccessMode for the persistent volume. + # Make sure to select an access mode that is supported by your storage provider! + # [[ref]](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#access-modes) accessMode: ReadWriteOnce + + # -- The amount of storage that is requested for the persistent volume. size: 1Gi - ## Set to true to retain the PVC upon helm uninstall + + # - Set to true to retain the PVC upon `helm uninstall` skipuninstall: false - # Create an emptyDir volume to share between all containers shared: + # -- Create an emptyDir volume to share between all containers enabled: false emptyDir: enabled: true + # -- Where to mount the shared volume in the main container. mountPath: /shared +# -- Mount a path on the host to the main container. +hostPathMounts: [] + # - name: "data" + # enabled: false + # emptyDir: false + # mountPath: "/data" + # subPath: some-subpath + # hostPath: "" + # readOnly: false + +# -- Specify any additional volumes here. (e.g. to mount nfs volumes directly) additionalVolumes: [] +# -- Specify any additional volume mounts for the main container here. additionalVolumeMounts: [] +# -- Used in conjunction with `controller.type: statefulset` to create individual disks for each instance. volumeClaimTemplates: [] -# Used in statefulset to create individual disks for each instance # - name: data # mountPath: /data # accessMode: "ReadWriteOnce" @@ -228,107 +380,271 @@ volumeClaimTemplates: [] # size: 2Gi # storageClass: cheap-storage-class +# -- Node selection constraint +# [[ref]](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector) nodeSelector: {} +# -- Defines affinity constraint rules. +# [[ref]](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) affinity: {} +# -- Specify taint tolerations +# [[ref]](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/) tolerations: [] +# -- Use hostAliases to add custom entries to /etc/hosts - mapping IP addresses to hostnames. +# [[ref]](https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/) hostAliases: [] -# Use hostAliases to add custom entries to /etc/hosts - mapping IP addresses to hostnames. -# ref: https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/ # - ip: "192.168.1.100" # hostnames: # - "example.com" # - "www.example.com" +# -- Set the resource requests / limits for the main container. resources: {} -# We usually recommend not to specify default resources and to leave this as a conscious -# choice for the user. This also increases chances charts run on environments with little -# resources, such as Minikube. If you do want to specify resources, uncomment the following -# lines, adjust them as necessary, and remove the curly braces after 'resources:'. -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi + ## We usually recommend not to specify default resources and to leave this as a conscious + ## choice for the user. This also increases chances charts run on environments with little + ## resources, such as Minikube. If you do want to specify resources, uncomment the following + ## lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi -## Used by TrueNAS SCALE to easily set add GPU's to Apps -# scaleGPU: {} +# -- The common chart supports several add-ons. These can be configured under this key. +# @default -- See below +addons: -## TrueCharts Specific - -# deviceMounts: -# config: -# enabled: false -# emptyDir: false -# hostPath: "/config" -# setPermissions: true - -# customStorage: -# - name: "data" -# enabled: false -# emptyDir: false -# mountPath: "/data" -# subPath: some-subpath -# hostPath: "" -# readOnly: false -# setPermissions: true - -ingress: - main: + # -- The common chart supports adding a VPN add-on. It can be configured under this key. + # For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#wireguard-vpn) + # @default -- See values.yaml + vpn: + # -- Enable running a VPN in the pod to route traffic through a VPN 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 + # -- Specify the VPN type. Valid options are openvpn or wireguard + type: openvpn + + # -- OpenVPN specific configuration + # @default -- See below + openvpn: + image: + # -- Specify the openvpn client image + repository: dperson/openvpn-client + # -- Specify the openvpn client image tag + tag: latest + # -- Specify the openvpn client image pull policy + pullPolicy: IfNotPresent + + # -- Credentials to connect to the VPN Service (used with -a) + auth: # "user;password" + # -- Optionally specify an existing secret that contains the credentials. + # Credentials should be stored under the `VPN_AUTH` key + authSecret: # my-vpn-secret + + # -- WireGuard specific configuration + # @default -- See below + wireguard: + image: + # -- Specify the WireGuard image + repository: docker pull ghcr.io/k8s-at-home/wireguard + # -- Specify the WireGuard image tag + tag: v1.0.20210424 + # -- Specify the WireGuard image pull policy + pullPolicy: IfNotPresent + + # -- Set the VPN container securityContext + # @default -- See values.yaml + securityContext: + capabilities: + add: + - NET_ADMIN + - SYS_MODULE + + # -- All variables specified here will be added to the vpn sidecar container + # See the documentation of the VPN image for all config values + env: {} + # TZ: UTC + + # -- Provide a customized vpn configuration file to be used by the VPN. + configFile: # |- + # Some Example Config + # remote greatvpnhost.com 8888 + # auth-user-pass + # Cipher AES + + # -- Reference an existing secret that contains the VPN configuration file + # The chart expects it to be present under the `vpnConfigfile` key. + configFileSecret: + + # -- Provide custom up/down scripts that can be used by the vpn configuration. + # @default -- See values.yaml + scripts: + up: # |- + # #!/bin/bash + # echo "connected" > /shared/vpnstatus + down: # |- + # #!/bin/bash + # echo "disconnected" > /shared/vpnstatus + + additionalVolumeMounts: [] + + # -- Optionally specify a livenessProbe, e.g. to check if the connection is still + # being protected by the VPN + livenessProbe: {} + # exec: + # command: + # - sh + # - -c + # - if [ $(curl -s https://ipinfo.io/country) == 'US' ]; then exit 0; else exit $?; fi + # initialDelaySeconds: 30 + # periodSeconds: 60 + # failureThreshold: 1 + + # If set to true, will deploy a network policy that blocks all outbound + # traffic except traffic specified as allowed + networkPolicy: + enabled: false + + # The egress configuration for your network policy, All outbound traffic + # From the pod will be blocked unless specified here. Your cluster must + # have a CNI that supports network policies (Canal, Calico, etc...) + # https://kubernetes.io/docs/concepts/services-networking/network-policies/ + # https://github.com/ahmetb/kubernetes-network-policy-recipes + egress: + # - to: + # - ipBlock: + # cidr: 0.0.0.0/0 + # ports: + # - port: 53 + # protocol: UDP + # - port: 53 + # protocol: TCP + + # -- The common library supports adding a code-server add-on to access files. It can be configured under this key. + # For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#code-server) + # @default -- See values.yaml + codeserver: + # -- Enable running a code-server container in the pod + enabled: false + + image: + # -- Specify the code-server image + repository: codercom/code-server + # -- Specify the code-server image tag + tag: 3.9.2 + # -- Specify the code-server image pull policy + pullPolicy: IfNotPresent + + # -- Set any environment variables for code-server here + env: {} + # TZ: UTC + + # -- Set codeserver command line arguments. + # Consider setting --user-data-dir to a persistent location to preserve code-server setting changes + args: + - --auth + - none + # - --user-data-dir + # - "/config/.vscode" + + # -- Specify a list of volumes that get mounted in the code-server container. + # At least 1 volumeMount is required! + volumeMounts: [] + # - name: config + # mountPath: /data/config + + # -- Specify the working dir that will be opened when code-server starts + # If not given, the app will default to the mountpah of the first specified volumeMount + workingDir: "" + + # -- Optionally allow access a Git repository by passing in a private SSH key + # @default -- See below + git: + # -- Raw SSH private key + deployKey: "" + # -- Base64-encoded SSH private key. When both variables are set, the raw SSH key takes precedence. + deployKeyBase64: "" + # -- Existing secret containing SSH private key + # The chart expects it to be present under the `id_rsa` key. + deployKeySecret: "" + + service: + # -- Enable a service for the code-server add-on. + enabled: true + type: ClusterIP + # Specify the default port information + ports: + codeserver: + port: 12321 + enabled: true + protocol: TCP + targetPort: codeserver + ## Specify the nodePort value for the LoadBalancer and NodePort service types. + ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport + ## + # nodePort: + annotations: {} + labels: {} + + ingress: + # -- Enable an ingress for the code-server add-on. + enabled: false + nameOverride: codeserver + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + labels: {} + hosts: + - host: code.chart-example.local + paths: + - path: / + # Ignored if not kubeVersion >= 1.14-0 + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - code.chart-example.local + + securityContext: + runAsUser: 0 + + # -- The common library supports adding a promtail add-on to to access logs and ship them to loki. It can be configured under this key. + # @default -- See values.yaml + promtail: + # -- Enable running a promtail container in the pod + enabled: false + + image: + # -- Specify the promtail image + repository: grafana/promtail + # -- Specify the promtail image tag + tag: 2.2.0 + # -- Specify the promtail image pull policy + pullPolicy: IfNotPresent + + # -- Set any environment variables for promtail here + env: {} + + # -- Set promtail command line arguments + args: [] + + # -- The URL to Loki + loki: "" + + # -- The paths to logs on the volume + logs: [] + # - name: log + # path: /config/logs/*.log + + # -- Specify a list of volumes that get mounted in the promtail container. + # At least 1 volumeMount is required! + volumeMounts: [] + # - name: config + # mountPath: /config + # readOnly: true + + securityContext: + runAsUser: 0 diff --git a/tests/library/common/cert_spec.rb b/tests/library/common/cert_spec.rb deleted file mode 100644 index c129c8285ea..00000000000 --- a/tests/library/common/cert_spec.rb +++ /dev/null @@ -1,322 +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 '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 deleted file mode 100644 index f91d4116b9d..00000000000 --- a/tests/library/common/container_resources_spec.rb +++ /dev/null @@ -1,90 +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 '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 deleted file mode 100644 index bb1decec3a1..00000000000 --- a/tests/library/common/container_spec.rb +++ /dev/null @@ -1,380 +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 '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 deleted file mode 100644 index 37fe729d75a..00000000000 --- a/tests/library/common/controller_spec.rb +++ /dev/null @@ -1,60 +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 '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 deleted file mode 100644 index 7a859dc31d9..00000000000 --- a/tests/library/common/hpa_spec.rb +++ /dev/null @@ -1,120 +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 '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 deleted file mode 100644 index 339c837091f..00000000000 --- a/tests/library/common/ingress_spec.rb +++ /dev/null @@ -1,281 +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 '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 deleted file mode 100644 index 8de52e46e27..00000000000 --- a/tests/library/common/job_permissions_spec.rb +++ /dev/null @@ -1,347 +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 '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 deleted file mode 100644 index 65657c979f4..00000000000 --- a/tests/library/common/pod_spec.rb +++ /dev/null @@ -1,316 +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 '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 deleted file mode 100644 index 8a76e4419fd..00000000000 --- a/tests/library/common/portal_spec.rb +++ /dev/null @@ -1,313 +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 '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 deleted file mode 100644 index 2baede12708..00000000000 --- a/tests/library/common/pvc_spec.rb +++ /dev/null @@ -1,110 +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 '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 deleted file mode 100644 index e17952c5417..00000000000 --- a/tests/library/common/service_spec.rb +++ /dev/null @@ -1,223 +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 '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/tests/test_helper.rb b/tests/test_helper.rb deleted file mode 100644 index 6170486bdbb..00000000000 --- a/tests/test_helper.rb +++ /dev/null @@ -1,146 +0,0 @@ -# frozen_string_literal: true - -require 'json' -require 'yaml' -require 'open3' - -require 'minitest-implicit-subject' -require "minitest/reporters" -require 'minitest/autorun' -require 'minitest/pride' - -class HelmCompileError < StandardError -end - -class HelmDepsError < StandardError -end - -class Chart - attr_reader :name, :path, :values - - def initialize(chart) - @name = chart.split('/').last - - @path = File.expand_path(chart) - - @values = default_values - - update_deps! - end - - def update_deps! - command = "helm dep update '#{path}'" - stdout, stderr, status = Open3.capture3(command) - raise HelmDepsError, stderr if status != 0 - end - - def reset! - @values = default_values - @parsed_resources = nil - end - - def value(value) - values.merge!(value) - end - - def configure_custom_name(name) - @name = name - end - - def execute_helm_template! - file = Tempfile.new(name) - file.write(JSON.parse(values.to_json).to_yaml) - file.close - - begin - command = "helm template '#{name}' '#{path}' --namespace='default' --values='#{file.path}'" - stdout, stderr, status = Open3.capture3(command) - - raise HelmCompileError, stderr if status != 0 - - stdout - ensure - file.unlink - end - end - - def parsed_resources - @parsed_resources ||= begin - output = execute_helm_template! - puts output if ENV.fetch('DEBUG', 'false') == 'true' - YAML.load_stream(output) - end - end - - def resources(matcher = nil) - return parsed_resources unless matcher - - parsed_resources.select do |r| - r >= Hash[matcher.map { |k, v| [k.to_s, v] }] - end - end - - def default_values - { - } - end -end - -class ExtendedMinitest < Minitest::Test - extend MiniTest::Spec::DSL -end - -class ChartTest < ExtendedMinitest - Minitest::Reporters.use! Minitest::Reporters::SpecReporter.new - - before do - chart.reset! - end - - def chart - self.class.class_variable_get('@@chart') - end - - def resource(name) - chart.resources(kind: name).first - end -end - -class Minitest::Result - def name - test_name = defined?(@name) ? @name : super - 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