update
diff --git a/charts/jenkins/templates/NOTES.txt b/charts/jenkins/templates/NOTES.txt
new file mode 100644
index 0000000..953dd26
--- /dev/null
+++ b/charts/jenkins/templates/NOTES.txt
@@ -0,0 +1,68 @@
+{{- $prefix := .Values.controller.jenkinsUriPrefix | default "" -}}
+{{- $url := "" -}}
+1. Get your '{{ .Values.controller.admin.username }}' user password by running:
+ kubectl exec --namespace {{ template "jenkins.namespace" . }} -it svc/{{ template "jenkins.fullname" . }} -c jenkins -- /bin/cat /run/secrets/additional/chart-admin-password && echo
+{{- if .Values.controller.ingress.hostName -}}
+{{- if .Values.controller.ingress.tls -}}
+{{- $url = print "https://" .Values.controller.ingress.hostName $prefix -}}
+{{- else -}}
+{{- $url = print "http://" .Values.controller.ingress.hostName $prefix -}}
+{{- end }}
+2. Visit {{ $url }}
+{{- else }}
+2. Get the Jenkins URL to visit by running these commands in the same shell:
+{{- if contains "NodePort" .Values.controller.serviceType }}
+ export NODE_PORT=$(kubectl get --namespace {{ template "jenkins.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "jenkins.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ template "jenkins.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
+{{- if .Values.controller.httpsKeyStore.enable -}}
+{{- $url = print "https://$NODE_IP:$NODE_PORT" $prefix -}}
+{{- else -}}
+{{- $url = print "http://$NODE_IP:$NODE_PORT" $prefix -}}
+{{- end }}
+ echo {{ $url }}
+
+{{- else if contains "LoadBalancer" .Values.controller.serviceType }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get svc --namespace {{ template "jenkins.namespace" . }} -w {{ template "jenkins.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ template "jenkins.namespace" . }} {{ template "jenkins.fullname" . }} --template "{{ "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}" }}")
+{{- if .Values.controller.httpsKeyStore.enable -}}
+{{- $url = print "https://$SERVICE_IP:" .Values.controller.servicePort $prefix -}}
+{{- else -}}
+{{- $url = print "http://$SERVICE_IP:" .Values.controller.servicePort $prefix -}}
+{{- end }}
+ echo {{ $url }}
+
+{{- else if contains "ClusterIP" .Values.controller.serviceType -}}
+{{- if .Values.controller.httpsKeyStore.enable -}}
+{{- $url = print "https://127.0.0.1:" .Values.controller.servicePort $prefix -}}
+{{- else -}}
+{{- $url = print "http://127.0.0.1:" .Values.controller.servicePort $prefix -}}
+{{- end }}
+ echo {{ $url }}
+ kubectl --namespace {{ template "jenkins.namespace" . }} port-forward svc/{{template "jenkins.fullname" . }} {{ .Values.controller.servicePort }}:{{ .Values.controller.servicePort }}
+{{- end }}
+{{- end }}
+
+3. Login with the password from step 1 and the username: {{ .Values.controller.admin.username }}
+4. Configure security realm and authorization strategy
+5. Use Jenkins Configuration as Code by specifying configScripts in your values.yaml file, see documentation: {{ $url }}/configuration-as-code and examples: https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos
+
+For more information on running Jenkins on Kubernetes, visit:
+https://cloud.google.com/solutions/jenkins-on-container-engine
+
+For more information about Jenkins Configuration as Code, visit:
+https://jenkins.io/projects/jcasc/
+
+{{ if and (eq .Values.controller.image.repository "jenkins/jenkins") (eq .Values.controller.image.registry "docker.io") }}
+NOTE: Consider using a custom image with pre-installed plugins
+{{- else if .Values.controller.installPlugins }}
+NOTE: Consider disabling `installPlugins` if your image already contains plugins.
+{{- end }}
+
+{{- if .Values.persistence.enabled }}
+{{- else }}
+#################################################################################
+###### WARNING: Persistence is disabled!!! You will lose your data when #####
+###### the Jenkins pod is terminated. #####
+#################################################################################
+{{- end }}
diff --git a/charts/jenkins/templates/_helpers.tpl b/charts/jenkins/templates/_helpers.tpl
new file mode 100644
index 0000000..8301a84
--- /dev/null
+++ b/charts/jenkins/templates/_helpers.tpl
@@ -0,0 +1,655 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "jenkins.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Expand the label of the chart.
+*/}}
+{{- define "jenkins.label" -}}
+{{- printf "%s-%s" (include "jenkins.name" .) .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+
+{{/*
+Allow the release namespace to be overridden for multi-namespace deployments in combined charts.
+*/}}
+{{- define "jenkins.namespace" -}}
+ {{- if .Values.namespaceOverride -}}
+ {{- .Values.namespaceOverride -}}
+ {{- else -}}
+ {{- .Release.Namespace -}}
+ {{- end -}}
+{{- end -}}
+
+{{- define "jenkins.agent.namespace" -}}
+ {{- if .Values.agent.namespace -}}
+ {{- tpl .Values.agent.namespace . -}}
+ {{- else -}}
+ {{- if .Values.namespaceOverride -}}
+ {{- .Values.namespaceOverride -}}
+ {{- else -}}
+ {{- .Release.Namespace -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "jenkins.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 -}}
+
+{{/*
+Returns the admin password
+https://github.com/helm/charts/issues/5167#issuecomment-619137759
+*/}}
+{{- define "jenkins.password" -}}
+ {{- if .Values.controller.admin.password -}}
+ {{- .Values.controller.admin.password | b64enc | quote }}
+ {{- else -}}
+ {{- $secret := (lookup "v1" "Secret" .Release.Namespace (include "jenkins.fullname" .)).data -}}
+ {{- if $secret -}}
+ {{/*
+ Reusing current password since secret exists
+ */}}
+ {{- index $secret ( .Values.controller.admin.passwordKey | default "jenkins-admin-password" ) -}}
+ {{- else -}}
+ {{/*
+ Generate new password
+ */}}
+ {{- randAlphaNum 22 | b64enc | quote }}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{/*
+Returns the Jenkins URL
+*/}}
+{{- define "jenkins.url" -}}
+{{- if .Values.controller.jenkinsUrl }}
+ {{- .Values.controller.jenkinsUrl }}
+{{- else }}
+ {{- if .Values.controller.ingress.hostName }}
+ {{- if .Values.controller.ingress.tls }}
+ {{- default "https" .Values.controller.jenkinsUrlProtocol }}://{{ tpl .Values.controller.ingress.hostName $ }}{{ default "" .Values.controller.jenkinsUriPrefix }}
+ {{- else }}
+ {{- default "http" .Values.controller.jenkinsUrlProtocol }}://{{ tpl .Values.controller.ingress.hostName $ }}{{ default "" .Values.controller.jenkinsUriPrefix }}
+ {{- end }}
+ {{- else }}
+ {{- default "http" .Values.controller.jenkinsUrlProtocol }}://{{ template "jenkins.fullname" . }}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}
+ {{- end}}
+{{- end}}
+{{- end -}}
+
+{{/*
+Returns configuration as code default config
+*/}}
+{{- define "jenkins.casc.defaults" -}}
+jenkins:
+ {{- $configScripts := toYaml .Values.controller.JCasC.configScripts }}
+ {{- if and (.Values.controller.JCasC.authorizationStrategy) (not (contains "authorizationStrategy:" $configScripts)) }}
+ authorizationStrategy:
+ {{- tpl .Values.controller.JCasC.authorizationStrategy . | nindent 4 }}
+ {{- end }}
+ {{- if and (.Values.controller.JCasC.securityRealm) (not (contains "securityRealm:" $configScripts)) }}
+ securityRealm:
+ {{- tpl .Values.controller.JCasC.securityRealm . | nindent 4 }}
+ {{- end }}
+ disableRememberMe: {{ .Values.controller.disableRememberMe }}
+ {{- if .Values.controller.legacyRemotingSecurityEnabled }}
+ remotingSecurity:
+ enabled: true
+ {{- end }}
+ mode: {{ .Values.controller.executorMode }}
+ numExecutors: {{ .Values.controller.numExecutors }}
+ {{- if not (kindIs "invalid" .Values.controller.customJenkinsLabels) }}
+ labelString: "{{ join " " .Values.controller.customJenkinsLabels }}"
+ {{- end }}
+ {{- if .Values.controller.projectNamingStrategy }}
+ {{- if kindIs "string" .Values.controller.projectNamingStrategy }}
+ projectNamingStrategy: "{{ .Values.controller.projectNamingStrategy }}"
+ {{- else }}
+ projectNamingStrategy:
+ {{- toYaml .Values.controller.projectNamingStrategy | nindent 4 }}
+ {{- end }}
+ {{- end }}
+ markupFormatter:
+ {{- if .Values.controller.enableRawHtmlMarkupFormatter }}
+ rawHtml:
+ disableSyntaxHighlighting: true
+ {{- else }}
+ {{- toYaml .Values.controller.markupFormatter | nindent 4 }}
+ {{- end }}
+ clouds:
+ - kubernetes:
+ containerCapStr: "{{ .Values.agent.containerCap }}"
+ {{- if .Values.agent.jnlpregistry }}
+ jnlpregistry: "{{ .Values.agent.jnlpregistry }}"
+ {{- end }}
+ defaultsProviderTemplate: "{{ .Values.agent.defaultsProviderTemplate }}"
+ connectTimeout: "{{ .Values.agent.kubernetesConnectTimeout }}"
+ readTimeout: "{{ .Values.agent.kubernetesReadTimeout }}"
+ {{- if .Values.agent.directConnection }}
+ directConnection: true
+ {{- else }}
+ {{- if .Values.agent.jenkinsUrl }}
+ jenkinsUrl: "{{ tpl .Values.agent.jenkinsUrl . }}"
+ {{- else }}
+ jenkinsUrl: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}"
+ {{- end }}
+ {{- if not .Values.agent.websocket }}
+ {{- if .Values.agent.jenkinsTunnel }}
+ jenkinsTunnel: "{{ tpl .Values.agent.jenkinsTunnel . }}"
+ {{- else }}
+ jenkinsTunnel: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
+ {{- end }}
+ {{- else }}
+ webSocket: true
+ {{- end }}
+ {{- end }}
+ maxRequestsPerHostStr: {{ .Values.agent.maxRequestsPerHostStr | quote }}
+ retentionTimeout: {{ .Values.agent.retentionTimeout | quote }}
+ waitForPodSec: {{ .Values.agent.waitForPodSec | quote }}
+ name: "{{ .Values.controller.cloudName }}"
+ namespace: "{{ template "jenkins.agent.namespace" . }}"
+ restrictedPssSecurityContext: {{ .Values.agent.restrictedPssSecurityContext }}
+ serverUrl: "{{ .Values.kubernetesURL }}"
+ credentialsId: "{{ .Values.credentialsId }}"
+ {{- if .Values.agent.enabled }}
+ podLabels:
+ - key: "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}"
+ value: "true"
+ {{- range $key, $val := .Values.agent.podLabels }}
+ - key: {{ $key | quote }}
+ value: {{ $val | quote }}
+ {{- end }}
+ templates:
+ {{- if not .Values.agent.disableDefaultAgent }}
+ {{- include "jenkins.casc.podTemplate" . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.additionalAgents }}
+ {{- /* save .Values.agent */}}
+ {{- $agent := .Values.agent }}
+ {{- range $name, $additionalAgent := .Values.additionalAgents }}
+ {{- $additionalContainersEmpty := and (hasKey $additionalAgent "additionalContainers") (empty $additionalAgent.additionalContainers) }}
+ {{- /* merge original .Values.agent into additional agent to ensure it at least has the default values */}}
+ {{- $additionalAgent := merge $additionalAgent $agent }}
+ {{- /* clear list of additional containers in case it is configured empty for this agent (merge might have overwritten that) */}}
+ {{- if $additionalContainersEmpty }}
+ {{- $_ := set $additionalAgent "additionalContainers" list }}
+ {{- end }}
+ {{- /* set .Values.agent to $additionalAgent */}}
+ {{- $_ := set $.Values "agent" $additionalAgent }}
+ {{- include "jenkins.casc.podTemplate" $ | nindent 8 }}
+ {{- end }}
+ {{- /* restore .Values.agent */}}
+ {{- $_ := set .Values "agent" $agent }}
+ {{- end }}
+ {{- if .Values.agent.podTemplates }}
+ {{- range $key, $val := .Values.agent.podTemplates }}
+ {{- tpl $val $ | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.additionalClouds }}
+ {{- /* save root */}}
+ {{- $oldRoot := deepCopy $ }}
+ {{- range $name, $additionalCloud := .Values.additionalClouds }}
+ {{- $newRoot := deepCopy $ }}
+ {{- /* clear additionalAgents from the copy if override set to `true` */}}
+ {{- if .additionalAgentsOverride }}
+ {{- $_ := set $newRoot.Values "additionalAgents" list}}
+ {{- end}}
+ {{- $newValues := merge $additionalCloud $newRoot.Values }}
+ {{- $_ := set $newRoot "Values" $newValues }}
+ {{- /* clear additionalClouds from the copy */}}
+ {{- $_ := set $newRoot.Values "additionalClouds" list }}
+ {{- with $newRoot}}
+ - kubernetes:
+ containerCapStr: "{{ .Values.agent.containerCap }}"
+ {{- if .Values.agent.jnlpregistry }}
+ jnlpregistry: "{{ .Values.agent.jnlpregistry }}"
+ {{- end }}
+ defaultsProviderTemplate: "{{ .Values.agent.defaultsProviderTemplate }}"
+ connectTimeout: "{{ .Values.agent.kubernetesConnectTimeout }}"
+ readTimeout: "{{ .Values.agent.kubernetesReadTimeout }}"
+ {{- if .Values.agent.directConnection }}
+ directConnection: true
+ {{- else }}
+ {{- if .Values.agent.jenkinsUrl }}
+ jenkinsUrl: "{{ tpl .Values.agent.jenkinsUrl . }}"
+ {{- else }}
+ jenkinsUrl: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "" .Values.controller.jenkinsUriPrefix }}"
+ {{- end }}
+ {{- if not .Values.agent.websocket }}
+ {{- if .Values.agent.jenkinsTunnel }}
+ jenkinsTunnel: "{{ tpl .Values.agent.jenkinsTunnel . }}"
+ {{- else }}
+ jenkinsTunnel: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
+ {{- end }}
+ {{- else }}
+ webSocket: true
+ {{- end }}
+ {{- end }}
+ maxRequestsPerHostStr: {{ .Values.agent.maxRequestsPerHostStr | quote }}
+ retentionTimeout: {{ .Values.agent.retentionTimeout | quote }}
+ waitForPodSec: {{ .Values.agent.waitForPodSec | quote }}
+ name: {{ $name | quote }}
+ namespace: "{{ template "jenkins.agent.namespace" . }}"
+ restrictedPssSecurityContext: {{ .Values.agent.restrictedPssSecurityContext }}
+ serverUrl: "{{ .Values.kubernetesURL }}"
+ credentialsId: "{{ .Values.credentialsId }}"
+ {{- if .Values.agent.enabled }}
+ podLabels:
+ - key: "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}"
+ value: "true"
+ {{- range $key, $val := .Values.agent.podLabels }}
+ - key: {{ $key | quote }}
+ value: {{ $val | quote }}
+ {{- end }}
+ templates:
+ {{- if not .Values.agent.disableDefaultAgent }}
+ {{- include "jenkins.casc.podTemplate" . | nindent 8 }}
+ {{- end }}
+ {{- if .Values.additionalAgents }}
+ {{- /* save .Values.agent */}}
+ {{- $agent := .Values.agent }}
+ {{- range $name, $additionalAgent := .Values.additionalAgents }}
+ {{- $additionalContainersEmpty := and (hasKey $additionalAgent "additionalContainers") (empty $additionalAgent.additionalContainers) }}
+ {{- /* merge original .Values.agent into additional agent to ensure it at least has the default values */}}
+ {{- $additionalAgent := merge $additionalAgent $agent }}
+ {{- /* clear list of additional containers in case it is configured empty for this agent (merge might have overwritten that) */}}
+ {{- if $additionalContainersEmpty }}
+ {{- $_ := set $additionalAgent "additionalContainers" list }}
+ {{- end }}
+ {{- /* set .Values.agent to $additionalAgent */}}
+ {{- $_ := set $.Values "agent" $additionalAgent }}
+ {{- include "jenkins.casc.podTemplate" $ | nindent 8 }}
+ {{- end }}
+ {{- /* restore .Values.agent */}}
+ {{- $_ := set .Values "agent" $agent }}
+ {{- end }}
+ {{- with .Values.agent.podTemplates }}
+ {{- range $key, $val := . }}
+ {{- tpl $val $ | nindent 8 }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- /* restore root */}}
+ {{- $_ := set $ "Values" $oldRoot.Values }}
+ {{- end }}
+ {{- if .Values.controller.csrf.defaultCrumbIssuer.enabled }}
+ crumbIssuer:
+ standard:
+ excludeClientIPFromCrumb: {{ if .Values.controller.csrf.defaultCrumbIssuer.proxyCompatability }}true{{ else }}false{{- end }}
+ {{- end }}
+{{- include "jenkins.casc.security" . }}
+{{- with .Values.controller.scriptApproval }}
+ scriptApproval:
+ approvedSignatures:
+ {{- range $key, $val := . }}
+ - "{{ $val }}"
+ {{- end }}
+{{- end }}
+unclassified:
+ location:
+ {{- with .Values.controller.jenkinsAdminEmail }}
+ adminAddress: {{ . }}
+ {{- end }}
+ url: {{ template "jenkins.url" . }}
+{{- end -}}
+
+{{/*
+Returns a name template to be used for jcasc configmaps, using
+suffix passed in at call as index 0
+*/}}
+{{- define "jenkins.casc.configName" -}}
+{{- $name := index . 0 -}}
+{{- $root := index . 1 -}}
+"{{- include "jenkins.fullname" $root -}}-jenkins-{{ $name }}"
+{{- end -}}
+
+{{/*
+Returns kubernetes pod template configuration as code
+*/}}
+{{- define "jenkins.casc.podTemplate" -}}
+- name: "{{ .Values.agent.podName }}"
+ namespace: "{{ template "jenkins.agent.namespace" . }}"
+{{- if .Values.agent.annotations }}
+ annotations:
+ {{- range $key, $value := .Values.agent.annotations }}
+ - key: {{ $key }}
+ value: {{ $value | quote }}
+ {{- end }}
+{{- end }}
+ id: {{ sha256sum (toYaml .Values.agent) }}
+ containers:
+ - name: "{{ .Values.agent.sideContainerName }}"
+ alwaysPullImage: {{ .Values.agent.alwaysPullImage }}
+ args: "{{ .Values.agent.args | replace "$" "^$" }}"
+ {{- with .Values.agent.command }}
+ command: {{ . }}
+ {{- end }}
+ envVars:
+ - envVar:
+ {{- if .Values.agent.directConnection }}
+ key: "JENKINS_DIRECT_CONNECTION"
+ {{- if .Values.agent.jenkinsTunnel }}
+ value: "{{ tpl .Values.agent.jenkinsTunnel . }}"
+ {{- else }}
+ value: "{{ template "jenkins.fullname" . }}-agent.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{ .Values.controller.agentListenerPort }}"
+ {{- end }}
+ {{- else }}
+ key: "JENKINS_URL"
+ {{- if .Values.agent.jenkinsUrl }}
+ value: {{ tpl .Values.agent.jenkinsUrl . }}
+ {{- else }}
+ value: "http://{{ template "jenkins.fullname" . }}.{{ template "jenkins.namespace" . }}.svc.{{.Values.clusterZone}}:{{.Values.controller.servicePort}}{{ default "/" .Values.controller.jenkinsUriPrefix }}"
+ {{- end }}
+ {{- end }}
+ image: "{{ .Values.agent.image.repository }}:{{ .Values.agent.image.tag }}"
+ {{- if .Values.agent.livenessProbe }}
+ livenessProbe:
+ execArgs: {{.Values.agent.livenessProbe.execArgs | quote}}
+ failureThreshold: {{.Values.agent.livenessProbe.failureThreshold}}
+ initialDelaySeconds: {{.Values.agent.livenessProbe.initialDelaySeconds}}
+ periodSeconds: {{.Values.agent.livenessProbe.periodSeconds}}
+ successThreshold: {{.Values.agent.livenessProbe.successThreshold}}
+ timeoutSeconds: {{.Values.agent.livenessProbe.timeoutSeconds}}
+ {{- end }}
+ privileged: "{{- if .Values.agent.privileged }}true{{- else }}false{{- end }}"
+ resourceLimitCpu: {{.Values.agent.resources.limits.cpu}}
+ resourceLimitMemory: {{.Values.agent.resources.limits.memory}}
+ {{- with .Values.agent.resources.limits.ephemeralStorage }}
+ resourceLimitEphemeralStorage: {{.}}
+ {{- end }}
+ resourceRequestCpu: {{.Values.agent.resources.requests.cpu}}
+ resourceRequestMemory: {{.Values.agent.resources.requests.memory}}
+ {{- with .Values.agent.resources.requests.ephemeralStorage }}
+ resourceRequestEphemeralStorage: {{.}}
+ {{- end }}
+ {{- with .Values.agent.runAsUser }}
+ runAsUser: {{ . }}
+ {{- end }}
+ {{- with .Values.agent.runAsGroup }}
+ runAsGroup: {{ . }}
+ {{- end }}
+ ttyEnabled: {{ .Values.agent.TTYEnabled }}
+ workingDir: {{ .Values.agent.workingDir }}
+{{- range $additionalContainers := .Values.agent.additionalContainers }}
+ - name: "{{ $additionalContainers.sideContainerName }}"
+ alwaysPullImage: {{ $additionalContainers.alwaysPullImage | default $.Values.agent.alwaysPullImage }}
+ args: "{{ $additionalContainers.args | replace "$" "^$" }}"
+ {{- with $additionalContainers.command }}
+ command: {{ . }}
+ {{- end }}
+ envVars:
+ - envVar:
+ key: "JENKINS_URL"
+ {{- if $additionalContainers.jenkinsUrl }}
+ value: {{ tpl ($additionalContainers.jenkinsUrl) . }}
+ {{- else }}
+ value: "http://{{ template "jenkins.fullname" $ }}.{{ template "jenkins.namespace" $ }}.svc.{{ $.Values.clusterZone }}:{{ $.Values.controller.servicePort }}{{ default "/" $.Values.controller.jenkinsUriPrefix }}"
+ {{- end }}
+ image: "{{ $additionalContainers.image.repository }}:{{ $additionalContainers.image.tag }}"
+ {{- if $additionalContainers.livenessProbe }}
+ livenessProbe:
+ execArgs: {{$additionalContainers.livenessProbe.execArgs | quote}}
+ failureThreshold: {{$additionalContainers.livenessProbe.failureThreshold}}
+ initialDelaySeconds: {{$additionalContainers.livenessProbe.initialDelaySeconds}}
+ periodSeconds: {{$additionalContainers.livenessProbe.periodSeconds}}
+ successThreshold: {{$additionalContainers.livenessProbe.successThreshold}}
+ timeoutSeconds: {{$additionalContainers.livenessProbe.timeoutSeconds}}
+ {{- end }}
+ privileged: "{{- if $additionalContainers.privileged }}true{{- else }}false{{- end }}"
+ resourceLimitCpu: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.limits.cpu }}{{ else }}{{ $.Values.agent.resources.limits.cpu }}{{ end }}
+ resourceLimitMemory: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.limits.memory }}{{ else }}{{ $.Values.agent.resources.limits.memory }}{{ end }}
+ resourceRequestCpu: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.requests.cpu }}{{ else }}{{ $.Values.agent.resources.requests.cpu }}{{ end }}
+ resourceRequestMemory: {{ if $additionalContainers.resources }}{{ $additionalContainers.resources.requests.memory }}{{ else }}{{ $.Values.agent.resources.requests.memory }}{{ end }}
+ {{- if or $additionalContainers.runAsUser $.Values.agent.runAsUser }}
+ runAsUser: {{ $additionalContainers.runAsUser | default $.Values.agent.runAsUser }}
+ {{- end }}
+ {{- if or $additionalContainers.runAsGroup $.Values.agent.runAsGroup }}
+ runAsGroup: {{ $additionalContainers.runAsGroup | default $.Values.agent.runAsGroup }}
+ {{- end }}
+ ttyEnabled: {{ $additionalContainers.TTYEnabled | default $.Values.agent.TTYEnabled }}
+ workingDir: {{ $additionalContainers.workingDir | default $.Values.agent.workingDir }}
+{{- end }}
+{{- if or .Values.agent.envVars .Values.agent.secretEnvVars }}
+ envVars:
+ {{- range $index, $var := .Values.agent.envVars }}
+ - envVar:
+ key: {{ $var.name }}
+ value: {{ tpl $var.value $ }}
+ {{- end }}
+ {{- range $index, $var := .Values.agent.secretEnvVars }}
+ - secretEnvVar:
+ key: {{ $var.key }}
+ secretName: {{ $var.secretName }}
+ secretKey: {{ $var.secretKey }}
+ optional: {{ $var.optional | default false }}
+ {{- end }}
+{{- end }}
+ idleMinutes: {{ .Values.agent.idleMinutes }}
+ instanceCap: 2147483647
+ {{- if .Values.agent.hostNetworking }}
+ hostNetwork: {{ .Values.agent.hostNetworking }}
+ {{- end }}
+ {{- if .Values.agent.imagePullSecretName }}
+ imagePullSecrets:
+ - name: {{ .Values.agent.imagePullSecretName }}
+ {{- end }}
+ label: "{{ .Release.Name }}-{{ .Values.agent.componentName }} {{ .Values.agent.customJenkinsLabels | join " " }}"
+{{- if .Values.agent.nodeSelector }}
+ nodeSelector:
+ {{- $local := dict "first" true }}
+ {{- range $key, $value := .Values.agent.nodeSelector }}
+ {{- if $local.first }} {{ else }},{{ end }}
+ {{- $key }}={{ tpl $value $ }}
+ {{- $_ := set $local "first" false }}
+ {{- end }}
+{{- end }}
+ nodeUsageMode: {{ quote .Values.agent.nodeUsageMode }}
+ podRetention: {{ .Values.agent.podRetention }}
+ showRawYaml: {{ .Values.agent.showRawYaml }}
+ serviceAccount: "{{ include "jenkins.serviceAccountAgentName" . }}"
+ slaveConnectTimeoutStr: "{{ .Values.agent.connectTimeout }}"
+{{- if .Values.agent.volumes }}
+ volumes:
+ {{- range $index, $volume := .Values.agent.volumes }}
+ -{{- if (eq $volume.type "ConfigMap") }} configMapVolume:
+ {{- else if (eq $volume.type "EmptyDir") }} emptyDirVolume:
+ {{- else if (eq $volume.type "EphemeralVolume") }} genericEphemeralVolume:
+ {{- else if (eq $volume.type "HostPath") }} hostPathVolume:
+ {{- else if (eq $volume.type "Nfs") }} nfsVolume:
+ {{- else if (eq $volume.type "PVC") }} persistentVolumeClaim:
+ {{- else if (eq $volume.type "Secret") }} secretVolume:
+ {{- else }} {{ $volume.type }}:
+ {{- end }}
+ {{- range $key, $value := $volume }}
+ {{- if not (eq $key "type") }}
+ {{ $key }}: {{ if kindIs "string" $value }}{{ tpl $value $ | quote }}{{ else }}{{ $value }}{{ end }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+{{- end }}
+{{- if .Values.agent.workspaceVolume }}
+ workspaceVolume:
+ {{- if (eq .Values.agent.workspaceVolume.type "DynamicPVC") }}
+ dynamicPVC:
+ {{- else if (eq .Values.agent.workspaceVolume.type "EmptyDir") }}
+ emptyDirWorkspaceVolume:
+ {{- else if (eq .Values.agent.workspaceVolume.type "EphemeralVolume") }}
+ genericEphemeralVolume:
+ {{- else if (eq .Values.agent.workspaceVolume.type "HostPath") }}
+ hostPathWorkspaceVolume:
+ {{- else if (eq .Values.agent.workspaceVolume.type "Nfs") }}
+ nfsWorkspaceVolume:
+ {{- else if (eq .Values.agent.workspaceVolume.type "PVC") }}
+ persistentVolumeClaimWorkspaceVolume:
+ {{- else }}
+ {{ .Values.agent.workspaceVolume.type }}:
+ {{- end }}
+ {{- range $key, $value := .Values.agent.workspaceVolume }}
+ {{- if not (eq $key "type") }}
+ {{ $key }}: {{ if kindIs "string" $value }}{{ tpl $value $ | quote }}{{ else }}{{ $value }}{{ end }}
+ {{- end }}
+ {{- end }}
+{{- end }}
+{{- if .Values.agent.yamlTemplate }}
+ yaml: |-
+ {{- tpl (trim .Values.agent.yamlTemplate) . | nindent 4 }}
+{{- end }}
+ yamlMergeStrategy: {{ .Values.agent.yamlMergeStrategy }}
+{{- end -}}
+
+{{- define "jenkins.kubernetes-version" -}}
+ {{- if .Values.controller.installPlugins -}}
+ {{- range .Values.controller.installPlugins -}}
+ {{- if hasPrefix "kubernetes:" . }}
+ {{- $split := splitList ":" . }}
+ {{- printf "%s" (index $split 1 ) -}}
+ {{- end -}}
+ {{- end -}}
+ {{- end -}}
+{{- end -}}
+
+{{- define "jenkins.casc.security" }}
+security:
+{{- with .Values.controller.JCasC }}
+{{- if .security }}
+ {{- .security | toYaml | nindent 2 }}
+{{- end }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "jenkins.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create -}}
+ {{ default (include "jenkins.fullname" .) .Values.serviceAccount.name }}
+{{- else -}}
+ {{ default "default" .Values.serviceAccount.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create the name of the service account for Jenkins agents to use
+*/}}
+{{- define "jenkins.serviceAccountAgentName" -}}
+{{- if .Values.serviceAccountAgent.create -}}
+ {{ default (printf "%s-%s" (include "jenkins.fullname" .) "agent") .Values.serviceAccountAgent.name }}
+{{- else -}}
+ {{ default "default" .Values.serviceAccountAgent.name }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create a full tag name for controller image
+*/}}
+{{- define "controller.image.tag" -}}
+{{- if .Values.controller.image.tagLabel -}}
+ {{- default (printf "%s-%s" .Chart.AppVersion .Values.controller.image.tagLabel) .Values.controller.image.tag -}}
+{{- else -}}
+ {{- default .Chart.AppVersion .Values.controller.image.tag -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create the HTTP port for interacting with the controller
+*/}}
+{{- define "controller.httpPort" -}}
+{{- if .Values.controller.httpsKeyStore.enable -}}
+ {{- .Values.controller.httpsKeyStore.httpPort -}}
+{{- else -}}
+ {{- .Values.controller.targetPort -}}
+{{- end -}}
+{{- end -}}
+
+{{- define "jenkins.configReloadContainer" -}}
+{{- $root := index . 0 -}}
+{{- $containerName := index . 1 -}}
+{{- $containerType := index . 2 -}}
+- name: {{ $containerName }}
+ image: "{{ $root.Values.controller.sidecars.configAutoReload.image.registry }}/{{ $root.Values.controller.sidecars.configAutoReload.image.repository }}:{{ $root.Values.controller.sidecars.configAutoReload.image.tag }}"
+ imagePullPolicy: {{ $root.Values.controller.sidecars.configAutoReload.imagePullPolicy }}
+ {{- if $root.Values.controller.sidecars.configAutoReload.containerSecurityContext }}
+ securityContext: {{- toYaml $root.Values.controller.sidecars.configAutoReload.containerSecurityContext | nindent 4 }}
+ {{- end }}
+ {{- if $root.Values.controller.sidecars.configAutoReload.envFrom }}
+ envFrom:
+{{ (tpl (toYaml $root.Values.controller.sidecars.configAutoReload.envFrom) $root) | indent 4 }}
+ {{- end }}
+ env:
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: LABEL
+ value: "{{ template "jenkins.fullname" $root }}-jenkins-config"
+ - name: FOLDER
+ value: "{{ $root.Values.controller.sidecars.configAutoReload.folder }}"
+ - name: NAMESPACE
+ value: '{{ $root.Values.controller.sidecars.configAutoReload.searchNamespace | default (include "jenkins.namespace" $root) }}'
+ {{- if eq $containerType "init" }}
+ - name: METHOD
+ value: "LIST"
+ {{- else if $root.Values.controller.sidecars.configAutoReload.sleepTime }}
+ - name: METHOD
+ value: "SLEEP"
+ - name: SLEEP_TIME
+ value: "{{ $root.Values.controller.sidecars.configAutoReload.sleepTime }}"
+ {{- end }}
+ {{- if eq $containerType "sidecar" }}
+ - name: REQ_URL
+ value: "{{- default "http" $root.Values.controller.sidecars.configAutoReload.scheme }}://localhost:{{- include "controller.httpPort" $root -}}{{- $root.Values.controller.jenkinsUriPrefix -}}/reload-configuration-as-code/?casc-reload-token=$(POD_NAME)"
+ - name: REQ_METHOD
+ value: "POST"
+ - name: REQ_RETRY_CONNECT
+ value: "{{ $root.Values.controller.sidecars.configAutoReload.reqRetryConnect }}"
+ {{- if $root.Values.controller.sidecars.configAutoReload.skipTlsVerify }}
+ - name: REQ_SKIP_TLS_VERIFY
+ value: "true"
+ {{- end }}
+ {{- end }}
+
+ {{- if $root.Values.controller.sidecars.configAutoReload.env }}
+ {{- range $envVarItem := $root.Values.controller.sidecars.configAutoReload.env -}}
+ {{- if or (ne $containerType "init") (ne .name "METHOD") }}
+{{- (tpl (toYaml (list $envVarItem)) $root) | nindent 4 }}
+ {{- end -}}
+ {{- end -}}
+ {{- end }}
+
+ resources:
+{{ toYaml $root.Values.controller.sidecars.configAutoReload.resources | indent 4 }}
+ volumeMounts:
+ - name: sc-config-volume
+ mountPath: {{ $root.Values.controller.sidecars.configAutoReload.folder | quote }}
+ - name: jenkins-home
+ mountPath: {{ $root.Values.controller.jenkinsHome }}
+ {{- if $root.Values.persistence.subPath }}
+ subPath: {{ $root.Values.persistence.subPath }}
+ {{- end }}
+
+{{- end -}}
diff --git a/charts/jenkins/templates/config-init-scripts.yaml b/charts/jenkins/templates/config-init-scripts.yaml
new file mode 100644
index 0000000..7dd253c
--- /dev/null
+++ b/charts/jenkins/templates/config-init-scripts.yaml
@@ -0,0 +1,18 @@
+{{- if .Values.controller.initScripts -}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "jenkins.fullname" . }}-init-scripts
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+data:
+{{- range $key, $val := .Values.controller.initScripts }}
+ init{{ $key }}.groovy: |-
+{{ tpl $val $ | indent 4 }}
+{{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/config.yaml b/charts/jenkins/templates/config.yaml
new file mode 100644
index 0000000..5de0b9f
--- /dev/null
+++ b/charts/jenkins/templates/config.yaml
@@ -0,0 +1,92 @@
+{{- $jenkinsHome := .Values.controller.jenkinsHome -}}
+
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+data:
+ apply_config.sh: |-
+ set -e
+{{- if .Values.controller.initializeOnce }}
+ if [ -f {{ .Values.controller.jenkinsHome }}/initialization-completed ]; then
+ echo "controller was previously initialized, refusing to re-initialize"
+ exit 0
+ fi
+{{- end }}
+ echo "disable Setup Wizard"
+ # Prevent Setup Wizard when JCasC is enabled
+ echo $JENKINS_VERSION > {{ .Values.controller.jenkinsHome }}/jenkins.install.UpgradeWizard.state
+ echo $JENKINS_VERSION > {{ .Values.controller.jenkinsHome }}/jenkins.install.InstallUtil.lastExecVersion
+{{- if .Values.controller.overwritePlugins }}
+ echo "remove all plugins from shared volume"
+ # remove all plugins from shared volume
+ rm -rf {{ .Values.controller.jenkinsHome }}/plugins/*
+{{- end }}
+{{- if .Values.controller.JCasC.overwriteConfiguration }}
+ echo "deleting all XML config files"
+ rm -f {{ .Values.controller.jenkinsHome }}/config.xml
+ rm -f {{ .Values.controller.jenkinsHome }}/*plugins*.xml
+ find {{ .Values.controller.jenkinsHome }} -maxdepth 1 -type f -iname '*configuration*.xml' -exec rm -f {} \;
+{{- end }}
+{{- if .Values.controller.installPlugins }}
+ echo "download plugins"
+ # Install missing plugins
+ cp /var/jenkins_config/plugins.txt {{ .Values.controller.jenkinsHome }};
+ rm -rf {{ .Values.controller.jenkinsRef }}/plugins/*.lock
+ version () { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; }
+ if [ -f "{{ .Values.controller.jenkinsWar }}" ] && [ -n "$(command -v jenkins-plugin-cli)" 2>/dev/null ] && [ $(version $(jenkins-plugin-cli --version)) -ge $(version "2.1.1") ]; then
+ jenkins-plugin-cli --verbose --war "{{ .Values.controller.jenkinsWar }}" --plugin-file "{{ .Values.controller.jenkinsHome }}/plugins.txt" --latest {{ .Values.controller.installLatestPlugins }}{{- if .Values.controller.installLatestSpecifiedPlugins }} --latest-specified{{- end }};
+ else
+ /usr/local/bin/install-plugins.sh `echo $(cat {{ .Values.controller.jenkinsHome }}/plugins.txt)`;
+ fi
+ echo "copy plugins to shared volume"
+ # Copy plugins to shared volume
+ yes n | cp -i {{ .Values.controller.jenkinsRef }}/plugins/* /var/jenkins_plugins/;
+{{- end }}
+ {{- if not .Values.controller.sidecars.configAutoReload.enabled }}
+ echo "copy configuration as code files"
+ mkdir -p {{ .Values.controller.jenkinsHome }}/casc_configs;
+ rm -rf {{ .Values.controller.jenkinsHome }}/casc_configs/*
+ {{- if or .Values.controller.JCasC.defaultConfig .Values.controller.JCasC.configScripts }}
+ cp -v /var/jenkins_config/*.yaml {{ .Values.controller.jenkinsHome }}/casc_configs
+ {{- end }}
+ {{- end }}
+ echo "finished initialization"
+{{- if .Values.controller.initializeOnce }}
+ touch {{ .Values.controller.jenkinsHome }}/initialization-completed
+{{- end }}
+ {{- if not .Values.controller.sidecars.configAutoReload.enabled }}
+# Only add config to this script if we aren't auto-reloading otherwise the pod will restart upon each config change:
+{{- if .Values.controller.JCasC.defaultConfig }}
+ jcasc-default-config.yaml: |-
+ {{- include "jenkins.casc.defaults" . |nindent 4}}
+{{- end }}
+{{- range $key, $val := .Values.controller.JCasC.configScripts }}
+ {{ $key }}.yaml: |-
+{{ tpl $val $| indent 4 }}
+{{- end }}
+{{- end }}
+ plugins.txt: |-
+{{- if .Values.controller.installPlugins }}
+ {{- range $installPlugin := .Values.controller.installPlugins }}
+ {{- $installPlugin | nindent 4 }}
+ {{- end }}
+ {{- range $addlPlugin := .Values.controller.additionalPlugins }}
+ {{- /* duplicate plugin check */}}
+ {{- range $installPlugin := $.Values.controller.installPlugins }}
+ {{- if eq (splitList ":" $addlPlugin | first) (splitList ":" $installPlugin | first) }}
+ {{- $message := print "[PLUGIN CONFLICT] controller.additionalPlugins contains '" $addlPlugin "'" }}
+ {{- $message := print $message " but controller.installPlugins already contains '" $installPlugin "'." }}
+ {{- $message := print $message " Override controller.installPlugins to use '" $addlPlugin "' plugin." }}
+ {{- fail $message }}
+ {{- end }}
+ {{- end }}
+ {{- $addlPlugin | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/deprecation.yaml b/charts/jenkins/templates/deprecation.yaml
new file mode 100644
index 0000000..f54017c
--- /dev/null
+++ b/charts/jenkins/templates/deprecation.yaml
@@ -0,0 +1,151 @@
+{{- if .Values.checkDeprecation }}
+ {{- if .Values.master }}
+ {{ fail "`master` does no longer exist. It has been renamed to `controller`" }}
+ {{- end }}
+
+ {{- if .Values.controller.imageTag }}
+ {{ fail "`controller.imageTag` does no longer exist. Please use `controller.image.tag` instead" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveListenerPort }}
+ {{ fail "`controller.slaveListenerPort` does no longer exist. It has been renamed to `controller.agentListenerPort`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveHostPort }}
+ {{ fail "`controller.slaveHostPort` does no longer exist. It has been renamed to `controller.agentListenerHostPort`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveKubernetesNamespace }}
+ {{ fail "`controller.slaveKubernetesNamespace` does no longer exist. It has been renamed to `agent.namespace`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveDefaultsProviderTemplate }}
+ {{ fail "`controller.slaveDefaultsProviderTemplate` does no longer exist. It has been renamed to `agent.defaultsProviderTemplate`" }}
+ {{- end }}
+
+ {{- if .Values.controller.useSecurity }}
+ {{ fail "`controller.useSecurity` does no longer exist. It has been renamed to `controller.adminSecret`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveJenkinsUrl }}
+ {{ fail "`controller.slaveJenkinsUrl` does no longer exist. It has been renamed to `agent.jenkinsUrl`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveJenkinsTunnel }}
+ {{ fail "`controller.slaveJenkinsTunnel` does no longer exist. It has been renamed to `agent.jenkinsTunnel`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveConnectTimeout }}
+ {{ fail "`controller.slaveConnectTimeout` does no longer exist. It has been renamed to `agent.kubernetesConnectTimeout`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveReadTimeout }}
+ {{ fail "`controller.slaveReadTimeout` does no longer exist. It has been renamed to `agent.kubernetesReadTimeout`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveListenerServiceType }}
+ {{ fail "`controller.slaveListenerServiceType` does no longer exist. It has been renamed to `controller.agentListenerServiceType`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveListenerLoadBalancerIP }}
+ {{ fail "`controller.slaveListenerLoadBalancerIP` does no longer exist. It has been renamed to `controller.agentListenerLoadBalancerIP`" }}
+ {{- end }}
+
+ {{- if .Values.controller.slaveListenerServiceAnnotations }}
+ {{ fail "`controller.slaveListenerServiceAnnotations` does no longer exist. It has been renamed to `controller.agentListenerServiceAnnotations`" }}
+ {{- end }}
+
+ {{- if .Values.agent.slaveConnectTimeout }}
+ {{ fail "`agent.slaveConnectTimeout` does no longer exist. It has been renamed to `agent.connectTimeout`" }}
+ {{- end }}
+
+ {{- if .Values.NetworkPolicy }}
+
+ {{- if .Values.NetworkPolicy.Enabled }}
+ {{ fail "`NetworkPolicy.Enabled` does no longer exist. It has been renamed to `networkPolicy.enabled`" }}
+ {{- end }}
+
+ {{- if .Values.NetworkPolicy.ApiVersion }}
+ {{ fail "`NetworkPolicy.ApiVersion` does no longer exist. It has been renamed to `networkPolicy.apiVersion`" }}
+ {{- end }}
+
+ {{ fail "NetworkPolicy.* values have been renamed, please check the documentation" }}
+ {{- end }}
+
+
+ {{- if .Values.rbac.install }}
+ {{ fail "`rbac.install` does no longer exist. It has been renamed to `rbac.create` and is enabled by default!" }}
+ {{- end }}
+
+ {{- if .Values.rbac.serviceAccountName }}
+ {{ fail "`rbac.serviceAccountName` does no longer exist. It has been renamed to `serviceAccount.name`" }}
+ {{- end }}
+
+ {{- if .Values.rbac.serviceAccountAnnotations }}
+ {{ fail "`rbac.serviceAccountAnnotations` does no longer exist. It has been renamed to `serviceAccount.annotations`" }}
+ {{- end }}
+
+ {{- if .Values.rbac.roleRef }}
+ {{ fail "`rbac.roleRef` does no longer exist. RBAC roles are now generated, please check the documentation" }}
+ {{- end }}
+
+ {{- if .Values.rbac.roleKind }}
+ {{ fail "`rbac.roleKind` does no longer exist. RBAC roles are now generated, please check the documentation" }}
+ {{- end }}
+
+ {{- if .Values.rbac.roleBindingKind }}
+ {{ fail "`rbac.roleBindingKind` does no longer exist. RBAC roles are now generated, please check the documentation" }}
+ {{- end }}
+
+ {{- if .Values.controller.JCasC.pluginVersion }}
+ {{ fail "controller.JCasC.pluginVersion has been deprecated, please use controller.installPlugins instead" }}
+ {{- end }}
+
+ {{- if .Values.controller.deploymentLabels }}
+ {{ fail "`controller.deploymentLabels` does no longer exist. It has been renamed to `controller.statefulSetLabels`" }}
+ {{- end }}
+
+ {{- if .Values.controller.deploymentAnnotations }}
+ {{ fail "`controller.deploymentAnnotations` does no longer exist. It has been renamed to `controller.statefulSetAnnotations`" }}
+ {{- end }}
+
+ {{- if .Values.controller.rollingUpdate }}
+ {{ fail "`controller.rollingUpdate` does no longer exist. It is no longer relevant, since a StatefulSet is used for the Jenkins controller" }}
+ {{- end }}
+
+ {{- if .Values.controller.tag }}
+ {{ fail "`controller.tag` no longer exists. It has been renamed to `controller.image.tag'" }}
+ {{- end }}
+
+ {{- if .Values.controller.tagLabel }}
+ {{ fail "`controller.tagLabel` no longer exists. It has been renamed to `controller.image.tagLabel`" }}
+ {{- end }}
+
+ {{- if .Values.controller.adminSecret }}
+ {{ fail "`controller.adminSecret` no longer exists. It has been renamed to `controller.admin.createSecret`" }}
+ {{- end }}
+
+ {{- if .Values.controller.adminUser }}
+ {{ fail "`controller.adminUser` no longer exists. It has been renamed to `controller.admin.username`" }}
+ {{- end }}
+
+ {{- if .Values.controller.adminPassword }}
+ {{ fail "`controller.adminPassword` no longer exists. It has been renamed to `controller.admin.password`" }}
+ {{- end }}
+
+ {{- if .Values.controller.sidecars.other }}
+ {{ fail "`controller.sidecars.other` no longer exists. It has been renamed to `controller.sidecars.additionalSidecarContainers`" }}
+ {{- end }}
+
+ {{- if .Values.agent.tag }}
+ {{ fail "`controller.agent.tag` no longer exists. It has been renamed to `controller.agent.image.tag`" }}
+ {{- end }}
+
+ {{- if .Values.backup }}
+ {{ fail "`controller.backup` no longer exists." }}
+ {{- end }}
+
+ {{- if .Values.helmtest.bats.tag }}
+ {{ fail "`helmtest.bats.tag` no longer exists. It has been renamed to `helmtest.bats.image.tag`" }}
+ {{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/home-pvc.yaml b/charts/jenkins/templates/home-pvc.yaml
new file mode 100644
index 0000000..f417d23
--- /dev/null
+++ b/charts/jenkins/templates/home-pvc.yaml
@@ -0,0 +1,41 @@
+{{- if not (contains "jenkins-home" (quote .Values.persistence.volumes)) }}
+{{- if and .Values.persistence.enabled (not .Values.persistence.existingClaim) -}}
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+{{- if .Values.persistence.annotations }}
+ annotations:
+{{ toYaml .Values.persistence.annotations | indent 4 }}
+{{- end }}
+ name: {{ template "jenkins.fullname" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- if .Values.persistence.labels }}
+{{ toYaml .Values.persistence.labels | indent 4 }}
+{{- end }}
+spec:
+{{- if .Values.persistence.dataSource }}
+ dataSource:
+{{ toYaml .Values.persistence.dataSource | indent 4 }}
+{{- end }}
+ accessModes:
+ - {{ .Values.persistence.accessMode | quote }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size | quote }}
+{{- if .Values.persistence.storageClass }}
+{{- if (eq "-" .Values.persistence.storageClass) }}
+ storageClassName: ""
+{{- else }}
+ storageClassName: "{{ .Values.persistence.storageClass }}"
+{{- end }}
+{{- end }}
+{{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/jcasc-config.yaml b/charts/jenkins/templates/jcasc-config.yaml
new file mode 100644
index 0000000..e404194
--- /dev/null
+++ b/charts/jenkins/templates/jcasc-config.yaml
@@ -0,0 +1,45 @@
+{{- $root := . }}
+{{- if .Values.controller.sidecars.configAutoReload.enabled }}
+{{- range $key, $val := .Values.controller.JCasC.configScripts }}
+{{- if $val }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "jenkins.casc.configName" (list (printf "config-%s" $key) $ )}}
+ namespace: {{ template "jenkins.namespace" $root }}
+ labels:
+ "app.kubernetes.io/name": {{ template "jenkins.name" $root}}
+ {{- if $root.Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ $root.Chart.Name }}-{{ $root.Chart.Version }}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
+ "app.kubernetes.io/instance": "{{ $.Release.Name }}"
+ "app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
+ {{ template "jenkins.fullname" $root }}-jenkins-config: "true"
+data:
+ {{ $key }}.yaml: |-
+{{ tpl $val $| indent 4 }}
+{{- end }}
+{{- end }}
+{{- if .Values.controller.JCasC.defaultConfig }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "jenkins.casc.configName" (list "jcasc-config" $ )}}
+ namespace: {{ template "jenkins.namespace" $root }}
+ labels:
+ "app.kubernetes.io/name": {{ template "jenkins.name" $root}}
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ $root.Chart.Name }}-{{ $root.Chart.Version }}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
+ "app.kubernetes.io/instance": "{{ $.Release.Name }}"
+ "app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
+ {{ template "jenkins.fullname" $root }}-jenkins-config: "true"
+data:
+ jcasc-default-config.yaml: |-
+ {{- include "jenkins.casc.defaults" . | nindent 4 }}
+{{- end}}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-agent-svc.yaml b/charts/jenkins/templates/jenkins-agent-svc.yaml
new file mode 100644
index 0000000..4440b91
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-agent-svc.yaml
@@ -0,0 +1,43 @@
+{{- if .Values.controller.agentListenerEnabled }}
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ template "jenkins.fullname" . }}-agent
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- if .Values.controller.agentListenerServiceAnnotations }}
+ annotations:
+ {{- toYaml .Values.controller.agentListenerServiceAnnotations | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.controller.agentListenerExternalTrafficPolicy }}
+ externalTrafficPolicy: {{.Values.controller.agentListenerExternalTrafficPolicy}}
+ {{- end }}
+ ports:
+ - port: {{ .Values.controller.agentListenerPort }}
+ targetPort: {{ .Values.controller.agentListenerPort }}
+ {{- if (and (eq .Values.controller.agentListenerServiceType "NodePort") (not (empty .Values.controller.agentListenerNodePort))) }}
+ nodePort: {{ .Values.controller.agentListenerNodePort }}
+ {{- end }}
+ name: agent-listener
+ selector:
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ type: {{ .Values.controller.agentListenerServiceType }}
+ {{if eq .Values.controller.agentListenerServiceType "LoadBalancer"}}
+{{- if .Values.controller.agentListenerLoadBalancerSourceRanges }}
+ loadBalancerSourceRanges:
+{{ toYaml .Values.controller.agentListenerLoadBalancerSourceRanges | indent 4 }}
+{{- end }}
+ {{- end }}
+ {{- if and (eq .Values.controller.agentListenerServiceType "LoadBalancer") (.Values.controller.agentListenerLoadBalancerIP) }}
+ loadBalancerIP: {{ .Values.controller.agentListenerLoadBalancerIP }}
+ {{- end }}
+ {{- end }}
diff --git a/charts/jenkins/templates/jenkins-aws-security-group-policies.yaml b/charts/jenkins/templates/jenkins-aws-security-group-policies.yaml
new file mode 100644
index 0000000..2f6e7a1
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-aws-security-group-policies.yaml
@@ -0,0 +1,16 @@
+{{- if .Values.awsSecurityGroupPolicies.enabled -}}
+{{- range .Values.awsSecurityGroupPolicies.policies -}}
+apiVersion: vpcresources.k8s.aws/v1beta1
+kind: SecurityGroupPolicy
+metadata:
+ name: {{ .name }}
+ namespace: {{ template "jenkins.namespace" $ }}
+spec:
+ podSelector:
+ {{- toYaml .podSelector | nindent 6}}
+ securityGroups:
+ groupIds:
+ {{- toYaml .securityGroupIds | nindent 6}}
+---
+{{- end -}}
+{{- end -}}
diff --git a/charts/jenkins/templates/jenkins-controller-alerting-rules.yaml b/charts/jenkins/templates/jenkins-controller-alerting-rules.yaml
new file mode 100644
index 0000000..3fd8061
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-alerting-rules.yaml
@@ -0,0 +1,26 @@
+{{- if and .Values.controller.prometheus.enabled .Values.controller.prometheus.alertingrules }}
+---
+apiVersion: monitoring.coreos.com/v1
+kind: PrometheusRule
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+{{- if .Values.controller.prometheus.prometheusRuleNamespace }}
+ namespace: {{ .Values.controller.prometheus.prometheusRuleNamespace }}
+{{- else }}
+ namespace: {{ template "jenkins.namespace" . }}
+{{- end }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- range $key, $val := .Values.controller.prometheus.alertingRulesAdditionalLabels }}
+ {{ $key }}: {{ $val | quote }}
+ {{- end}}
+spec:
+ groups:
+{{ toYaml .Values.controller.prometheus.alertingrules | indent 2 }}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-backendconfig.yaml b/charts/jenkins/templates/jenkins-controller-backendconfig.yaml
new file mode 100644
index 0000000..0e8a566
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-backendconfig.yaml
@@ -0,0 +1,24 @@
+{{- if .Values.controller.backendconfig.enabled }}
+apiVersion: {{ .Values.controller.backendconfig.apiVersion }}
+kind: BackendConfig
+metadata:
+ name: {{ .Values.controller.backendconfig.name }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- if .Values.controller.backendconfig.labels }}
+{{ toYaml .Values.controller.backendconfig.labels | indent 4 }}
+{{- end }}
+{{- if .Values.controller.backendconfig.annotations }}
+ annotations:
+{{ toYaml .Values.controller.backendconfig.annotations | indent 4 }}
+{{- end }}
+spec:
+{{ toYaml .Values.controller.backendconfig.spec | indent 2 }}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-ingress.yaml b/charts/jenkins/templates/jenkins-controller-ingress.yaml
new file mode 100644
index 0000000..b3b344f
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-ingress.yaml
@@ -0,0 +1,77 @@
+{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
+{{- if .Values.controller.ingress.enabled }}
+{{- if semverCompare ">=1.19-0" $kubeTargetVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" $kubeTargetVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: {{ .Values.controller.ingress.apiVersion }}
+{{- end }}
+kind: Ingress
+metadata:
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- if .Values.controller.ingress.labels }}
+{{ toYaml .Values.controller.ingress.labels | indent 4 }}
+{{- end }}
+{{- if .Values.controller.ingress.annotations }}
+ annotations:
+{{ toYaml .Values.controller.ingress.annotations | indent 4 }}
+{{- end }}
+ name: {{ template "jenkins.fullname" . }}
+spec:
+{{- if .Values.controller.ingress.ingressClassName }}
+ ingressClassName: {{ .Values.controller.ingress.ingressClassName | quote }}
+{{- end }}
+ rules:
+ - http:
+ paths:
+{{- if empty (.Values.controller.ingress.paths) }}
+ - backend:
+{{- if semverCompare ">=1.19-0" $kubeTargetVersion }}
+ service:
+ name: {{ template "jenkins.fullname" . }}
+ port:
+ number: {{ .Values.controller.servicePort }}
+ pathType: ImplementationSpecific
+{{- else }}
+ serviceName: {{ template "jenkins.fullname" . }}
+ servicePort: {{ .Values.controller.servicePort }}
+{{- end }}
+{{- if .Values.controller.ingress.path }}
+ path: {{ .Values.controller.ingress.path }}
+{{- end -}}
+{{- else }}
+{{ tpl (toYaml .Values.controller.ingress.paths | indent 6) . }}
+{{- end -}}
+{{- if .Values.controller.ingress.hostName }}
+ host: {{ tpl .Values.controller.ingress.hostName . | quote }}
+{{- end }}
+{{- if .Values.controller.ingress.resourceRootUrl }}
+ - http:
+ paths:
+ - backend:
+{{- if semverCompare ">=1.19-0" $kubeTargetVersion }}
+ service:
+ name: {{ template "jenkins.fullname" . }}
+ port:
+ number: {{ .Values.controller.servicePort }}
+ pathType: ImplementationSpecific
+{{- else }}
+ serviceName: {{ template "jenkins.fullname" . }}
+ servicePort: {{ .Values.controller.servicePort }}
+{{- end }}
+ host: {{ tpl .Values.controller.ingress.resourceRootUrl . | quote }}
+{{- end }}
+{{- if .Values.controller.ingress.tls }}
+ tls:
+{{ tpl (toYaml .Values.controller.ingress.tls ) . | indent 4 }}
+{{- end -}}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-networkpolicy.yaml b/charts/jenkins/templates/jenkins-controller-networkpolicy.yaml
new file mode 100644
index 0000000..82835f2
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-networkpolicy.yaml
@@ -0,0 +1,76 @@
+{{- if .Values.networkPolicy.enabled }}
+kind: NetworkPolicy
+apiVersion: {{ .Values.networkPolicy.apiVersion }}
+metadata:
+ name: "{{ .Release.Name }}-{{ .Values.controller.componentName }}"
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+spec:
+ podSelector:
+ matchLabels:
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ ingress:
+ # Allow web access to the UI
+ - ports:
+ - port: {{ .Values.controller.targetPort }}
+ {{- if .Values.controller.agentListenerEnabled }}
+ # Allow inbound connections from agents
+ - from:
+ {{- if .Values.networkPolicy.internalAgents.allowed }}
+ - podSelector:
+ matchLabels:
+ "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}": "true"
+ {{- range $k,$v:= .Values.networkPolicy.internalAgents.podLabels }}
+ {{ $k }}: {{ $v }}
+ {{- end }}
+ {{- if .Values.networkPolicy.internalAgents.namespaceLabels }}
+ namespaceSelector:
+ matchLabels:
+ {{- range $k,$v:= .Values.networkPolicy.internalAgents.namespaceLabels }}
+ {{ $k }}: {{ $v }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ {{- if or .Values.networkPolicy.externalAgents.ipCIDR .Values.networkPolicy.externalAgents.except }}
+ - ipBlock:
+ cidr: {{ required "ipCIDR is required if you wish to allow external agents to connect to Jenkins Controller." .Values.networkPolicy.externalAgents.ipCIDR }}
+ {{- if .Values.networkPolicy.externalAgents.except }}
+ except:
+ {{- range .Values.networkPolicy.externalAgents.except }}
+ - {{ . }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+ ports:
+ - port: {{ .Values.controller.agentListenerPort }}
+ {{- end }}
+{{- if .Values.agent.enabled }}
+---
+kind: NetworkPolicy
+apiVersion: {{ .Values.networkPolicy.apiVersion }}
+metadata:
+ name: "{{ .Release.Name }}-{{ .Values.agent.componentName }}"
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+spec:
+ podSelector:
+ matchLabels:
+ # DefaultDeny
+ "jenkins/{{ .Release.Name }}-{{ .Values.agent.componentName }}": "true"
+{{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-pdb.yaml b/charts/jenkins/templates/jenkins-controller-pdb.yaml
new file mode 100644
index 0000000..9dc1faf
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-pdb.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.controller.podDisruptionBudget.enabled }}
+{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
+{{- if semverCompare ">=1.21-0" $kubeTargetVersion -}}
+apiVersion: policy/v1
+{{- else if semverCompare ">=1.5-0" $kubeTargetVersion -}}
+apiVersion: policy/v1beta1
+{{- else -}}
+apiVersion: {{ .Values.controller.podDisruptionBudget.apiVersion }}
+{{- end }}
+kind: PodDisruptionBudget
+metadata:
+ name: {{ template "jenkins.fullname" . }}-pdb
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- if .Values.controller.podDisruptionBudget.labels -}}
+ {{ toYaml .Values.controller.podDisruptionBudget.labels | nindent 4 }}
+ {{- end }}
+ {{- if .Values.controller.podDisruptionBudget.annotations }}
+ annotations: {{ toYaml .Values.controller.podDisruptionBudget.annotations | nindent 4 }}
+ {{- end }}
+spec:
+ maxUnavailable: {{ .Values.controller.podDisruptionBudget.maxUnavailable }}
+ selector:
+ matchLabels:
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-podmonitor.yaml b/charts/jenkins/templates/jenkins-controller-podmonitor.yaml
new file mode 100644
index 0000000..9a04019
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-podmonitor.yaml
@@ -0,0 +1,30 @@
+{{- if .Values.controller.googlePodMonitor.enabled }}
+apiVersion: monitoring.googleapis.com/v1
+kind: PodMonitoring
+
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+{{- if .Values.controller.googlePodMonitor.serviceMonitorNamespace }}
+ namespace: {{ .Values.controller.googlePodMonitor.serviceMonitorNamespace }}
+{{- else }}
+ namespace: {{ template "jenkins.namespace" . }}
+{{- end }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+
+spec:
+ endpoints:
+ - interval: {{ .Values.controller.googlePodMonitor.scrapeInterval }}
+ port: http
+ path: {{ .Values.controller.jenkinsUriPrefix }}{{ .Values.controller.googlePodMonitor.scrapeEndpoint }}
+ selector:
+ matchLabels:
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-route.yaml b/charts/jenkins/templates/jenkins-controller-route.yaml
new file mode 100644
index 0000000..3550380
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-route.yaml
@@ -0,0 +1,34 @@
+{{- if .Values.controller.route.enabled }}
+apiVersion: route.openshift.io/v1
+kind: Route
+metadata:
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ app: {{ template "jenkins.fullname" . }}
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ release: "{{ .Release.Name }}"
+ heritage: "{{ .Release.Service }}"
+ component: "{{ .Release.Name }}-{{ .Values.controller.componentName }}"
+{{- if .Values.controller.route.labels }}
+{{ toYaml .Values.controller.route.labels | indent 4 }}
+{{- end }}
+{{- if .Values.controller.route.annotations }}
+ annotations:
+{{ toYaml .Values.controller.route.annotations | indent 4 }}
+{{- end }}
+ name: {{ template "jenkins.fullname" . }}
+spec:
+ host: {{ .Values.controller.route.path }}
+ port:
+ targetPort: http
+ tls:
+ insecureEdgeTerminationPolicy: Redirect
+ termination: edge
+ to:
+ kind: Service
+ name: {{ template "jenkins.fullname" . }}
+ weight: 100
+ wildcardPolicy: None
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-secondary-ingress.yaml b/charts/jenkins/templates/jenkins-controller-secondary-ingress.yaml
new file mode 100644
index 0000000..c63e482
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-secondary-ingress.yaml
@@ -0,0 +1,56 @@
+{{- if .Values.controller.secondaryingress.enabled }}
+{{- $kubeTargetVersion := default .Capabilities.KubeVersion.GitVersion .Values.kubeTargetVersionOverride }}
+{{- $serviceName := include "jenkins.fullname" . -}}
+{{- $servicePort := .Values.controller.servicePort -}}
+{{- if semverCompare ">=1.19-0" $kubeTargetVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" $kubeTargetVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: {{ .Values.controller.secondaryingress.apiVersion }}
+{{- end }}
+kind: Ingress
+metadata:
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- if .Values.controller.secondaryingress.labels -}}
+ {{ toYaml .Values.controller.secondaryingress.labels | nindent 4 }}
+ {{- end }}
+ {{- if .Values.controller.secondaryingress.annotations }}
+ annotations: {{ toYaml .Values.controller.secondaryingress.annotations | nindent 4 }}
+ {{- end }}
+ name: {{ template "jenkins.fullname" . }}-secondary
+spec:
+{{- if .Values.controller.secondaryingress.ingressClassName }}
+ ingressClassName: {{ .Values.controller.secondaryingress.ingressClassName | quote }}
+{{- end }}
+ rules:
+ - host: {{ .Values.controller.secondaryingress.hostName }}
+ http:
+ paths:
+ {{- range .Values.controller.secondaryingress.paths }}
+ - path: {{ . | quote }}
+ backend:
+{{ if semverCompare ">=1.19-0" $kubeTargetVersion }}
+ service:
+ name: {{ $serviceName }}
+ port:
+ number: {{ $servicePort }}
+ pathType: ImplementationSpecific
+{{ else }}
+ serviceName: {{ $serviceName }}
+ servicePort: {{ $servicePort }}
+{{ end }}
+ {{- end}}
+{{- if .Values.controller.secondaryingress.tls }}
+ tls:
+{{ toYaml .Values.controller.secondaryingress.tls | indent 4 }}
+{{- end -}}
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-servicemonitor.yaml b/charts/jenkins/templates/jenkins-controller-servicemonitor.yaml
new file mode 100644
index 0000000..8710b2b
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-servicemonitor.yaml
@@ -0,0 +1,45 @@
+{{- if and .Values.controller.prometheus.enabled }}
+apiVersion: monitoring.coreos.com/v1
+kind: ServiceMonitor
+
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+{{- if .Values.controller.prometheus.serviceMonitorNamespace }}
+ namespace: {{ .Values.controller.prometheus.serviceMonitorNamespace }}
+{{- else }}
+ namespace: {{ template "jenkins.namespace" . }}
+{{- end }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- range $key, $val := .Values.controller.prometheus.serviceMonitorAdditionalLabels }}
+ {{ $key }}: {{ $val | quote }}
+ {{- end}}
+
+spec:
+ endpoints:
+ - interval: {{ .Values.controller.prometheus.scrapeInterval }}
+ port: http
+ path: {{ .Values.controller.jenkinsUriPrefix }}{{ .Values.controller.prometheus.scrapeEndpoint }}
+ {{- with .Values.controller.prometheus.relabelings }}
+ relabelings:
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ {{- with .Values.controller.prometheus.metricRelabelings }}
+ metricRelabelings:
+ {{- toYaml . | nindent 6 }}
+ {{- end }}
+ jobLabel: {{ template "jenkins.fullname" . }}
+ namespaceSelector:
+ matchNames:
+ - "{{ template "jenkins.namespace" $ }}"
+ selector:
+ matchLabels:
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- end }}
diff --git a/charts/jenkins/templates/jenkins-controller-statefulset.yaml b/charts/jenkins/templates/jenkins-controller-statefulset.yaml
new file mode 100644
index 0000000..ca0edc6
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-statefulset.yaml
@@ -0,0 +1,413 @@
+{{- if .Capabilities.APIVersions.Has "apps/v1" }}
+apiVersion: apps/v1
+{{- else }}
+apiVersion: apps/v1beta1
+{{- end }}
+kind: StatefulSet
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- range $key, $val := .Values.controller.statefulSetLabels }}
+ {{ $key }}: {{ $val | quote }}
+ {{- end}}
+ {{- if .Values.controller.statefulSetAnnotations }}
+ annotations:
+{{ toYaml .Values.controller.statefulSetAnnotations | indent 4 }}
+ {{- end }}
+spec:
+ serviceName: {{ template "jenkins.fullname" . }}
+ replicas: 1
+ selector:
+ matchLabels:
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ {{- if .Values.controller.updateStrategy }}
+ updateStrategy:
+{{ toYaml .Values.controller.updateStrategy | indent 4 }}
+ {{- end }}
+ template:
+ metadata:
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- range $key, $val := .Values.controller.podLabels }}
+ {{ $key }}: {{ $val | quote }}
+ {{- end}}
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/config.yaml") . | sha256sum }}
+ {{- if .Values.controller.initScripts }}
+ checksum/config-init-scripts: {{ include (print $.Template.BasePath "/config-init-scripts.yaml") . | sha256sum }}
+ {{- end }}
+ {{- if .Values.controller.podAnnotations }}
+{{ tpl (toYaml .Values.controller.podAnnotations | indent 8) . }}
+ {{- end }}
+ spec:
+ {{- if .Values.controller.schedulerName }}
+ schedulerName: {{ .Values.controller.schedulerName }}
+ {{- end }}
+ {{- if .Values.controller.nodeSelector }}
+ nodeSelector:
+{{ toYaml .Values.controller.nodeSelector | indent 8 }}
+ {{- end }}
+ {{- if .Values.controller.tolerations }}
+ tolerations:
+{{ toYaml .Values.controller.tolerations | indent 8 }}
+ {{- end }}
+ {{- if .Values.controller.affinity }}
+ affinity:
+{{ toYaml .Values.controller.affinity | indent 8 }}
+ {{- end }}
+ {{- if quote .Values.controller.terminationGracePeriodSeconds }}
+ terminationGracePeriodSeconds: {{ .Values.controller.terminationGracePeriodSeconds }}
+ {{- end }}
+ {{- if .Values.controller.priorityClassName }}
+ priorityClassName: {{ .Values.controller.priorityClassName }}
+ {{- end }}
+ {{- if .Values.controller.shareProcessNamespace }}
+ shareProcessNamespace: true
+ {{- end }}
+{{- if .Values.controller.usePodSecurityContext }}
+ securityContext:
+ {{- if kindIs "map" .Values.controller.podSecurityContextOverride }}
+ {{- tpl (toYaml .Values.controller.podSecurityContextOverride | nindent 8) . -}}
+ {{- else }}
+ {{/* The rest of this section should be replaced with the contents of this comment one the runAsUser, fsGroup, and securityContextCapabilities Helm chart values have been removed:
+ runAsUser: 1000
+ fsGroup: 1000
+ runAsNonRoot: true
+ */}}
+ runAsUser: {{ default 0 .Values.controller.runAsUser }}
+ {{- if and (.Values.controller.runAsUser) (.Values.controller.fsGroup) }}
+ {{- if not (eq (int .Values.controller.runAsUser) 0) }}
+ fsGroup: {{ .Values.controller.fsGroup }}
+ runAsNonRoot: true
+ {{- end }}
+ {{- if .Values.controller.securityContextCapabilities }}
+ capabilities:
+ {{- toYaml .Values.controller.securityContextCapabilities | nindent 10 }}
+ {{- end }}
+ {{- end }}
+ {{- end }}
+{{- end }}
+ serviceAccountName: "{{ template "jenkins.serviceAccountName" . }}"
+{{- if .Values.controller.hostNetworking }}
+ hostNetwork: true
+ dnsPolicy: ClusterFirstWithHostNet
+{{- end }}
+ {{- if .Values.controller.hostAliases }}
+ hostAliases:
+ {{- toYaml .Values.controller.hostAliases | nindent 8 }}
+ {{- end }}
+ initContainers:
+{{- if .Values.controller.customInitContainers }}
+{{ tpl (toYaml .Values.controller.customInitContainers) . | indent 8 }}
+{{- end }}
+
+{{- if .Values.controller.sidecars.configAutoReload.enabled }}
+{{- include "jenkins.configReloadContainer" (list $ "config-reload-init" "init") | nindent 8 }}
+{{- end}}
+
+ - name: "init"
+ image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
+ imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
+ {{- if .Values.controller.containerSecurityContext }}
+ securityContext: {{- toYaml .Values.controller.containerSecurityContext | nindent 12 }}
+ {{- end }}
+ command: [ "sh", "/var/jenkins_config/apply_config.sh" ]
+ {{- if .Values.controller.initContainerEnvFrom }}
+ envFrom:
+{{ (tpl (toYaml .Values.controller.initContainerEnvFrom) .) | indent 12 }}
+ {{- end }}
+ {{- if .Values.controller.initContainerEnv }}
+ env:
+{{ (tpl (toYaml .Values.controller.initContainerEnv) .) | indent 12 }}
+ {{- end }}
+ resources:
+{{- if .Values.controller.initContainerResources }}
+{{ toYaml .Values.controller.initContainerResources | indent 12 }}
+{{- else }}
+{{ toYaml .Values.controller.resources | indent 12 }}
+{{- end }}
+ volumeMounts:
+ {{- if .Values.persistence.mounts }}
+{{ toYaml .Values.persistence.mounts | indent 12 }}
+ {{- end }}
+ - mountPath: {{ .Values.controller.jenkinsHome }}
+ name: jenkins-home
+ {{- if .Values.persistence.subPath }}
+ subPath: {{ .Values.persistence.subPath }}
+ {{- end }}
+ - mountPath: /var/jenkins_config
+ name: jenkins-config
+ {{- if .Values.controller.installPlugins }}
+ {{- if .Values.controller.overwritePluginsFromImage }}
+ - mountPath: {{ .Values.controller.jenkinsRef }}/plugins
+ name: plugins
+ {{- end }}
+ - mountPath: /var/jenkins_plugins
+ name: plugin-dir
+ - mountPath: /tmp
+ name: tmp-volume
+ {{- end }}
+ {{- if or .Values.controller.initScripts .Values.controller.initConfigMap }}
+ - mountPath: {{ .Values.controller.jenkinsHome }}/init.groovy.d
+ name: init-scripts
+ {{- end }}
+ {{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
+ {{- $httpsJKSDirPath := printf "%s" .Values.controller.httpsKeyStore.path }}
+ - mountPath: {{ $httpsJKSDirPath }}
+ name: jenkins-https-keystore
+ {{- end }}
+ containers:
+ - name: jenkins
+ image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
+ imagePullPolicy: "{{ .Values.controller.image.pullPolicy }}"
+ {{- if .Values.controller.containerSecurityContext }}
+ securityContext: {{- toYaml .Values.controller.containerSecurityContext | nindent 12 }}
+ {{- end }}
+ {{- if .Values.controller.overrideArgs }}
+ args: [
+ {{- range $overrideArg := .Values.controller.overrideArgs }}
+ "{{- tpl $overrideArg $ }}",
+ {{- end }}
+ ]
+ {{- else if .Values.controller.httpsKeyStore.enable }}
+ {{- $httpsJKSFilePath := printf "%s/%s" .Values.controller.httpsKeyStore.path .Values.controller.httpsKeyStore.fileName }}
+ args: [ "--httpPort={{.Values.controller.httpsKeyStore.httpPort}}", "--httpsPort={{.Values.controller.targetPort}}", '--httpsKeyStore={{ $httpsJKSFilePath }}', "--httpsKeyStorePassword=$(JENKINS_HTTPS_KEYSTORE_PASSWORD)" ]
+ {{- else }}
+ args: [ "--httpPort={{.Values.controller.targetPort}}"]
+ {{- end }}
+ {{- if .Values.controller.lifecycle }}
+ lifecycle:
+{{ toYaml .Values.controller.lifecycle | indent 12 }}
+ {{- end }}
+{{- if .Values.controller.terminationMessagePath }}
+ terminationMessagePath: {{ .Values.controller.terminationMessagePath }}
+{{- end }}
+{{- if .Values.controller.terminationMessagePolicy }}
+ terminationMessagePolicy: {{ .Values.controller.terminationMessagePolicy }}
+{{- end }}
+ {{- if .Values.controller.containerEnvFrom }}
+ envFrom:
+{{ (tpl ( toYaml .Values.controller.containerEnvFrom) .) | indent 12 }}
+ {{- end }}
+ env:
+ {{- if .Values.controller.containerEnv }}
+{{ (tpl ( toYaml .Values.controller.containerEnv) .) | indent 12 }}
+ {{- end }}
+ {{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
+ - name: SECRETS
+ value: /run/secrets/additional
+ {{- end }}
+ - name: POD_NAME
+ valueFrom:
+ fieldRef:
+ fieldPath: metadata.name
+ - name: JAVA_OPTS
+ value: >-
+ {{ if .Values.controller.sidecars.configAutoReload.enabled }} -Dcasc.reload.token=$(POD_NAME) {{ end }}{{ default "" .Values.controller.javaOpts }}
+ - name: JENKINS_OPTS
+ value: >-
+ {{ if .Values.controller.jenkinsUriPrefix }}--prefix={{ .Values.controller.jenkinsUriPrefix }} {{ end }} --webroot=/var/jenkins_cache/war {{ default "" .Values.controller.jenkinsOpts}}
+ - name: JENKINS_SLAVE_AGENT_PORT
+ value: "{{ .Values.controller.agentListenerPort }}"
+ {{- if .Values.controller.httpsKeyStore.enable }}
+ - name: JENKINS_HTTPS_KEYSTORE_PASSWORD
+ {{- if not .Values.controller.httpsKeyStore.disableSecretMount }}
+ valueFrom:
+ secretKeyRef:
+ name: {{ if .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName }} {{ else if .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ else }} {{ template "jenkins.fullname" . }}-https-jks {{ end }}
+ key: "{{ .Values.controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretKey }}"
+ {{- else }}
+ value: {{ .Values.controller.httpsKeyStore.password }}
+ {{- end }}
+ {{- end }}
+
+ - name: CASC_JENKINS_CONFIG
+ value: {{ .Values.controller.sidecars.configAutoReload.folder | default (printf "%s/casc_configs" (.Values.controller.jenkinsRef)) }}{{- if .Values.controller.JCasC.configUrls }},{{ join "," .Values.controller.JCasC.configUrls }}{{- end }}
+ ports:
+ {{- if .Values.controller.httpsKeyStore.enable }}
+ - containerPort: {{.Values.controller.httpsKeyStore.httpPort}}
+ {{- else }}
+ - containerPort: {{.Values.controller.targetPort}}
+ {{- end }}
+ name: http
+ - containerPort: {{ .Values.controller.agentListenerPort }}
+ name: agent-listener
+ {{- if .Values.controller.agentListenerHostPort }}
+ hostPort: {{ .Values.controller.agentListenerHostPort }}
+ {{- end }}
+ {{- if .Values.controller.jmxPort }}
+ - containerPort: {{ .Values.controller.jmxPort }}
+ name: jmx
+ {{- end }}
+{{- range $index, $port := .Values.controller.extraPorts }}
+ - containerPort: {{ $port.port }}
+ name: {{ $port.name }}
+{{- end }}
+{{- if and .Values.controller.healthProbes .Values.controller.probes}}
+ {{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.GitVersion }}
+ startupProbe:
+{{ tpl (toYaml .Values.controller.probes.startupProbe | indent 12) .}}
+ {{- end }}
+ livenessProbe:
+{{ tpl (toYaml .Values.controller.probes.livenessProbe | indent 12) .}}
+ readinessProbe:
+{{ tpl (toYaml .Values.controller.probes.readinessProbe | indent 12) .}}
+{{- end }}
+ resources:
+{{ toYaml .Values.controller.resources | indent 12 }}
+ volumeMounts:
+{{- if .Values.persistence.mounts }}
+{{ toYaml .Values.persistence.mounts | indent 12 }}
+{{- end }}
+ {{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
+ {{- $httpsJKSDirPath := printf "%s" .Values.controller.httpsKeyStore.path }}
+ - mountPath: {{ $httpsJKSDirPath }}
+ name: jenkins-https-keystore
+ {{- end }}
+ - mountPath: {{ .Values.controller.jenkinsHome }}
+ name: jenkins-home
+ readOnly: false
+ {{- if .Values.persistence.subPath }}
+ subPath: {{ .Values.persistence.subPath }}
+ {{- end }}
+ - mountPath: /var/jenkins_config
+ name: jenkins-config
+ readOnly: true
+ {{- if .Values.controller.installPlugins }}
+ - mountPath: {{ .Values.controller.jenkinsRef }}/plugins/
+ name: plugin-dir
+ readOnly: false
+ {{- end }}
+ {{- if or .Values.controller.initScripts .Values.controller.initConfigMap }}
+ - mountPath: {{ .Values.controller.jenkinsHome }}/init.groovy.d
+ name: init-scripts
+ {{- end }}
+ {{- if .Values.controller.sidecars.configAutoReload.enabled }}
+ - name: sc-config-volume
+ mountPath: {{ .Values.controller.sidecars.configAutoReload.folder | default (printf "%s/casc_configs" (.Values.controller.jenkinsRef)) }}
+ {{- end }}
+ {{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
+ - name: jenkins-secrets
+ mountPath: /run/secrets/additional
+ readOnly: true
+ {{- end }}
+ - name: jenkins-cache
+ mountPath: /var/jenkins_cache
+ - mountPath: /tmp
+ name: tmp-volume
+
+{{- if .Values.controller.sidecars.configAutoReload.enabled }}
+{{- include "jenkins.configReloadContainer" (list $ "config-reload" "sidecar") | nindent 8 }}
+{{- end}}
+
+
+{{- if .Values.controller.sidecars.additionalSidecarContainers}}
+{{ tpl (toYaml .Values.controller.sidecars.additionalSidecarContainers | indent 8) .}}
+{{- end }}
+
+ volumes:
+{{- if .Values.persistence.volumes }}
+{{ tpl (toYaml .Values.persistence.volumes | indent 6) . }}
+{{- end }}
+ {{- if .Values.controller.installPlugins }}
+ {{- if .Values.controller.overwritePluginsFromImage }}
+ - name: plugins
+ emptyDir: {}
+ {{- end }}
+ {{- end }}
+ {{- if and .Values.controller.initScripts .Values.controller.initConfigMap }}
+ - name: init-scripts
+ projected:
+ sources:
+ - configMap:
+ name: {{ template "jenkins.fullname" . }}-init-scripts
+ - configMap:
+ name: {{ .Values.controller.initConfigMap }}
+ {{- else if .Values.controller.initConfigMap }}
+ - name: init-scripts
+ configMap:
+ name: {{ .Values.controller.initConfigMap }}
+ {{- else if .Values.controller.initScripts }}
+ - name: init-scripts
+ configMap:
+ name: {{ template "jenkins.fullname" . }}-init-scripts
+ {{- end }}
+ - name: jenkins-config
+ configMap:
+ name: {{ template "jenkins.fullname" . }}
+ {{- if .Values.controller.installPlugins }}
+ - name: plugin-dir
+ emptyDir: {}
+ {{- end }}
+ {{- if or .Values.controller.additionalSecrets .Values.controller.existingSecret .Values.controller.additionalExistingSecrets .Values.controller.admin.createSecret }}
+ - name: jenkins-secrets
+ projected:
+ sources:
+ {{- if .Values.controller.additionalSecrets }}
+ - secret:
+ name: {{ template "jenkins.fullname" . }}-additional-secrets
+ {{- end }}
+ {{- if .Values.controller.additionalExistingSecrets }}
+ {{- range $key, $value := .Values.controller.additionalExistingSecrets }}
+ - secret:
+ name: {{ tpl $value.name $ }}
+ items:
+ - key: {{ tpl $value.keyName $ }}
+ path: {{ tpl $value.name $ }}-{{ tpl $value.keyName $ }}
+ {{- end }}
+ {{- end }}
+ {{- if .Values.controller.admin.createSecret }}
+ - secret:
+ name: {{ .Values.controller.admin.existingSecret | default (include "jenkins.fullname" .) }}
+ items:
+ - key: {{ .Values.controller.admin.userKey | default "jenkins-admin-user" }}
+ path: chart-admin-username
+ - key: {{ .Values.controller.admin.passwordKey | default "jenkins-admin-password" }}
+ path: chart-admin-password
+ {{- end }}
+ {{- if .Values.controller.existingSecret }}
+ - secret:
+ name: {{ .Values.controller.existingSecret }}
+ {{- end }}
+ {{- end }}
+ - name: jenkins-cache
+ emptyDir: {}
+ {{- if not (contains "jenkins-home" (quote .Values.persistence.volumes)) }}
+ - name: jenkins-home
+ {{- if .Values.persistence.enabled }}
+ persistentVolumeClaim:
+ claimName: {{ .Values.persistence.existingClaim | default (include "jenkins.fullname" .) }}
+ {{- else }}
+ emptyDir: {}
+ {{- end -}}
+ {{- end }}
+ - name: sc-config-volume
+ emptyDir: {}
+ - name: tmp-volume
+ emptyDir: {}
+
+ {{- if and .Values.controller.httpsKeyStore.enable (not .Values.controller.httpsKeyStore.disableSecretMount) }}
+ - name: jenkins-https-keystore
+ secret:
+ secretName: {{ if .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName }} {{ else }} {{ template "jenkins.fullname" . }}-https-jks {{ end }}
+ items:
+ - key: {{ .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretKey }}
+ path: {{ .Values.controller.httpsKeyStore.fileName }}
+ {{- end }}
+
+{{- if .Values.controller.imagePullSecretName }}
+ imagePullSecrets:
+ - name: {{ .Values.controller.imagePullSecretName }}
+{{- end -}}
diff --git a/charts/jenkins/templates/jenkins-controller-svc.yaml b/charts/jenkins/templates/jenkins-controller-svc.yaml
new file mode 100644
index 0000000..a83466c
--- /dev/null
+++ b/charts/jenkins/templates/jenkins-controller-svc.yaml
@@ -0,0 +1,56 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{template "jenkins.fullname" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ {{- if .Values.controller.serviceLabels }}
+{{ toYaml .Values.controller.serviceLabels | indent 4 }}
+ {{- end }}
+{{- if .Values.controller.serviceAnnotations }}
+ annotations:
+{{ toYaml .Values.controller.serviceAnnotations | indent 4 }}
+{{- end }}
+spec:
+ {{- if .Values.controller.serviceExternalTrafficPolicy }}
+ externalTrafficPolicy: {{.Values.controller.serviceExternalTrafficPolicy}}
+ {{- end }}
+ {{- if (and (eq .Values.controller.serviceType "ClusterIP") (not (empty .Values.controller.clusterIP))) }}
+ clusterIP: {{.Values.controller.clusterIP}}
+ {{- end }}
+ ports:
+ - port: {{.Values.controller.servicePort}}
+ name: http
+ targetPort: {{ .Values.controller.targetPort }}
+ {{- if (and (eq .Values.controller.serviceType "NodePort") (not (empty .Values.controller.nodePort))) }}
+ nodePort: {{.Values.controller.nodePort}}
+ {{- end }}
+{{- range $index, $port := .Values.controller.extraPorts }}
+ - port: {{ $port.port }}
+ name: {{ $port.name }}
+ {{- if $port.targetPort }}
+ targetPort: {{ $port.targetPort }}
+ {{- else }}
+ targetPort: {{ $port.port }}
+ {{- end -}}
+{{- end }}
+ selector:
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ type: {{.Values.controller.serviceType}}
+ {{if eq .Values.controller.serviceType "LoadBalancer"}}
+{{- if .Values.controller.loadBalancerSourceRanges }}
+ loadBalancerSourceRanges:
+{{ toYaml .Values.controller.loadBalancerSourceRanges | indent 4 }}
+{{- end }}
+ {{if .Values.controller.loadBalancerIP}}
+ loadBalancerIP: {{.Values.controller.loadBalancerIP}}
+ {{end}}
+ {{end}}
diff --git a/charts/jenkins/templates/rbac.yaml b/charts/jenkins/templates/rbac.yaml
new file mode 100644
index 0000000..581cb8d
--- /dev/null
+++ b/charts/jenkins/templates/rbac.yaml
@@ -0,0 +1,149 @@
+{{ if .Values.rbac.create }}
+{{- $serviceName := include "jenkins.fullname" . -}}
+
+# This role is used to allow Jenkins scheduling of agents via Kubernetes plugin.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ $serviceName }}-schedule-agents
+ namespace: {{ template "jenkins.agent.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+rules:
+- apiGroups: [""]
+ resources: ["pods", "pods/exec", "pods/log", "persistentvolumeclaims", "events"]
+ verbs: ["get", "list", "watch"]
+- apiGroups: [""]
+ resources: ["pods", "pods/exec", "persistentvolumeclaims"]
+ verbs: ["create", "delete", "deletecollection", "patch", "update"]
+
+---
+
+# We bind the role to the Jenkins service account. The role binding is created in the namespace
+# where the agents are supposed to run.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ $serviceName }}-schedule-agents
+ namespace: {{ template "jenkins.agent.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ $serviceName }}-schedule-agents
+subjects:
+- kind: ServiceAccount
+ name: {{ template "jenkins.serviceAccountName" .}}
+ namespace: {{ template "jenkins.namespace" . }}
+
+---
+
+{{- if .Values.rbac.readSecrets }}
+# This is needed if you want to use https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/
+# as it needs permissions to get/watch/list Secrets
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ template "jenkins.fullname" . }}-read-secrets
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+rules:
+ - apiGroups: [""]
+ resources: ["secrets"]
+ verbs: ["get", "watch", "list"]
+
+---
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ $serviceName }}-read-secrets
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ template "jenkins.fullname" . }}-read-secrets
+subjects:
+ - kind: ServiceAccount
+ name: {{ template "jenkins.serviceAccountName" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+
+---
+{{- end}}
+
+{{- if .Values.controller.sidecars.configAutoReload.enabled }}
+# The sidecar container which is responsible for reloading configuration changes
+# needs permissions to watch ConfigMaps
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+ name: {{ template "jenkins.fullname" . }}-casc-reload
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+rules:
+- apiGroups: [""]
+ resources: ["configmaps"]
+ verbs: ["get", "watch", "list"]
+
+---
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+ name: {{ $serviceName }}-watch-configmaps
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: Role
+ name: {{ template "jenkins.fullname" . }}-casc-reload
+subjects:
+- kind: ServiceAccount
+ name: {{ template "jenkins.serviceAccountName" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+
+{{- end}}
+
+{{ end }}
diff --git a/charts/jenkins/templates/secret-additional.yaml b/charts/jenkins/templates/secret-additional.yaml
new file mode 100644
index 0000000..d1908aa
--- /dev/null
+++ b/charts/jenkins/templates/secret-additional.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.controller.additionalSecrets -}}
+---
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ template "jenkins.fullname" . }}-additional-secrets
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+type: Opaque
+data:
+{{- range .Values.controller.additionalSecrets }}
+ {{ .name }}: {{ .value | b64enc }}
+{{- end }}
+{{- end }}
diff --git a/charts/jenkins/templates/secret-claims.yaml b/charts/jenkins/templates/secret-claims.yaml
new file mode 100644
index 0000000..e8b6d6c
--- /dev/null
+++ b/charts/jenkins/templates/secret-claims.yaml
@@ -0,0 +1,29 @@
+{{- if .Values.controller.secretClaims -}}
+{{- $r := .Release -}}
+{{- $v := .Values -}}
+{{- $chart := printf "%s-%s" .Chart.Name .Chart.Version -}}
+{{- $namespace := include "jenkins.namespace" . -}}
+{{- $serviceName := include "jenkins.fullname" . -}}
+{{ range .Values.controller.secretClaims }}
+---
+kind: SecretClaim
+apiVersion: vaultproject.io/v1
+metadata:
+ name: {{ $serviceName }}-{{ .name | default .path | lower }}
+ namespace: {{ $namespace }}
+ labels:
+ "app.kubernetes.io/name": '{{ $serviceName }}'
+ {{- if $v.renderHelmLabels }}
+ "helm.sh/chart": "{{ $chart }}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ $r.Service }}"
+ "app.kubernetes.io/instance": "{{ $r.Name }}"
+ "app.kubernetes.io/component": "{{ $v.controller.componentName }}"
+spec:
+ type: {{ .type | default "Opaque" }}
+ path: {{ .path }}
+{{- if .renew }}
+ renew: {{ .renew }}
+{{- end }}
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/charts/jenkins/templates/secret-https-jks.yaml b/charts/jenkins/templates/secret-https-jks.yaml
new file mode 100644
index 0000000..5348de4
--- /dev/null
+++ b/charts/jenkins/templates/secret-https-jks.yaml
@@ -0,0 +1,20 @@
+{{- if and .Values.controller.httpsKeyStore.enable ( not .Values.controller.httpsKeyStore.jenkinsHttpsJksSecretName ) (not .Values.controller.httpsKeyStore.disableSecretMount) -}}
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ template "jenkins.fullname" . }}-https-jks
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+type: Opaque
+data:
+ jenkins-jks-file: |
+{{ .Values.controller.httpsKeyStore.jenkinsKeyStoreBase64Encoded | indent 4 }}
+ https-jks-password: {{ .Values.controller.httpsKeyStore.password | b64enc }}
+{{- end }}
diff --git a/charts/jenkins/templates/secret.yaml b/charts/jenkins/templates/secret.yaml
new file mode 100644
index 0000000..cc6ace1
--- /dev/null
+++ b/charts/jenkins/templates/secret.yaml
@@ -0,0 +1,20 @@
+{{- if and (not .Values.controller.admin.existingSecret) (.Values.controller.admin.createSecret) -}}
+
+apiVersion: v1
+kind: Secret
+metadata:
+ name: {{ template "jenkins.fullname" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+type: Opaque
+data:
+ jenkins-admin-password: {{ template "jenkins.password" . }}
+ jenkins-admin-user: {{ .Values.controller.admin.username | b64enc | quote }}
+{{- end }}
diff --git a/charts/jenkins/templates/service-account-agent.yaml b/charts/jenkins/templates/service-account-agent.yaml
new file mode 100644
index 0000000..48f08ba
--- /dev/null
+++ b/charts/jenkins/templates/service-account-agent.yaml
@@ -0,0 +1,26 @@
+{{ if .Values.serviceAccountAgent.create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "jenkins.serviceAccountAgentName" . }}
+ namespace: {{ template "jenkins.agent.namespace" . }}
+{{- if .Values.serviceAccountAgent.annotations }}
+ annotations:
+{{ tpl (toYaml .Values.serviceAccountAgent.annotations) . | indent 4 }}
+{{- end }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- if .Values.serviceAccountAgent.extraLabels }}
+{{ tpl (toYaml .Values.serviceAccountAgent.extraLabels) . | indent 4 }}
+{{- end }}
+{{- if .Values.serviceAccountAgent.imagePullSecretName }}
+imagePullSecrets:
+ - name: {{ .Values.serviceAccountAgent.imagePullSecretName }}
+{{- end -}}
+{{ end }}
diff --git a/charts/jenkins/templates/service-account.yaml b/charts/jenkins/templates/service-account.yaml
new file mode 100644
index 0000000..b44eb48
--- /dev/null
+++ b/charts/jenkins/templates/service-account.yaml
@@ -0,0 +1,26 @@
+{{ if .Values.serviceAccount.create }}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "jenkins.serviceAccountName" . }}
+ namespace: {{ template "jenkins.namespace" . }}
+{{- if .Values.serviceAccount.annotations }}
+ annotations:
+{{ tpl (toYaml .Values.serviceAccount.annotations) . | indent 4 }}
+{{- end }}
+ labels:
+ "app.kubernetes.io/name": '{{ template "jenkins.name" .}}'
+ {{- if .Values.renderHelmLabels }}
+ "helm.sh/chart": "{{ template "jenkins.label" .}}"
+ {{- end }}
+ "app.kubernetes.io/managed-by": "{{ .Release.Service }}"
+ "app.kubernetes.io/instance": "{{ .Release.Name }}"
+ "app.kubernetes.io/component": "{{ .Values.controller.componentName }}"
+{{- if .Values.serviceAccount.extraLabels }}
+{{ tpl (toYaml .Values.serviceAccount.extraLabels) . | indent 4 }}
+{{- end }}
+{{- if .Values.serviceAccount.imagePullSecretName }}
+imagePullSecrets:
+ - name: {{ .Values.serviceAccount.imagePullSecretName }}
+{{- end -}}
+{{ end }}
diff --git a/charts/jenkins/templates/tests/jenkins-test.yaml b/charts/jenkins/templates/tests/jenkins-test.yaml
new file mode 100644
index 0000000..12a935e
--- /dev/null
+++ b/charts/jenkins/templates/tests/jenkins-test.yaml
@@ -0,0 +1,49 @@
+{{- if .Values.controller.testEnabled }}
+apiVersion: v1
+kind: Pod
+metadata:
+ name: "{{ .Release.Name }}-ui-test-{{ randAlphaNum 5 | lower }}"
+ namespace: {{ template "jenkins.namespace" . }}
+ annotations:
+ "helm.sh/hook": test-success
+spec:
+ {{- if .Values.controller.nodeSelector }}
+ nodeSelector:
+{{ toYaml .Values.controller.nodeSelector | indent 4 }}
+ {{- end }}
+ {{- if .Values.controller.tolerations }}
+ tolerations:
+{{ toYaml .Values.controller.tolerations | indent 4 }}
+ {{- end }}
+ initContainers:
+ - name: "test-framework"
+ image: "{{ .Values.helmtest.bats.image.registry }}/{{ .Values.helmtest.bats.image.repository }}:{{ .Values.helmtest.bats.image.tag }}"
+ command:
+ - "bash"
+ - "-c"
+ args:
+ - |
+ # copy bats to tools dir
+ set -ex
+ cp -R /opt/bats /tools/bats/
+ volumeMounts:
+ - mountPath: /tools
+ name: tools
+ containers:
+ - name: {{ .Release.Name }}-ui-test
+ image: "{{ .Values.controller.image.registry }}/{{ .Values.controller.image.repository }}:{{- include "controller.image.tag" . -}}"
+ command: ["/tools/bats/bin/bats", "-t", "/tests/run.sh"]
+ volumeMounts:
+ - mountPath: /tests
+ name: tests
+ readOnly: true
+ - mountPath: /tools
+ name: tools
+ volumes:
+ - name: tests
+ configMap:
+ name: {{ template "jenkins.fullname" . }}-tests
+ - name: tools
+ emptyDir: {}
+ restartPolicy: Never
+{{- end }}
diff --git a/charts/jenkins/templates/tests/test-config.yaml b/charts/jenkins/templates/tests/test-config.yaml
new file mode 100644
index 0000000..12c5b3a
--- /dev/null
+++ b/charts/jenkins/templates/tests/test-config.yaml
@@ -0,0 +1,14 @@
+{{- if .Values.controller.testEnabled }}
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ template "jenkins.fullname" . }}-tests
+ namespace: {{ template "jenkins.namespace" . }}
+ annotations:
+ "helm.sh/hook": test
+data:
+ run.sh: |-
+ @test "Testing Jenkins UI is accessible" {
+ curl --retry 48 --retry-delay 10 {{ template "jenkins.fullname" . }}:{{ .Values.controller.servicePort }}{{ default "" .Values.controller.jenkinsUriPrefix }}/login
+ }
+{{- end }}