Added chart versions:

jenkins/jenkins:
    - 5.4.3
  speedscale/speedscale-operator:
    - 2.2.185
pull/1059/head
github-actions[bot] 2024-07-20 00:47:03 +00:00
parent f162315458
commit 68c0f03659
57 changed files with 10195 additions and 1 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
annotations:
artifacthub.io/category: integration-delivery
artifacthub.io/changes: |
- Update `configuration-as-code` to version `1836.vccda_4a_122a_a_e`
artifacthub.io/images: |
- name: jenkins
image: docker.io/jenkins/jenkins:2.452.3-jdk17
- name: k8s-sidecar
image: docker.io/kiwigrid/k8s-sidecar:1.27.5
- name: inbound-agent
image: jenkins/inbound-agent:3256.v88a_f6e922152-1
artifacthub.io/license: Apache-2.0
artifacthub.io/links: |
- name: Chart Source
url: https://github.com/jenkinsci/helm-charts/tree/main/charts/jenkins
- name: Jenkins
url: https://www.jenkins.io/
- name: support
url: https://github.com/jenkinsci/helm-charts/issues
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Jenkins
catalog.cattle.io/kube-version: '>=1.14-0'
catalog.cattle.io/release-name: jenkins
apiVersion: v2
appVersion: 2.452.3
description: 'Jenkins - Build great things at any scale! As the leading open source
automation server, Jenkins provides over 1800 plugins to support building, deploying
and automating any project. '
home: https://www.jenkins.io/
icon: file://assets/icons/jenkins.svg
keywords:
- jenkins
- ci
- devops
kubeVersion: '>=1.14-0'
maintainers:
- email: maor.friedman@redhat.com
name: maorfr
- email: mail@torstenwalter.de
name: torstenwalter
- email: garridomota@gmail.com
name: mogaal
- email: wmcdona89@gmail.com
name: wmcdona89
- email: timjacomb1@gmail.com
name: timja
name: jenkins
sources:
- https://github.com/jenkinsci/jenkins
- https://github.com/jenkinsci/docker-inbound-agent
- https://github.com/maorfr/kube-tasks
- https://github.com/jenkinsci/configuration-as-code-plugin
type: application
version: 5.4.3

View File

@ -0,0 +1,706 @@
# Jenkins
[![Artifact Hub](https://img.shields.io/endpoint?url=https://artifacthub.io/badge/repository/jenkins)](https://artifacthub.io/packages/helm/jenkinsci/jenkins)
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
[![Releases downloads](https://img.shields.io/github/downloads/jenkinsci/helm-charts/total.svg)](https://github.com/jenkinsci/helm-charts/releases)
[![Join the chat at https://app.gitter.im/#/room/#jenkins-ci:matrix.org](https://badges.gitter.im/badge.svg)](https://app.gitter.im/#/room/#jenkins-ci:matrix.org)
[Jenkins](https://www.jenkins.io/) is the leading open source automation server, Jenkins provides over 1800 plugins to support building, deploying and automating any project.
This chart installs a Jenkins server which spawns agents on [Kubernetes](http://kubernetes.io) utilizing the [Jenkins Kubernetes plugin](https://plugins.jenkins.io/kubernetes/).
Inspired by the awesome work of [Carlos Sanchez](https://github.com/carlossg).
## Get Repository Info
```console
helm repo add jenkins https://charts.jenkins.io
helm repo update
```
_See [`helm repo`](https://helm.sh/docs/helm/helm_repo/) for command documentation._
## Install Chart
```console
# Helm 3
$ helm install [RELEASE_NAME] jenkins/jenkins [flags]
```
_See [configuration](#configuration) below._
_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
## Uninstall Chart
```console
# Helm 3
$ helm uninstall [RELEASE_NAME]
```
This removes all the Kubernetes components associated with the chart and deletes the release.
_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
## Upgrade Chart
```console
# Helm 3
$ helm upgrade [RELEASE_NAME] jenkins/jenkins [flags]
```
_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
Visit the chart's [CHANGELOG](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/CHANGELOG.md) to view the chart's release history.
For migration between major version check [migration guide](#migration-guide).
## Building weekly releases
The default charts target Long-Term-Support (LTS) releases of Jenkins.
To use other versions the easiest way is to update the image tag to the version you want.
You can also rebuild the chart if you want the `appVersion` field to match.
## Configuration
See [Customizing the Chart Before Installing](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing).
To see all configurable options with detailed comments, visit the chart's [values.yaml](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/values.yaml), or run these configuration commands:
```console
# Helm 3
$ helm show values jenkins/jenkins
```
For a summary of all configurable options, see [VALUES_SUMMARY.md](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md).
### Configure Security Realm and Authorization Strategy
This chart configured a `securityRealm` and `authorizationStrategy` as shown below:
```yaml
controller:
JCasC:
securityRealm: |-
local:
allowsSignup: false
enableCaptcha: false
users:
- id: "${chart-admin-username}"
name: "Jenkins Admin"
password: "${chart-admin-password}"
authorizationStrategy: |-
loggedInUsersCanDoAnything:
allowAnonymousRead: false
```
With the configuration above there is only a single user.
This is fine for getting started quickly, but it needs to be adjusted for any serious environment.
So you should adjust this to suite your needs.
That could be using LDAP / OIDC / .. as authorization strategy and use globalMatrix as authorization strategy to configure more fine-grained permissions.
### Consider using a custom image
This chart allows the user to specify plugins which should be installed. However, for production use cases one should consider to build a custom Jenkins image which has all required plugins pre-installed.
This way you can be sure which plugins Jenkins is using when starting up and you avoid trouble in case of connectivity issues to the Jenkins update site.
The [docker repository](https://github.com/jenkinsci/docker) for the Jenkins image contains [documentation](https://github.com/jenkinsci/docker#preinstalling-plugins) how to do it.
Here is an example how that can be done:
```Dockerfile
FROM jenkins/jenkins:lts
RUN jenkins-plugin-cli --plugins kubernetes workflow-aggregator git configuration-as-code
```
NOTE: If you want a reproducible build then you should specify a non-floating tag for the image `jenkins/jenkins:2.249.3` and specify plugin versions.
Once you built the image and pushed it to your registry you can specify it in your values file like this:
```yaml
controller:
image: "registry/my-jenkins"
tag: "v1.2.3"
installPlugins: false
```
Notice: `installPlugins` is set to false to disable plugin download. In this case, the image `registry/my-jenkins:v1.2.3` must have the plugins specified as default value for [the `controller.installPlugins` directive](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins) to ensure that the configuration side-car system works as expected.
In case you are using a private registry you can use 'imagePullSecretName' to specify the name of the secret to use when pulling the image:
```yaml
controller:
image: "registry/my-jenkins"
tag: "v1.2.3"
imagePullSecretName: registry-secret
installPlugins: false
```
### External URL Configuration
If you are using the ingress definitions provided by this chart via the `controller.ingress` block the configured hostname will be the ingress hostname starting with `https://` or `http://` depending on the `tls` configuration.
The Protocol can be overwritten by specifying `controller.jenkinsUrlProtocol`.
If you are not using the provided ingress you can specify `controller.jenkinsUrl` to change the URL definition.
### Configuration as Code
Jenkins Configuration as Code (JCasC) is now a standard component in the Jenkins project.
To allow JCasC's configuration from the helm values, the plugin [`configuration-as-code`](https://plugins.jenkins.io/configuration-as-code/) must be installed in the Jenkins Controller's Docker image (which is the case by default as specified by the [default value of the directive `controller.installPlugins`](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-plugins)).
JCasc configuration is passed through Helm values under the key `controller.JCasC`.
The section ["Jenkins Configuration as Code (JCasC)" of the page "VALUES_SUMMARY.md"](https://github.com/jenkinsci/helm-charts/blob/main/charts/jenkins/VALUES_SUMMARY.md#jenkins-configuration-as-code-jcasc) lists all the possible directives.
In particular, you may specify custom JCasC scripts by adding sub-key under the `controller.JCasC.configScripts` for each configuration area where each corresponds to a plugin or section of the UI.
The sub-keys (prior to `|` character) are only labels used to give the section a meaningful name.
The only restriction is they must conform to RFC 1123 definition of a DNS label, so they may only contain lowercase letters, numbers, and hyphens.
Each key will become the name of a configuration yaml file on the controller in `/var/jenkins_home/casc_configs` (by default) and will be processed by the Configuration as Code Plugin during Jenkins startup.
The lines after each `|` become the content of the configuration yaml file.
The first line after this is a JCasC root element, e.g. jenkins, credentials, etc.
Best reference is the Documentation link here: `https://<jenkins_url>/configuration-as-code`.
The example below sets custom systemMessage:
```yaml
controller:
JCasC:
configScripts:
welcome-message: |
jenkins:
systemMessage: Welcome to our CI\CD server.
```
More complex example that creates ldap settings:
```yaml
controller:
JCasC:
configScripts:
ldap-settings: |
jenkins:
securityRealm:
ldap:
configurations:
- server: ldap.acme.com
rootDN: dc=acme,dc=uk
managerPasswordSecret: ${LDAP_PASSWORD}
groupMembershipStrategy:
fromUserRecord:
attributeName: "memberOf"
```
Keep in mind that default configuration file already contains some values that you won't be able to override under configScripts section.
For example, you can not configure Jenkins URL and System Admin email address like this because of conflicting configuration error.
Incorrect:
```yaml
controller:
JCasC:
configScripts:
jenkins-url: |
unclassified:
location:
url: https://example.com/jenkins
adminAddress: example@mail.com
```
Correct:
```yaml
controller:
jenkinsUrl: https://example.com/jenkins
jenkinsAdminEmail: example@mail.com
```
Further JCasC examples can be found [here](https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos).
#### Breaking out large Config as Code scripts
Jenkins Config as Code scripts can become quite large, and maintaining all of your scripts within one yaml file can be difficult. The Config as Code plugin itself suggests updating the `CASC_JENKINS_CONFIG` environment variable to be a comma separated list of paths for the plugin to traverse, picking up the yaml files as needed.
However, under the Jenkins helm chart, this `CASC_JENKINS_CONFIG` value is maintained through the templates. A better solution is to split your `controller.JCasC.configScripts` into separate values files, and provide each file during the helm install.
For example, you can have a values file (e.g values_main.yaml) that defines the values described in the `VALUES_SUMMARY.md` for your Jenkins configuration:
```yaml
jenkins:
controller:
jenkinsUrlProtocol: https
installPlugins: false
...
```
In a second file (e.g values_jenkins_casc.yaml), you can define a section of your config scripts:
```yaml
jenkins:
controller:
JCasC:
configScripts:
jenkinsCasc: |
jenkins:
disableRememberMe: false
mode: NORMAL
...
```
And keep extending your config scripts by creating more files (so not all config scripts are located in one yaml file for better maintenance):
values_jenkins_unclassified.yaml
```yaml
jenkins:
controller:
JCasC:
configScripts:
unclassifiedCasc: |
unclassified:
...
```
When installing, you provide all relevant yaml files (e.g `helm install -f values_main.yaml -f values_jenkins_casc.yaml -f values_jenkins_unclassified.yaml ...`). Instead of updating the `CASC_JENKINS_CONFIG` environment variable to include multiple paths, multiple CasC yaml files will be created in the same path `var/jenkins_home/casc_configs`.
#### Config as Code With or Without Auto-Reload
Config as Code changes (to `controller.JCasC.configScripts`) can either force a new pod to be created and only be applied at next startup, or can be auto-reloaded on-the-fly.
If you set `controller.sidecars.configAutoReload.enabled` to `true`, a second, auxiliary container will be installed into the Jenkins controller pod, known as a "sidecar".
This watches for changes to configScripts, copies the content onto the Jenkins file-system and issues a POST to `http://<jenkins_url>/reload-configuration-as-code` with a pre-shared key.
You can monitor this sidecar's logs using command `kubectl logs <controller_pod> -c config-reload -f`.
If you want to enable auto-reload then you also need to configure rbac as the container which triggers the reload needs to watch the config maps:
```yaml
controller:
sidecars:
configAutoReload:
enabled: true
rbac:
create: true
```
### Allow Limited HTML Markup in User-Submitted Text
Some third-party systems (e.g. GitHub) use HTML-formatted data in their payload sent to a Jenkins webhook (e.g. URL of a pull-request being built).
To display such data as processed HTML instead of raw text set `controller.enableRawHtmlMarkupFormatter` to true.
This option requires installation of the [OWASP Markup Formatter Plugin (antisamy-markup-formatter)](https://plugins.jenkins.io/antisamy-markup-formatter/).
This plugin is **not** installed by default but may be added to `controller.additionalPlugins`.
### Change max connections to Kubernetes API
When using agents with containers other than JNLP, The kubernetes plugin will communicate with those containers using the Kubernetes API. this changes the maximum concurrent connections
```yaml
agent:
maxRequestsPerHostStr: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Change container cleanup timeout API
For tasks that use very large images, this timeout can be increased to avoid early termination of the task while the Kubernetes pod is still deploying.
```yaml
agent:
retentionTimeout: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Change seconds to wait for pod to be running
This will change how long Jenkins will wait (seconds) for pod to be in running state.
```yaml
agent:
waitForPodSec: "32"
```
This will change the configuration of the kubernetes "cloud" (as called by jenkins) that is created automatically as part of this helm chart.
### Mounting Volumes into Agent Pods
Your Jenkins Agents will run as pods, and it's possible to inject volumes where needed:
```yaml
agent:
volumes:
- type: Secret
secretName: jenkins-mysecrets
mountPath: /var/run/secrets/jenkins-mysecrets
```
The supported volume types are: `ConfigMap`, `EmptyDir`, `HostPath`, `Nfs`, `PVC`, `Secret`.
Each type supports a different set of configurable attributes, defined by [the corresponding Java class](https://github.com/jenkinsci/kubernetes-plugin/tree/master/src/main/java/org/csanchez/jenkins/plugins/kubernetes/volumes).
### NetworkPolicy
To make use of the NetworkPolicy resources created by default, install [a networking plugin that implements the Kubernetes NetworkPolicy spec](https://kubernetes.io/docs/tasks/administer-cluster/declare-network-policy#before-you-begin).
[Install](#install-chart) helm chart with network policy enabled by setting `networkPolicy.enabled` to `true`.
You can use `controller.networkPolicy.internalAgents` and `controller.networkPolicy.externalAgents` stanzas for fine-grained controls over where internal/external agents can connect from.
Internal ones are allowed based on pod labels and (optionally) namespaces, and external ones are allowed based on IP ranges.
### Script approval list
`controller.scriptApproval` allows to pass function signatures that will be allowed in pipelines.
Example:
```yaml
controller:
scriptApproval:
- "method java.util.Base64$Decoder decode java.lang.String"
- "new java.lang.String byte[]"
- "staticMethod java.util.Base64 getDecoder"
```
### Custom Labels
`controller.serviceLabels` can be used to add custom labels in `jenkins-controller-svc.yaml`.
For example:
```yaml
ServiceLabels:
expose: true
```
### Persistence
The Jenkins image stores persistence under `/var/jenkins_home` path of the container.
A dynamically managed Persistent Volume Claim is used to keep the data across deployments, by default.
This is known to work in GCE, AWS, and minikube. Alternatively, a previously configured Persistent Volume Claim can be used.
It is possible to mount several volumes using `persistence.volumes` and `persistence.mounts` parameters.
See additional `persistence` values using [configuration commands](#configuration).
#### Existing PersistentVolumeClaim
1. Create the PersistentVolume
2. Create the PersistentVolumeClaim
3. [Install](#install-chart) the chart, setting `persistence.existingClaim` to `PVC_NAME`
#### Long Volume Attach/Mount Times
Certain volume type and filesystem format combinations may experience long
attach/mount times, [10 or more minutes][K8S_VOLUME_TIMEOUT], when using
`fsGroup`. This issue may result in the following entries in the pod's event
history:
```console
Warning FailedMount 38m kubelet, aks-default-41587790-2 Unable to attach or mount volumes: unmounted volumes=[jenkins-home], unattached volumes=[plugins plugin-dir jenkins-token-rmq2g sc-config-volume tmp jenkins-home jenkins-config secrets-dir]: timed out waiting for the condition
```
In these cases, experiment with replacing `fsGroup` with
`supplementalGroups` in the pod's `securityContext`. This can be achieved by
setting the `controller.podSecurityContextOverride` Helm chart value to
something like:
```yaml
controller:
podSecurityContextOverride:
runAsNonRoot: true
runAsUser: 1000
supplementalGroups: [1000]
```
This issue has been reported on [azureDisk with ext4][K8S_VOLUME_TIMEOUT] and
on [Alibaba cloud][K8S_VOLUME_TIMEOUT_ALIBABA].
[K8S_VOLUME_TIMEOUT]: https://github.com/kubernetes/kubernetes/issues/67014
[K8S_VOLUME_TIMEOUT_ALIBABA]: https://github.com/kubernetes/kubernetes/issues/67014#issuecomment-698770511
#### Storage Class
It is possible to define which storage class to use, by setting `persistence.storageClass` to `[customStorageClass]`.
If set to a dash (`-`), dynamic provisioning is disabled.
If the storage class is set to null or left undefined (`""`), the default provisioner is used (gp2 on AWS, standard on GKE, AWS & OpenStack).
### Additional Secrets
Additional secrets and Additional Existing Secrets,
can be mounted into the Jenkins controller through the chart or created using `controller.additionalSecrets` or `controller.additionalExistingSecrets`.
A common use case might be identity provider credentials if using an external LDAP or OIDC-based identity provider.
The secret may then be referenced in JCasC configuration (see [JCasC configuration](#configuration-as-code)).
`values.yaml` controller section, referencing mounted secrets:
```yaml
controller:
# the 'name' and 'keyName' are concatenated with a '-' in between, so for example:
# an existing secret "secret-credentials" and a key inside it named "github-password" should be used in Jcasc as ${secret-credentials-github-password}
# 'name' and 'keyName' must be lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-',
# and must start and end with an alphanumeric character (e.g. 'my-name', or '123-abc')
# existingSecret existing secret "secret-credentials" and a key inside it named "github-username" should be used in Jcasc as ${github-username}
# When using existingSecret no need to specify the keyName under additionalExistingSecrets.
existingSecret: secret-credentials
additionalExistingSecrets:
- name: secret-credentials
keyName: github-username
- name: secret-credentials
keyName: github-password
- name: secret-credentials
keyName: token
additionalSecrets:
- name: client_id
value: abc123
- name: client_secret
value: xyz999
JCasC:
securityRealm: |
oic:
clientId: ${client_id}
clientSecret: ${client_secret}
...
configScripts:
jenkins-casc-configs: |
credentials:
system:
domainCredentials:
- credentials:
- string:
description: "github access token"
id: "github_app_token"
scope: GLOBAL
secret: ${secret-credentials-token}
- usernamePassword:
description: "github access username password"
id: "github_username_pass"
password: ${secret-credentials-github-password}
scope: GLOBAL
username: ${secret-credentials-github-username}
```
For more information, see [JCasC documentation](https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/docs/features/secrets.adoc#kubernetes-secrets).
### Secret Claims from HashiCorp Vault
It's possible for this chart to generate `SecretClaim` resources in order to automatically create and maintain Kubernetes `Secrets` from HashiCorp [Vault](https://www.vaultproject.io/) via [`kube-vault-controller`](https://github.com/roboll/kube-vault-controller)
These `Secrets` can then be referenced in the same manner as Additional Secrets above.
This can be achieved by defining required Secret Claims within `controller.secretClaims`, as follows:
```yaml
controller:
secretClaims:
- name: jenkins-secret
path: secret/path
- name: jenkins-short-ttl
path: secret/short-ttl-path
renew: 60
```
### RBAC
RBAC is enabled by default. If you want to disable it you will need to set `rbac.create` to `false`.
### Adding Custom Pod Templates
It is possible to add custom pod templates for the default configured kubernetes cloud.
Add a key under `agent.podTemplates` for each pod template. Each key (prior to `|` character) is just a label, and can be any value.
Keys are only used to give the pod template a meaningful name. The only restriction is they may only contain RFC 1123 \ DNS label characters: lowercase letters, numbers, and hyphens. Each pod template can contain multiple containers.
There's no need to add the _jnlp_ container since the kubernetes plugin will automatically inject it into the pod.
For this pod templates configuration to be loaded the following values must be set:
```yaml
controller.JCasC.defaultConfig: true
```
The example below creates a python pod template in the kubernetes cloud:
```yaml
agent:
podTemplates:
python: |
- name: python
label: jenkins-python
serviceAccount: jenkins
containers:
- name: python
image: python:3
command: "/bin/sh -c"
args: "cat"
ttyEnabled: true
privileged: true
resourceRequestCpu: "400m"
resourceRequestMemory: "512Mi"
resourceLimitCpu: "1"
resourceLimitMemory: "1024Mi"
```
Best reference is `https://<jenkins_url>/configuration-as-code/reference#Cloud-kubernetes`.
### Adding Pod Templates Using additionalAgents
`additionalAgents` may be used to configure additional kubernetes pod templates.
Each additional agent corresponds to `agent` in terms of the configurable values and inherits all values from `agent` so you only need to specify values which differ.
For example:
```yaml
agent:
podName: default
customJenkinsLabels: default
# set resources for additional agents to inherit
resources:
limits:
cpu: "1"
memory: "2048Mi"
additionalAgents:
maven:
podName: maven
customJenkinsLabels: maven
# An example of overriding the jnlp container
# sideContainerName: jnlp
image: jenkins/jnlp-agent-maven
tag: latest
python:
podName: python
customJenkinsLabels: python
sideContainerName: python
image: python
tag: "3"
command: "/bin/sh -c"
args: "cat"
TTYEnabled: true
```
### Ingress Configuration
This chart provides ingress resources configurable via the `controller.ingress` block.
The simplest configuration looks like the following:
```yaml
controller:
ingress:
enabled: true
paths: []
apiVersion: "extensions/v1beta1"
hostName: jenkins.example.com
```
This snippet configures an ingress rule for exposing jenkins at `jenkins.example.com`
You can define labels and annotations via `controller.ingress.labels` and `controller.ingress.annotations` respectively.
Additionally, you can configure the ingress tls via `controller.ingress.tls`.
By default, this ingress rule exposes all paths.
If needed this can be overwritten by specifying the wanted paths in `controller.ingress.paths`
If you want to configure a secondary ingress e.g. you don't want the jenkins instance exposed but still want to receive webhooks you can configure `controller.secondaryingress`.
The secondaryingress doesn't expose anything by default and has to be configured via `controller.secondaryingress.paths`:
```yaml
controller:
ingress:
enabled: true
apiVersion: "extensions/v1beta1"
hostName: "jenkins.internal.example.com"
annotations:
kubernetes.io/ingress.class: "internal"
secondaryingress:
enabled: true
apiVersion: "extensions/v1beta1"
hostName: "jenkins-scm.example.com"
annotations:
kubernetes.io/ingress.class: "public"
paths:
- /github-webhook
```
## Prometheus Metrics
If you want to expose Prometheus metrics you need to install the [Jenkins Prometheus Metrics Plugin](https://github.com/jenkinsci/prometheus-plugin).
It will expose an endpoint (default `/prometheus`) with metrics where a Prometheus Server can scrape.
If you have implemented [Prometheus Operator](https://github.com/prometheus-operator/prometheus-operator), you can set `controller.prometheus.enabled` to `true` to configure a `ServiceMonitor` and `PrometheusRule`.
If you want to further adjust alerting rules you can do so by configuring `controller.prometheus.alertingrules`
If you have implemented Prometheus without using the operator, you can leave `controller.prometheus.enabled` set to `false`.
### Running Behind a Forward Proxy
The controller pod uses an Init Container to install plugins etc. If you are behind a corporate proxy it may be useful to set `controller.initContainerEnv` to add environment variables such as `http_proxy`, so that these can be downloaded.
Additionally, you may want to add env vars for the init container, the Jenkins container, and the JVM (`controller.javaOpts`):
```yaml
controller:
initContainerEnv:
- name: http_proxy
value: "http://192.168.64.1:3128"
- name: https_proxy
value: "http://192.168.64.1:3128"
- name: no_proxy
value: ""
- name: JAVA_OPTS
value: "-Dhttps.proxyHost=proxy_host_name_without_protocol -Dhttps.proxyPort=3128"
containerEnv:
- name: http_proxy
value: "http://192.168.64.1:3128"
- name: https_proxy
value: "http://192.168.64.1:3128"
javaOpts: >-
-Dhttp.proxyHost=192.168.64.1
-Dhttp.proxyPort=3128
-Dhttps.proxyHost=192.168.64.1
-Dhttps.proxyPort=3128
```
### HTTPS Keystore Configuration
[This configuration](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777) enables jenkins to use keystore in order to serve HTTPS.
Here is the [value file section](https://wiki.jenkins.io/pages/viewpage.action?pageId=135468777#RunningJenkinswithnativeSSL/HTTPS-ConfigureJenkinstouseHTTPSandtheJKSkeystore) related to keystore configuration.
Keystore itself should be placed in front of `jenkinsKeyStoreBase64Encoded` key and in base64 encoded format. To achieve that after having `keystore.jks` file simply do this: `cat keystore.jks | base64` and paste the output in front of `jenkinsKeyStoreBase64Encoded`.
After enabling `httpsKeyStore.enable` make sure that `httpPort` and `targetPort` are not the same, as `targetPort` will serve HTTPS.
Do not set `controller.httpsKeyStore.httpPort` to `-1` because it will cause readiness and liveliness prob to fail.
If you already have a kubernetes secret that has keystore and its password you can specify its' name in front of `jenkinsHttpsJksSecretName`, You need to remember that your secret should have proper data key names `jenkins-jks-file` (or override the key name using `jenkinsHttpsJksSecretKey`)
and `https-jks-password` (or override the key name using `jenkinsHttpsJksPasswordSecretKey`; additionally you can make it get the password from a different secret using `jenkinsHttpsJksPasswordSecretName`). Example:
```yaml
controller:
httpsKeyStore:
enable: true
jenkinsHttpsJksSecretName: ''
httpPort: 8081
path: "/var/jenkins_keystore"
fileName: "keystore.jks"
password: "changeit"
jenkinsKeyStoreBase64Encoded: ''
```
### AWS Security Group Policies
To create SecurityGroupPolicies set `awsSecurityGroupPolicies.enabled` to true and add your policies. Each policy requires a `name`, array of `securityGroupIds` and a `podSelector`. Example:
```yaml
awsSecurityGroupPolicies:
enabled: true
policies:
- name: "jenkins-controller"
securityGroupIds:
- sg-123456789
podSelector:
matchExpressions:
- key: app.kubernetes.io/component
operator: In
values:
- jenkins-controller
```
### Agent Direct Connection
Set `directConnection` to `true` to allow agents to connect directly to a given TCP port without having to negotiate a HTTP(S) connection. This can allow you to have agent connections without an external HTTP(S) port. Example:
```yaml
agent:
jenkinsTunnel: "jenkinsci-agent:50000"
directConnection: true
```
## Migration Guide
### From stable repository
Upgrade an existing release from `stable/jenkins` to `jenkins/jenkins` seamlessly by ensuring you have the latest [repository info](#get-repository-info) and running the [upgrade commands](#upgrade-chart) specifying the `jenkins/jenkins` chart.
### Major Version Upgrades
Chart release versions follow [SemVer](../../CONTRIBUTING.md#versioning), where a MAJOR version change (example `1.0.0` -> `2.0.0`) indicates an incompatible breaking change needing manual actions.
See [UPGRADING.md](./UPGRADING.md) for a list of breaking changes

View File

@ -0,0 +1,148 @@
# Upgrade Notes
## To 5.0.0
- `controller.image`, `controller.tag`, and `controller.tagLabel` have been removed. If you want to overwrite the image you now need to configure any or all of:
- `controller.image.registry`
- `controller.image.repository`
- `controller.image.tag`
- `controller.image.tagLabel`
- `controller.imagePullPolicy` has been removed. If you want to overwrite the pull policy you now need to configure `controller.image.pullPolicy`.
- `controller.sidecars.configAutoReload.image` has been removed. If you want to overwrite the configAutoReload image you now need to configure any or all of:
- `controller.sidecars.configAutoReload.image.registry`
- `controller.sidecars.configAutoReload.image.repository`
- `controller.sidecars.configAutoReload.image.tag`
- `controller.sidecars.other` has been renamed to `controller.sidecars.additionalSidecarContainers`.
- `agent.image` and `agent.tag` have been removed. If you want to overwrite the agent image you now need to configure any or all of:
- `agent.image.repository`
- `agent.image.tag`
- The registry can still be overwritten by `agent.jnlpregistry`
- `agent.additionalContainers[*].image` has been renamed to `agent.additionalContainers[*].image.repository`
- `agent.additionalContainers[*].tag` has been renamed to `agent.additionalContainers[*].image.tag`
- `additionalAgents.*.image` has been renamed to `additionalAgents.*.image.repository`
- `additionalAgents.*.tag` has been renamed to `additionalAgents.*.image.tag`
- `additionalClouds.*.additionalAgents.*.image` has been renamed to `additionalClouds.*.additionalAgents.*.image.repository`
- `additionalClouds.*.additionalAgents.*.tag` has been renamed to `additionalClouds.*.additionalAgents.*.image.tag`
- `helmtest.bats.image` has been split up to:
- `helmtest.bats.image.registry`
- `helmtest.bats.image.repository`
- `helmtest.bats.image.tag`
- `controller.adminUsername` and `controller.adminPassword` have been renamed to `controller.admin.username` and `controller.admin.password` respectively
- `controller.adminSecret` has been renamed to `controller.admin.createSecret`
- `backup.*` was unmaintained and has thus been removed. See the following page for alternatives: [Kubernetes Backup and Migrations](https://nubenetes.com/kubernetes-backup-migrations/).
## To 4.0.0
Removes automatic `remotingSecurity` setting when using a container tag older than `2.326` (introduced in [`3.11.7`](./CHANGELOG.md#3117)). If you're using a version older than `2.326`, you should explicitly set `.controller.legacyRemotingSecurityEnabled` to `true`.
## To 3.0.0
* Check `securityRealm` and `authorizationStrategy` and adjust it.
Otherwise, your configured users and permissions will be overridden.
* You need to use helm version 3 as the `Chart.yaml` uses `apiVersion: v2`.
* All XML configuration options have been removed.
In case those are still in use you need to migrate to configuration as code.
Upgrade guide to 2.0.0 contains pointers how to do that.
* Jenkins is now using a `StatefulSet` instead of a `Deployment`
* terminology has been adjusted that's also reflected in values.yaml
The following values from `values.yaml` have been renamed:
* `master` => `controller`
* `master.useSecurity` => `controller.adminSecret`
* `master.slaveListenerPort` => `controller.agentListenerPort`
* `master.slaveHostPort` => `controller.agentListenerHostPort`
* `master.slaveKubernetesNamespace` => `agent.namespace`
* `master.slaveDefaultsProviderTemplate` => `agent.defaultsProviderTemplate`
* `master.slaveJenkinsUrl` => `agent.jenkinsUrl`
* `master.slaveJenkinsTunnel` => `agent.jenkinsTunnel`
* `master.slaveConnectTimeout` => `agent.kubernetesConnectTimeout`
* `master.slaveReadTimeout` => `agent.kubernetesReadTimeout`
* `master.slaveListenerServiceAnnotations` => `controller.agentListenerServiceAnnotations`
* `master.slaveListenerServiceType` => `controller.agentListenerServiceType`
* `master.slaveListenerLoadBalancerIP` => `controller.agentListenerLoadBalancerIP`
* `agent.slaveConnectTimeout` => `agent.connectTimeout`
* Removed values:
* `master.imageTag`: use `controller.image` and `controller.tag` instead
* `slave.imageTag`: use `agent.image` and `agent.tag` instead
## To 2.0.0
Configuration as Code is now default + container does not run as root anymore.
### Configuration as Code new default
Configuration is done via [Jenkins Configuration as Code Plugin](https://github.com/jenkinsci/configuration-as-code-plugin) by default.
That means that changes in values which result in a configuration change are always applied.
In contrast, the XML configuration was only applied during the first start and never altered.
:exclamation::exclamation::exclamation:
Attention:
This also means if you manually altered configuration then this will most likely be reset to what was configured by default.
It also applies to `securityRealm` and `authorizationStrategy` as they are also configured using configuration as code.
:exclamation::exclamation::exclamation:
### Image does not run as root anymore
It's not recommended to run containers in Kubernetes as `root`.
❗Attention: If you had not configured a different user before then you need to ensure that your image supports the user and group ID configured and also manually change permissions of all files so that Jenkins is still able to use them.
### Summary of updated values
As version 2.0.0 only updates default values and nothing else it's still possible to migrate to this version and opt out of some or all new defaults.
All you have to do is ensure the old values are set in your installation.
Here we show which values have changed and the previous default values:
```yaml
controller:
runAsUser: 1000 # was unset before
fsGroup: 1000 # was unset before
JCasC:
enabled: true # was false
defaultConfig: true # was false
sidecars:
configAutoReload:
enabled: true # was false
```
### Migration steps
Migration instructions heavily depend on your current setup.
So think of the list below more as a general guideline of what should be done.
- Ensure that the Jenkins image you are using contains a user with ID 1000 and a group with the same ID.
That's the case for `jenkins/jenkins:lts` image, which the chart uses by default
- Make a backup of your existing installation especially the persistent volume
- Ensure that you have the configuration as code plugin installed
- Export your current settings via the plugin:
`Manage Jenkins` -> `Configuration as Code` -> `Download Configuration`
- prepare your values file for the update e.g. add additional configuration as code setting that you need.
The export taken from above might be a good starting point for this.
In addition, the [demos](https://github.com/jenkinsci/configuration-as-code-plugin/tree/master/demos) from the plugin itself are quite useful.
- Test drive those setting on a separate installation
- Put Jenkins to Quiet Down mode so that it does not accept new jobs
`<JENKINS_URL>/quietDown`
- Change permissions of all files and folders to the new user and group id:
```console
kubectl exec -it <jenkins_pod> -c jenkins /bin/bash
chown -R 1000:1000 /var/jenkins_home
```
- Update Jenkins
## To 1.0.0
Breaking changes:
- Values have been renamed to follow [helm recommended naming conventions](https://helm.sh/docs/chart_best_practices/#naming-conventions) so that all variables start with a lowercase letter and words are separated with camelcase
- All resources are now using [helm recommended standard labels](https://helm.sh/docs/chart_best_practices/#standard-labels)
As a result of the label changes also the selectors of the deployment have been updated.
Those are immutable so trying an updated will cause an error like:
```console
Error: Deployment.apps "jenkins" is invalid: spec.selector: Invalid value: v1.LabelSelector{MatchLabels:map[string]string{"app.kubernetes.io/component":"jenkins-controller", "app.kubernetes.io/instance":"jenkins"}, MatchExpressions:[]v1.LabelSelectorRequirement(nil)}: field is immutable
```
In order to upgrade, [uninstall](./README.md#uninstall-chart) the Jenkins Deployment before upgrading:

View File

@ -0,0 +1,309 @@
# Jenkins
## Configuration
The following tables list the configurable parameters of the Jenkins chart and their default values.
## Values
| Key | Type | Description | Default |
|:----|:-----|:---------|:------------|
| [additionalAgents](./values.yaml#L1165) | object | Configure additional | `{}` |
| [additionalClouds](./values.yaml#L1190) | object | | `{}` |
| [agent.TTYEnabled](./values.yaml#L1083) | bool | Allocate pseudo tty to the side container | `false` |
| [agent.additionalContainers](./values.yaml#L1118) | list | Add additional containers to the agents | `[]` |
| [agent.alwaysPullImage](./values.yaml#L976) | bool | Always pull agent container image before build | `false` |
| [agent.annotations](./values.yaml#L1114) | object | Annotations to apply to the pod | `{}` |
| [agent.args](./values.yaml#L1077) | string | Arguments passed to command to execute | `"${computer.jnlpmac} ${computer.name}"` |
| [agent.command](./values.yaml#L1075) | string | Command to execute when side container starts | `nil` |
| [agent.componentName](./values.yaml#L944) | string | | `"jenkins-agent"` |
| [agent.connectTimeout](./values.yaml#L1112) | int | Timeout in seconds for an agent to be online | `100` |
| [agent.containerCap](./values.yaml#L1085) | int | Max number of agents to launch | `10` |
| [agent.customJenkinsLabels](./values.yaml#L941) | list | Append Jenkins labels to the agent | `[]` |
| [agent.defaultsProviderTemplate](./values.yaml#L907) | string | The name of the pod template to use for providing default values | `""` |
| [agent.directConnection](./values.yaml#L947) | bool | | `false` |
| [agent.disableDefaultAgent](./values.yaml#L1136) | bool | Disable the default Jenkins Agent configuration | `false` |
| [agent.enabled](./values.yaml#L905) | bool | Enable Kubernetes plugin jnlp-agent podTemplate | `true` |
| [agent.envVars](./values.yaml#L1058) | list | Environment variables for the agent Pod | `[]` |
| [agent.hostNetworking](./values.yaml#L955) | bool | Enables the agent to use the host network | `false` |
| [agent.idleMinutes](./values.yaml#L1090) | int | Allows the Pod to remain active for reuse until the configured number of minutes has passed since the last step was executed on it | `0` |
| [agent.image.repository](./values.yaml#L934) | string | Repository to pull the agent jnlp image from | `"jenkins/inbound-agent"` |
| [agent.image.tag](./values.yaml#L936) | string | Tag of the image to pull | `"3256.v88a_f6e922152-1"` |
| [agent.imagePullSecretName](./values.yaml#L943) | string | Name of the secret to be used to pull the image | `nil` |
| [agent.inheritYamlMergeStrategy](./values.yaml#L1110) | bool | Controls whether the defined yaml merge strategy will be inherited if another defined pod template is configured to inherit from the current one | `false` |
| [agent.jenkinsTunnel](./values.yaml#L915) | string | Overrides the Kubernetes Jenkins tunnel | `nil` |
| [agent.jenkinsUrl](./values.yaml#L911) | string | Overrides the Kubernetes Jenkins URL | `nil` |
| [agent.jnlpregistry](./values.yaml#L931) | string | Custom registry used to pull the agent jnlp image from | `nil` |
| [agent.kubernetesConnectTimeout](./values.yaml#L917) | int | The connection timeout in seconds for connections to Kubernetes API. The minimum value is 5 | `5` |
| [agent.kubernetesReadTimeout](./values.yaml#L919) | int | The read timeout in seconds for connections to Kubernetes API. The minimum value is 15 | `15` |
| [agent.livenessProbe](./values.yaml#L966) | object | | `{}` |
| [agent.maxRequestsPerHostStr](./values.yaml#L921) | string | The maximum concurrent connections to Kubernetes API | `"32"` |
| [agent.namespace](./values.yaml#L927) | string | Namespace in which the Kubernetes agents should be launched | `nil` |
| [agent.nodeSelector](./values.yaml#L1069) | object | Node labels for pod assignment | `{}` |
| [agent.nodeUsageMode](./values.yaml#L939) | string | | `"NORMAL"` |
| [agent.podLabels](./values.yaml#L929) | object | Custom Pod labels (an object with `label-key: label-value` pairs) | `{}` |
| [agent.podName](./values.yaml#L1087) | string | Agent Pod base name | `"default"` |
| [agent.podRetention](./values.yaml#L985) | string | | `"Never"` |
| [agent.podTemplates](./values.yaml#L1146) | object | Configures extra pod templates for the default kubernetes cloud | `{}` |
| [agent.privileged](./values.yaml#L949) | bool | Agent privileged container | `false` |
| [agent.resources](./values.yaml#L957) | object | Resources allocation (Requests and Limits) | `{"limits":{"cpu":"512m","memory":"512Mi"},"requests":{"cpu":"512m","memory":"512Mi"}}` |
| [agent.restrictedPssSecurityContext](./values.yaml#L982) | bool | Set a restricted securityContext on jnlp containers | `false` |
| [agent.retentionTimeout](./values.yaml#L923) | int | Time in minutes after which the Kubernetes cloud plugin will clean up an idle worker that has not already terminated | `5` |
| [agent.runAsGroup](./values.yaml#L953) | string | Configure container group | `nil` |
| [agent.runAsUser](./values.yaml#L951) | string | Configure container user | `nil` |
| [agent.secretEnvVars](./values.yaml#L1062) | list | Mount a secret as environment variable | `[]` |
| [agent.showRawYaml](./values.yaml#L989) | bool | | `true` |
| [agent.sideContainerName](./values.yaml#L1079) | string | Side container name | `"jnlp"` |
| [agent.volumes](./values.yaml#L996) | list | Additional volumes | `[]` |
| [agent.waitForPodSec](./values.yaml#L925) | int | Seconds to wait for pod to be running | `600` |
| [agent.websocket](./values.yaml#L946) | bool | Enables agent communication via websockets | `false` |
| [agent.workingDir](./values.yaml#L938) | string | Configure working directory for default agent | `"/home/jenkins/agent"` |
| [agent.workspaceVolume](./values.yaml#L1031) | object | Workspace volume (defaults to EmptyDir) | `{}` |
| [agent.yamlMergeStrategy](./values.yaml#L1108) | string | Defines how the raw yaml field gets merged with yaml definitions from inherited pod templates. Possible values: "merge" or "override" | `"override"` |
| [agent.yamlTemplate](./values.yaml#L1097) | string | The raw yaml of a Pod API Object to merge into the agent spec | `""` |
| [awsSecurityGroupPolicies.enabled](./values.yaml#L1316) | bool | | `false` |
| [awsSecurityGroupPolicies.policies[0].name](./values.yaml#L1318) | string | | `""` |
| [awsSecurityGroupPolicies.policies[0].podSelector](./values.yaml#L1320) | object | | `{}` |
| [awsSecurityGroupPolicies.policies[0].securityGroupIds](./values.yaml#L1319) | list | | `[]` |
| [checkDeprecation](./values.yaml#L1313) | bool | Checks if any deprecated values are used | `true` |
| [clusterZone](./values.yaml#L21) | string | Override the cluster name for FQDN resolving | `"cluster.local"` |
| [controller.JCasC.authorizationStrategy](./values.yaml#L533) | string | Jenkins Config as Code Authorization Strategy-section | `"loggedInUsersCanDoAnything:\n allowAnonymousRead: false"` |
| [controller.JCasC.configMapAnnotations](./values.yaml#L538) | object | Annotations for the JCasC ConfigMap | `{}` |
| [controller.JCasC.configScripts](./values.yaml#L507) | object | List of Jenkins Config as Code scripts | `{}` |
| [controller.JCasC.configUrls](./values.yaml#L504) | list | Remote URLs for configuration files. | `[]` |
| [controller.JCasC.defaultConfig](./values.yaml#L498) | bool | Enables default Jenkins configuration via configuration as code plugin | `true` |
| [controller.JCasC.overwriteConfiguration](./values.yaml#L502) | bool | Whether Jenkins Config as Code should overwrite any existing configuration | `false` |
| [controller.JCasC.security](./values.yaml#L514) | object | Jenkins Config as Code security-section | `{"apiToken":{"creationOfLegacyTokenEnabled":false,"tokenGenerationOnCreationEnabled":false,"usageStatisticsEnabled":true}}` |
| [controller.JCasC.securityRealm](./values.yaml#L522) | string | Jenkins Config as Code Security Realm-section | `"local:\n allowsSignup: false\n enableCaptcha: false\n users:\n - id: \"${chart-admin-username}\"\n name: \"Jenkins Admin\"\n password: \"${chart-admin-password}\""` |
| [controller.additionalExistingSecrets](./values.yaml#L459) | list | List of additional existing secrets to mount | `[]` |
| [controller.additionalPlugins](./values.yaml#L409) | list | List of plugins to install in addition to those listed in controller.installPlugins | `[]` |
| [controller.additionalSecrets](./values.yaml#L468) | list | List of additional secrets to create and mount | `[]` |
| [controller.admin.createSecret](./values.yaml#L91) | bool | Create secret for admin user | `true` |
| [controller.admin.existingSecret](./values.yaml#L94) | string | The name of an existing secret containing the admin credentials | `""` |
| [controller.admin.password](./values.yaml#L81) | string | Admin password created as a secret if `controller.admin.createSecret` is true | `<random password>` |
| [controller.admin.passwordKey](./values.yaml#L86) | string | The key in the existing admin secret containing the password | `"jenkins-admin-password"` |
| [controller.admin.userKey](./values.yaml#L84) | string | The key in the existing admin secret containing the username | `"jenkins-admin-user"` |
| [controller.admin.username](./values.yaml#L78) | string | Admin username created as a secret if `controller.admin.createSecret` is true | `"admin"` |
| [controller.affinity](./values.yaml#L660) | object | Affinity settings | `{}` |
| [controller.agentListenerEnabled](./values.yaml#L318) | bool | Create Agent listener service | `true` |
| [controller.agentListenerExternalTrafficPolicy](./values.yaml#L328) | string | Traffic Policy of for the agentListener service | `nil` |
| [controller.agentListenerHostPort](./values.yaml#L322) | string | Host port to listen for agents | `nil` |
| [controller.agentListenerLoadBalancerIP](./values.yaml#L358) | string | Static IP for the agentListener LoadBalancer | `nil` |
| [controller.agentListenerLoadBalancerSourceRanges](./values.yaml#L330) | list | Allowed inbound IP for the agentListener service | `["0.0.0.0/0"]` |
| [controller.agentListenerNodePort](./values.yaml#L324) | string | Node port to listen for agents | `nil` |
| [controller.agentListenerPort](./values.yaml#L320) | int | Listening port for agents | `50000` |
| [controller.agentListenerServiceAnnotations](./values.yaml#L353) | object | Annotations for the agentListener service | `{}` |
| [controller.agentListenerServiceType](./values.yaml#L350) | string | Defines how to expose the agentListener service | `"ClusterIP"` |
| [controller.backendconfig.annotations](./values.yaml#L763) | object | backendconfig annotations | `{}` |
| [controller.backendconfig.apiVersion](./values.yaml#L757) | string | backendconfig API version | `"extensions/v1beta1"` |
| [controller.backendconfig.enabled](./values.yaml#L755) | bool | Enables backendconfig | `false` |
| [controller.backendconfig.labels](./values.yaml#L761) | object | backendconfig labels | `{}` |
| [controller.backendconfig.name](./values.yaml#L759) | string | backendconfig name | `nil` |
| [controller.backendconfig.spec](./values.yaml#L765) | object | backendconfig spec | `{}` |
| [controller.cloudName](./values.yaml#L487) | string | Name of default cloud configuration. | `"kubernetes"` |
| [controller.clusterIp](./values.yaml#L217) | string | k8s service clusterIP. Only used if serviceType is ClusterIP | `nil` |
| [controller.componentName](./values.yaml#L34) | string | Used for label app.kubernetes.io/component | `"jenkins-controller"` |
| [controller.containerEnv](./values.yaml#L150) | list | Environment variables for Jenkins Container | `[]` |
| [controller.containerEnvFrom](./values.yaml#L147) | list | Environment variable sources for Jenkins Container | `[]` |
| [controller.containerSecurityContext](./values.yaml#L205) | object | Allow controlling the securityContext for the jenkins container | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true,"runAsGroup":1000,"runAsUser":1000}` |
| [controller.csrf.defaultCrumbIssuer.enabled](./values.yaml#L339) | bool | Enable the default CSRF Crumb issuer | `true` |
| [controller.csrf.defaultCrumbIssuer.proxyCompatability](./values.yaml#L341) | bool | Enable proxy compatibility | `true` |
| [controller.customInitContainers](./values.yaml#L541) | list | Custom init-container specification in raw-yaml format | `[]` |
| [controller.customJenkinsLabels](./values.yaml#L68) | list | Append Jenkins labels to the controller | `[]` |
| [controller.disableRememberMe](./values.yaml#L59) | bool | Disable use of remember me | `false` |
| [controller.disabledAgentProtocols](./values.yaml#L333) | list | Disabled agent protocols | `["JNLP-connect","JNLP2-connect"]` |
| [controller.enableRawHtmlMarkupFormatter](./values.yaml#L429) | bool | Enable HTML parsing using OWASP Markup Formatter Plugin (antisamy-markup-formatter) | `false` |
| [controller.executorMode](./values.yaml#L65) | string | Sets the executor mode of the Jenkins node. Possible values are "NORMAL" or "EXCLUSIVE" | `"NORMAL"` |
| [controller.existingSecret](./values.yaml#L456) | string | | `nil` |
| [controller.extraPorts](./values.yaml#L388) | list | Optionally configure other ports to expose in the controller container | `[]` |
| [controller.fsGroup](./values.yaml#L186) | int | Deprecated in favor of `controller.podSecurityContextOverride`. uid that will be used for persistent volume. | `1000` |
| [controller.googlePodMonitor.enabled](./values.yaml#L826) | bool | | `false` |
| [controller.googlePodMonitor.scrapeEndpoint](./values.yaml#L831) | string | | `"/prometheus"` |
| [controller.googlePodMonitor.scrapeInterval](./values.yaml#L829) | string | | `"60s"` |
| [controller.healthProbes](./values.yaml#L248) | bool | Enable Kubernetes Probes configuration configured in `controller.probes` | `true` |
| [controller.hostAliases](./values.yaml#L779) | list | Allows for adding entries to Pod /etc/hosts | `[]` |
| [controller.hostNetworking](./values.yaml#L70) | bool | | `false` |
| [controller.httpsKeyStore.disableSecretMount](./values.yaml#L847) | bool | | `false` |
| [controller.httpsKeyStore.enable](./values.yaml#L838) | bool | Enables HTTPS keystore on jenkins controller | `false` |
| [controller.httpsKeyStore.fileName](./values.yaml#L855) | string | Jenkins keystore filename which will appear under controller.httpsKeyStore.path | `"keystore.jks"` |
| [controller.httpsKeyStore.httpPort](./values.yaml#L851) | int | HTTP Port that Jenkins should listen to along with HTTPS, it also serves as the liveness and readiness probes port. | `8081` |
| [controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretKey](./values.yaml#L846) | string | Name of the key in the secret that contains the JKS password | `"https-jks-password"` |
| [controller.httpsKeyStore.jenkinsHttpsJksPasswordSecretName](./values.yaml#L844) | string | Name of the secret that contains the JKS password, if it is not in the same secret as the JKS file | `""` |
| [controller.httpsKeyStore.jenkinsHttpsJksSecretKey](./values.yaml#L842) | string | Name of the key in the secret that already has ssl keystore | `"jenkins-jks-file"` |
| [controller.httpsKeyStore.jenkinsHttpsJksSecretName](./values.yaml#L840) | string | Name of the secret that already has ssl keystore | `""` |
| [controller.httpsKeyStore.jenkinsKeyStoreBase64Encoded](./values.yaml#L860) | string | Base64 encoded Keystore content. Keystore must be converted to base64 then being pasted here | `nil` |
| [controller.httpsKeyStore.password](./values.yaml#L857) | string | Jenkins keystore password | `"password"` |
| [controller.httpsKeyStore.path](./values.yaml#L853) | string | Path of HTTPS keystore file | `"/var/jenkins_keystore"` |
| [controller.image.pullPolicy](./values.yaml#L47) | string | Controller image pull policy | `"Always"` |
| [controller.image.registry](./values.yaml#L37) | string | Controller image registry | `"docker.io"` |
| [controller.image.repository](./values.yaml#L39) | string | Controller image repository | `"jenkins/jenkins"` |
| [controller.image.tag](./values.yaml#L42) | string | Controller image tag override; i.e., tag: "2.440.1-jdk17" | `nil` |
| [controller.image.tagLabel](./values.yaml#L45) | string | Controller image tag label | `"jdk17"` |
| [controller.imagePullSecretName](./values.yaml#L49) | string | Controller image pull secret | `nil` |
| [controller.ingress.annotations](./values.yaml#L702) | object | Ingress annotations | `{}` |
| [controller.ingress.apiVersion](./values.yaml#L698) | string | Ingress API version | `"extensions/v1beta1"` |
| [controller.ingress.enabled](./values.yaml#L681) | bool | Enables ingress | `false` |
| [controller.ingress.hostName](./values.yaml#L715) | string | Ingress hostname | `nil` |
| [controller.ingress.labels](./values.yaml#L700) | object | Ingress labels | `{}` |
| [controller.ingress.path](./values.yaml#L711) | string | Ingress path | `nil` |
| [controller.ingress.paths](./values.yaml#L685) | list | Override for the default Ingress paths | `[]` |
| [controller.ingress.resourceRootUrl](./values.yaml#L717) | string | Hostname to serve assets from | `nil` |
| [controller.ingress.tls](./values.yaml#L719) | list | Ingress TLS configuration | `[]` |
| [controller.initConfigMap](./values.yaml#L446) | string | Name of the existing ConfigMap that contains init scripts | `nil` |
| [controller.initContainerEnv](./values.yaml#L141) | list | Environment variables for Init Container | `[]` |
| [controller.initContainerEnvFrom](./values.yaml#L137) | list | Environment variable sources for Init Container | `[]` |
| [controller.initContainerResources](./values.yaml#L128) | object | Resources allocation (Requests and Limits) for Init Container | `{}` |
| [controller.initScripts](./values.yaml#L442) | object | Map of groovy init scripts to be executed during Jenkins controller start | `{}` |
| [controller.initializeOnce](./values.yaml#L414) | bool | Initialize only on first installation. Ensures plugins do not get updated inadvertently. Requires `persistence.enabled` to be set to `true` | `false` |
| [controller.installLatestPlugins](./values.yaml#L403) | bool | Download the minimum required version or latest version of all dependencies | `true` |
| [controller.installLatestSpecifiedPlugins](./values.yaml#L406) | bool | Set to true to download the latest version of any plugin that is requested to have the latest version | `false` |
| [controller.installPlugins](./values.yaml#L395) | list | List of Jenkins plugins to install. If you don't want to install plugins, set it to `false` | `["kubernetes:4253.v7700d91739e5","workflow-aggregator:600.vb_57cdd26fdd7","git:5.2.2","configuration-as-code:1836.vccda_4a_122a_a_e"]` |
| [controller.javaOpts](./values.yaml#L156) | string | Append to `JAVA_OPTS` env var | `nil` |
| [controller.jenkinsAdminEmail](./values.yaml#L96) | string | Email address for the administrator of the Jenkins instance | `nil` |
| [controller.jenkinsHome](./values.yaml#L101) | string | Custom Jenkins home path | `"/var/jenkins_home"` |
| [controller.jenkinsOpts](./values.yaml#L158) | string | Append to `JENKINS_OPTS` env var | `nil` |
| [controller.jenkinsRef](./values.yaml#L106) | string | Custom Jenkins reference path | `"/usr/share/jenkins/ref"` |
| [controller.jenkinsUriPrefix](./values.yaml#L173) | string | Root URI Jenkins will be served on | `nil` |
| [controller.jenkinsUrl](./values.yaml#L168) | string | Set Jenkins URL if you are not using the ingress definitions provided by the chart | `nil` |
| [controller.jenkinsUrlProtocol](./values.yaml#L165) | string | Set protocol for Jenkins URL; `https` if `controller.ingress.tls`, `http` otherwise | `nil` |
| [controller.jenkinsWar](./values.yaml#L109) | string | | `"/usr/share/jenkins/jenkins.war"` |
| [controller.jmxPort](./values.yaml#L385) | string | Open a port, for JMX stats | `nil` |
| [controller.legacyRemotingSecurityEnabled](./values.yaml#L361) | bool | Whether legacy remoting security should be enabled | `false` |
| [controller.lifecycle](./values.yaml#L51) | object | Lifecycle specification for controller-container | `{}` |
| [controller.loadBalancerIP](./values.yaml#L376) | string | Optionally assign a known public LB IP | `nil` |
| [controller.loadBalancerSourceRanges](./values.yaml#L372) | list | Allowed inbound IP addresses | `["0.0.0.0/0"]` |
| [controller.markupFormatter](./values.yaml#L433) | string | Yaml of the markup formatter to use | `"plainText"` |
| [controller.nodePort](./values.yaml#L223) | string | k8s node port. Only used if serviceType is NodePort | `nil` |
| [controller.nodeSelector](./values.yaml#L647) | object | Node labels for pod assignment | `{}` |
| [controller.numExecutors](./values.yaml#L62) | int | Set Number of executors | `0` |
| [controller.overwritePlugins](./values.yaml#L418) | bool | Overwrite installed plugins on start | `false` |
| [controller.overwritePluginsFromImage](./values.yaml#L422) | bool | Overwrite plugins that are already installed in the controller image | `true` |
| [controller.podAnnotations](./values.yaml#L668) | object | Annotations for controller pod | `{}` |
| [controller.podDisruptionBudget.annotations](./values.yaml#L312) | object | | `{}` |
| [controller.podDisruptionBudget.apiVersion](./values.yaml#L310) | string | Policy API version | `"policy/v1beta1"` |
| [controller.podDisruptionBudget.enabled](./values.yaml#L305) | bool | Enable Kubernetes Pod Disruption Budget configuration | `false` |
| [controller.podDisruptionBudget.labels](./values.yaml#L313) | object | | `{}` |
| [controller.podDisruptionBudget.maxUnavailable](./values.yaml#L315) | string | Number of pods that can be unavailable. Either an absolute number or a percentage | `"0"` |
| [controller.podLabels](./values.yaml#L241) | object | Custom Pod labels (an object with `label-key: label-value` pairs) | `{}` |
| [controller.podSecurityContextOverride](./values.yaml#L202) | string | Completely overwrites the contents of the pod security context, ignoring the values provided for `runAsUser`, `fsGroup`, and `securityContextCapabilities` | `nil` |
| [controller.priorityClassName](./values.yaml#L665) | string | The name of a `priorityClass` to apply to the controller pod | `nil` |
| [controller.probes.livenessProbe.failureThreshold](./values.yaml#L266) | int | Set the failure threshold for the liveness probe | `5` |
| [controller.probes.livenessProbe.httpGet.path](./values.yaml#L269) | string | Set the Pod's HTTP path for the liveness probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.livenessProbe.httpGet.port](./values.yaml#L271) | string | Set the Pod's HTTP port to use for the liveness probe | `"http"` |
| [controller.probes.livenessProbe.initialDelaySeconds](./values.yaml#L280) | string | Set the initial delay for the liveness probe in seconds | `nil` |
| [controller.probes.livenessProbe.periodSeconds](./values.yaml#L273) | int | Set the time interval between two liveness probes executions in seconds | `10` |
| [controller.probes.livenessProbe.timeoutSeconds](./values.yaml#L275) | int | Set the timeout for the liveness probe in seconds | `5` |
| [controller.probes.readinessProbe.failureThreshold](./values.yaml#L284) | int | Set the failure threshold for the readiness probe | `3` |
| [controller.probes.readinessProbe.httpGet.path](./values.yaml#L287) | string | Set the Pod's HTTP path for the liveness probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.readinessProbe.httpGet.port](./values.yaml#L289) | string | Set the Pod's HTTP port to use for the readiness probe | `"http"` |
| [controller.probes.readinessProbe.initialDelaySeconds](./values.yaml#L298) | string | Set the initial delay for the readiness probe in seconds | `nil` |
| [controller.probes.readinessProbe.periodSeconds](./values.yaml#L291) | int | Set the time interval between two readiness probes executions in seconds | `10` |
| [controller.probes.readinessProbe.timeoutSeconds](./values.yaml#L293) | int | Set the timeout for the readiness probe in seconds | `5` |
| [controller.probes.startupProbe.failureThreshold](./values.yaml#L253) | int | Set the failure threshold for the startup probe | `12` |
| [controller.probes.startupProbe.httpGet.path](./values.yaml#L256) | string | Set the Pod's HTTP path for the startup probe | `"{{ default \"\" .Values.controller.jenkinsUriPrefix }}/login"` |
| [controller.probes.startupProbe.httpGet.port](./values.yaml#L258) | string | Set the Pod's HTTP port to use for the startup probe | `"http"` |
| [controller.probes.startupProbe.periodSeconds](./values.yaml#L260) | int | Set the time interval between two startup probes executions in seconds | `10` |
| [controller.probes.startupProbe.timeoutSeconds](./values.yaml#L262) | int | Set the timeout for the startup probe in seconds | `5` |
| [controller.projectNamingStrategy](./values.yaml#L425) | string | | `"standard"` |
| [controller.prometheus.alertingRulesAdditionalLabels](./values.yaml#L812) | object | Additional labels to add to the PrometheusRule object | `{}` |
| [controller.prometheus.alertingrules](./values.yaml#L810) | list | Array of prometheus alerting rules | `[]` |
| [controller.prometheus.enabled](./values.yaml#L795) | bool | Enables prometheus service monitor | `false` |
| [controller.prometheus.metricRelabelings](./values.yaml#L822) | list | | `[]` |
| [controller.prometheus.prometheusRuleNamespace](./values.yaml#L814) | string | Set a custom namespace where to deploy PrometheusRule resource | `""` |
| [controller.prometheus.relabelings](./values.yaml#L820) | list | | `[]` |
| [controller.prometheus.scrapeEndpoint](./values.yaml#L805) | string | The endpoint prometheus should get metrics from | `"/prometheus"` |
| [controller.prometheus.scrapeInterval](./values.yaml#L801) | string | How often prometheus should scrape metrics | `"60s"` |
| [controller.prometheus.serviceMonitorAdditionalLabels](./values.yaml#L797) | object | Additional labels to add to the service monitor object | `{}` |
| [controller.prometheus.serviceMonitorNamespace](./values.yaml#L799) | string | Set a custom namespace where to deploy ServiceMonitor resource | `nil` |
| [controller.resources](./values.yaml#L115) | object | Resource allocation (Requests and Limits) | `{"limits":{"cpu":"2000m","memory":"4096Mi"},"requests":{"cpu":"50m","memory":"256Mi"}}` |
| [controller.route.annotations](./values.yaml#L774) | object | Route annotations | `{}` |
| [controller.route.enabled](./values.yaml#L770) | bool | Enables openshift route | `false` |
| [controller.route.labels](./values.yaml#L772) | object | Route labels | `{}` |
| [controller.route.path](./values.yaml#L776) | string | Route path | `nil` |
| [controller.runAsUser](./values.yaml#L183) | int | Deprecated in favor of `controller.podSecurityContextOverride`. uid that jenkins runs with. | `1000` |
| [controller.schedulerName](./values.yaml#L643) | string | Name of the Kubernetes scheduler to use | `""` |
| [controller.scriptApproval](./values.yaml#L437) | list | List of groovy functions to approve | `[]` |
| [controller.secondaryingress.annotations](./values.yaml#L737) | object | | `{}` |
| [controller.secondaryingress.apiVersion](./values.yaml#L735) | string | | `"extensions/v1beta1"` |
| [controller.secondaryingress.enabled](./values.yaml#L729) | bool | | `false` |
| [controller.secondaryingress.hostName](./values.yaml#L744) | string | | `nil` |
| [controller.secondaryingress.labels](./values.yaml#L736) | object | | `{}` |
| [controller.secondaryingress.paths](./values.yaml#L732) | list | | `[]` |
| [controller.secondaryingress.tls](./values.yaml#L745) | string | | `nil` |
| [controller.secretClaims](./values.yaml#L480) | list | List of `SecretClaim` resources to create | `[]` |
| [controller.securityContextCapabilities](./values.yaml#L192) | object | | `{}` |
| [controller.serviceAnnotations](./values.yaml#L230) | object | Jenkins controller service annotations | `{}` |
| [controller.serviceExternalTrafficPolicy](./values.yaml#L227) | string | | `nil` |
| [controller.serviceLabels](./values.yaml#L236) | object | Labels for the Jenkins controller-service | `{}` |
| [controller.servicePort](./values.yaml#L219) | int | k8s service port | `8080` |
| [controller.serviceType](./values.yaml#L214) | string | k8s service type | `"ClusterIP"` |
| [controller.shareProcessNamespace](./values.yaml#L124) | bool | | `false` |
| [controller.sidecars.additionalSidecarContainers](./values.yaml#L625) | list | Configures additional sidecar container(s) for the Jenkins controller | `[]` |
| [controller.sidecars.configAutoReload.additionalVolumeMounts](./values.yaml#L571) | list | Enables additional volume mounts for the config auto-reload container | `[]` |
| [controller.sidecars.configAutoReload.containerSecurityContext](./values.yaml#L620) | object | Enable container security context | `{"allowPrivilegeEscalation":false,"readOnlyRootFilesystem":true}` |
| [controller.sidecars.configAutoReload.enabled](./values.yaml#L554) | bool | Enables Jenkins Config as Code auto-reload | `true` |
| [controller.sidecars.configAutoReload.env](./values.yaml#L602) | object | Environment variables for the Jenkins Config as Code auto-reload container | `{}` |
| [controller.sidecars.configAutoReload.envFrom](./values.yaml#L600) | list | Environment variable sources for the Jenkins Config as Code auto-reload container | `[]` |
| [controller.sidecars.configAutoReload.folder](./values.yaml#L613) | string | | `"/var/jenkins_home/casc_configs"` |
| [controller.sidecars.configAutoReload.image.registry](./values.yaml#L557) | string | Registry for the image that triggers the reload | `"docker.io"` |
| [controller.sidecars.configAutoReload.image.repository](./values.yaml#L559) | string | Repository of the image that triggers the reload | `"kiwigrid/k8s-sidecar"` |
| [controller.sidecars.configAutoReload.image.tag](./values.yaml#L561) | string | Tag for the image that triggers the reload | `"1.27.5"` |
| [controller.sidecars.configAutoReload.imagePullPolicy](./values.yaml#L562) | string | | `"IfNotPresent"` |
| [controller.sidecars.configAutoReload.logging](./values.yaml#L577) | object | Config auto-reload logging settings | `{"configuration":{"backupCount":3,"formatter":"JSON","logLevel":"INFO","logToConsole":true,"logToFile":false,"maxBytes":1024,"override":false}}` |
| [controller.sidecars.configAutoReload.logging.configuration.override](./values.yaml#L581) | bool | Enables custom log config utilizing using the settings below. | `false` |
| [controller.sidecars.configAutoReload.reqRetryConnect](./values.yaml#L595) | int | How many connection-related errors to retry on | `10` |
| [controller.sidecars.configAutoReload.resources](./values.yaml#L563) | object | | `{}` |
| [controller.sidecars.configAutoReload.scheme](./values.yaml#L590) | string | The scheme to use when connecting to the Jenkins configuration as code endpoint | `"http"` |
| [controller.sidecars.configAutoReload.skipTlsVerify](./values.yaml#L592) | bool | Skip TLS verification when connecting to the Jenkins configuration as code endpoint | `false` |
| [controller.sidecars.configAutoReload.sleepTime](./values.yaml#L597) | string | How many seconds to wait before updating config-maps/secrets (sets METHOD=SLEEP on the sidecar) | `nil` |
| [controller.sidecars.configAutoReload.sshTcpPort](./values.yaml#L611) | int | | `1044` |
| [controller.statefulSetAnnotations](./values.yaml#L670) | object | Annotations for controller StatefulSet | `{}` |
| [controller.statefulSetLabels](./values.yaml#L232) | object | Jenkins controller custom labels for the StatefulSet | `{}` |
| [controller.targetPort](./values.yaml#L221) | int | k8s target port | `8080` |
| [controller.terminationGracePeriodSeconds](./values.yaml#L653) | string | Set TerminationGracePeriodSeconds | `nil` |
| [controller.terminationMessagePath](./values.yaml#L655) | string | Set the termination message path | `nil` |
| [controller.terminationMessagePolicy](./values.yaml#L657) | string | Set the termination message policy | `nil` |
| [controller.testEnabled](./values.yaml#L834) | bool | Can be used to disable rendering controller test resources when using helm template | `true` |
| [controller.tolerations](./values.yaml#L651) | list | Toleration labels for pod assignment | `[]` |
| [controller.topologySpreadConstraints](./values.yaml#L677) | object | Topology spread constraints | `{}` |
| [controller.updateStrategy](./values.yaml#L674) | object | Update strategy for StatefulSet | `{}` |
| [controller.usePodSecurityContext](./values.yaml#L176) | bool | Enable pod security context (must be `true` if podSecurityContextOverride, runAsUser or fsGroup are set) | `true` |
| [credentialsId](./values.yaml#L27) | string | The Jenkins credentials to access the Kubernetes API server. For the default cluster it is not needed. | `nil` |
| [fullnameOverride](./values.yaml#L13) | string | Override the full resource names | `jenkins-(release-name)` or `jenkins` if the release-name is `jenkins` |
| [helmtest.bats.image.registry](./values.yaml#L1329) | string | Registry of the image used to test the framework | `"docker.io"` |
| [helmtest.bats.image.repository](./values.yaml#L1331) | string | Repository of the image used to test the framework | `"bats/bats"` |
| [helmtest.bats.image.tag](./values.yaml#L1333) | string | Tag of the image to test the framework | `"1.11.0"` |
| [kubernetesURL](./values.yaml#L24) | string | The URL of the Kubernetes API server | `"https://kubernetes.default"` |
| [nameOverride](./values.yaml#L10) | string | Override the resource name prefix | `Chart.Name` |
| [namespaceOverride](./values.yaml#L16) | string | Override the deployment namespace | `Release.Namespace` |
| [networkPolicy.apiVersion](./values.yaml#L1259) | string | NetworkPolicy ApiVersion | `"networking.k8s.io/v1"` |
| [networkPolicy.enabled](./values.yaml#L1254) | bool | Enable the creation of NetworkPolicy resources | `false` |
| [networkPolicy.externalAgents.except](./values.yaml#L1273) | list | A list of IP sub-ranges to be excluded from the allowlisted IP range | `[]` |
| [networkPolicy.externalAgents.ipCIDR](./values.yaml#L1271) | string | The IP range from which external agents are allowed to connect to controller, i.e., 172.17.0.0/16 | `nil` |
| [networkPolicy.internalAgents.allowed](./values.yaml#L1263) | bool | Allow internal agents (from the same cluster) to connect to controller. Agent pods will be filtered based on PodLabels | `true` |
| [networkPolicy.internalAgents.namespaceLabels](./values.yaml#L1267) | object | A map of labels (keys/values) that agents namespaces must have to be able to connect to controller | `{}` |
| [networkPolicy.internalAgents.podLabels](./values.yaml#L1265) | object | A map of labels (keys/values) that agent pods must have to be able to connect to controller | `{}` |
| [persistence.accessMode](./values.yaml#L1229) | string | The PVC access mode | `"ReadWriteOnce"` |
| [persistence.annotations](./values.yaml#L1225) | object | Annotations for the PVC | `{}` |
| [persistence.dataSource](./values.yaml#L1235) | object | Existing data source to clone PVC from | `{}` |
| [persistence.enabled](./values.yaml#L1209) | bool | Enable the use of a Jenkins PVC | `true` |
| [persistence.existingClaim](./values.yaml#L1215) | string | Provide the name of a PVC | `nil` |
| [persistence.labels](./values.yaml#L1227) | object | Labels for the PVC | `{}` |
| [persistence.mounts](./values.yaml#L1247) | list | Additional mounts | `[]` |
| [persistence.size](./values.yaml#L1231) | string | The size of the PVC | `"8Gi"` |
| [persistence.storageClass](./values.yaml#L1223) | string | Storage class for the PVC | `nil` |
| [persistence.subPath](./values.yaml#L1240) | string | SubPath for jenkins-home mount | `nil` |
| [persistence.volumes](./values.yaml#L1242) | list | Additional volumes | `[]` |
| [rbac.create](./values.yaml#L1279) | bool | Whether RBAC resources are created | `true` |
| [rbac.readSecrets](./values.yaml#L1281) | bool | Whether the Jenkins service account should be able to read Kubernetes secrets | `false` |
| [renderHelmLabels](./values.yaml#L30) | bool | Enables rendering of the helm.sh/chart label to the annotations | `true` |
| [serviceAccount.annotations](./values.yaml#L1291) | object | Configures annotations for the ServiceAccount | `{}` |
| [serviceAccount.create](./values.yaml#L1285) | bool | Configures if a ServiceAccount with this name should be created | `true` |
| [serviceAccount.extraLabels](./values.yaml#L1293) | object | Configures extra labels for the ServiceAccount | `{}` |
| [serviceAccount.imagePullSecretName](./values.yaml#L1295) | string | Controller ServiceAccount image pull secret | `nil` |
| [serviceAccount.name](./values.yaml#L1289) | string | | `nil` |
| [serviceAccountAgent.annotations](./values.yaml#L1306) | object | Configures annotations for the agent ServiceAccount | `{}` |
| [serviceAccountAgent.create](./values.yaml#L1300) | bool | Configures if an agent ServiceAccount should be created | `false` |
| [serviceAccountAgent.extraLabels](./values.yaml#L1308) | object | Configures extra labels for the agent ServiceAccount | `{}` |
| [serviceAccountAgent.imagePullSecretName](./values.yaml#L1310) | string | Agent ServiceAccount image pull secret | `nil` |
| [serviceAccountAgent.name](./values.yaml#L1304) | string | The name of the agent ServiceAccount to be used by access-controlled resources | `nil` |

View File

@ -0,0 +1,28 @@
# Jenkins
## Configuration
The following tables list the configurable parameters of the Jenkins chart and their default values.
{{- define "chart.valueDefaultColumnRender" -}}
{{- $defaultValue := (trimAll "`" (default .Default .AutoDefault) | replace "\n" "") -}}
`{{- $defaultValue | replace "\n" "" -}}`
{{- end -}}
{{- define "chart.typeColumnRender" -}}
{{- .Type -}}
{{- end -}}
{{- define "chart.valueDescription" -}}
{{- default .Description .AutoDescription }}
{{- end -}}
{{- define "chart.valuesTable" -}}
| Key | Type | Description | Default |
|:----|:-----|:---------|:------------|
{{- range .Values }}
| [{{ .Key }}](./values.yaml#L{{ .LineNumber }}) | {{ template "chart.typeColumnRender" . }} | {{ template "chart.valueDescription" . }} | {{ template "chart.valueDefaultColumnRender" . }} |
{{- end }}
{{- end }}
{{ template "chart.valuesSection" . }}

View File

@ -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 }}

View File

@ -0,0 +1,669 @@
{{/* 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 }}
inheritYamlMergeStrategy: {{ .Values.agent.inheritYamlMergeStrategy }}
{{- 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 }}
{{- if $root.Values.controller.sidecars.configAutoReload.logging.configuration.override }}
- name: LOG_CONFIG
value: "{{ $root.Values.controller.jenkinsHome }}/auto-reload/auto-reload-config.yaml"
{{- 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 }}
{{- if $root.Values.controller.sidecars.configAutoReload.logging.configuration.override }}
- name: auto-reload-config
mountPath: {{ $root.Values.controller.jenkinsHome }}/auto-reload
- name: auto-reload-config-logs
mountPath: {{ $root.Values.controller.jenkinsHome }}/auto-reload-logs
{{- end }}
{{- if $root.Values.controller.sidecars.configAutoReload.additionalVolumeMounts }}
{{ (tpl (toYaml $root.Values.controller.sidecars.configAutoReload.additionalVolumeMounts) $root) | indent 4 }}
{{- end }}
{{- end -}}

View File

@ -0,0 +1,60 @@
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.override }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "jenkins.fullname" . }}-auto-reload-config
namespace: {{ template "jenkins.namespace" . }}
labels:
"app.kubernetes.io/name": {{ template "jenkins.name" . }}
{{- if .Values.renderHelmLabels }}
"helm.sh/chart": "{{ .Chart.Name }}-{{ .Chart.Version }}"
{{- end }}
"app.kubernetes.io/managed-by": "{{ $.Release.Service }}"
"app.kubernetes.io/instance": "{{ $.Release.Name }}"
"app.kubernetes.io/component": "{{ $.Values.controller.componentName }}"
data:
auto-reload-config.yaml: |-
version: 1
disable_existing_loggers: false
root:
level: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.logLevel }}
handlers:
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToConsole}}
- console
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToFile }}
- file
{{- end }}
handlers:
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToConsole}}
console:
class: logging.StreamHandler
level: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.logLevel }}
formatter: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.formatter }}
{{- end }}
{{- if .Values.controller.sidecars.configAutoReload.logging.configuration.logToFile }}
file:
class : logging.handlers.RotatingFileHandler
formatter: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.formatter }}
filename: {{ .Values.controller.jenkinsHome }}/auto-reload-logs/file.log
maxBytes: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.maxBytes }}
backupCount: {{ .Values.controller.sidecars.configAutoReload.logging.configuration.backupCount }}
{{- end }}
formatters:
JSON:
"()": logger.JsonFormatter
format: "%(levelname)s %(message)s"
rename_fields:
message: msg
levelname: level
LOGFMT:
"()": logger.LogfmtFormatter
keys:
- time
- level
- msg
mapping:
time: asctime
level: levelname
msg: message
{{- end }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -0,0 +1,53 @@
{{- $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"
{{- if $root.Values.controller.JCasC.configMapAnnotations }}
annotations:
{{ toYaml $root.Values.controller.JCasC.configMapAnnotations | indent 4 }}
{{- end }}
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"
{{- if $root.Values.controller.JCasC.configMapAnnotations }}
annotations:
{{ toYaml $root.Values.controller.JCasC.configMapAnnotations | indent 4 }}
{{- end }}
data:
jcasc-default-config.yaml: |-
{{- include "jenkins.casc.defaults" . | nindent 4 }}
{{- end}}
{{- end }}

View File

@ -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 }}

View File

@ -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 -}}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -0,0 +1,424 @@
{{- 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 .Values.controller.topologySpreadConstraints }}
topologySpreadConstraints:
{{ toYaml .Values.controller.topologySpreadConstraints | 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.sidecars.configAutoReload.logging.configuration.override }}
- name: auto-reload-config
configMap:
name: {{ template "jenkins.fullname" . }}-auto-reload-config
- name: auto-reload-config-logs
emptyDir: {}
{{- 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 -}}

View File

@ -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}}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,23 @@
# Patterns to ignore when building packages.
# This supports shell glob matching, relative path matching, and
# negation (prefixed with !). Only one pattern per line.
.DS_Store
# Common VCS dirs
.git/
.gitignore
.bzr/
.bzrignore
.hg/
.hgignore
.svn/
# Common backup files
*.swp
*.bak
*.tmp
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

View File

@ -0,0 +1,27 @@
annotations:
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Speedscale Operator
catalog.cattle.io/kube-version: '>= 1.17.0-0'
catalog.cattle.io/release-name: speedscale-operator
apiVersion: v1
appVersion: 2.2.185
description: Stress test your APIs with real world scenarios. Collect and replay
traffic without scripting.
home: https://speedscale.com
icon: file://assets/icons/speedscale-operator.png
keywords:
- speedscale
- test
- testing
- regression
- reliability
- load
- replay
- network
- traffic
kubeVersion: '>= 1.17.0-0'
maintainers:
- email: support@speedscale.com
name: Speedscale Support
name: speedscale-operator
version: 2.2.185

View File

@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2021 Speedscale
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -0,0 +1,108 @@
# Speedscale Operator
The [Speedscale](https://www.speedscale.com) Operator is a [Kubernetes operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
that watches for deployments to be applied to the cluster and takes action based on annotations. The operator
can inject a proxy to capture traffic into or out of applications, or setup an isolation test environment around
a deployment for testing. The operator itself is a deployment that will be always present on the cluster once
the helm chart is installed.
## Prerequisites
- Kubernetes 1.20+
- Helm 3+
- Appropriate [network and firewall configuration](https://docs.speedscale.com/reference/networking) for Speedscale cloud and webhook traffic
## Get Repo Info
```bash
helm repo add speedscale https://speedscale.github.io/operator-helm/
helm repo update
```
_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._
## Install Chart
An API key is required. Sign up for a [free Speedscale trial](https://speedscale.com/free-trial/) if you do not have one.
```bash
helm install speedscale-operator speedscale/speedscale-operator \
-n speedscale \
--create-namespace \
--set apiKey=<YOUR-SPEEDSCALE-API-KEY> \
--set clusterName=<YOUR-CLUSTER-NAME>
```
_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
### Pre-install job failure
We use pre-install job to check provided API key and provision some of the required resources.
If the job failed during the installation, you'll see the following error during install:
```
Error: INSTALLATION FAILED: failed pre-install: job failed: BackoffLimitExceeded
```
You can inspect the logs using this command:
```bash
kubectl -n speedscale logs job/speedscale-operator-pre-install
```
After fixing the error, uninstall the helm release, delete the failed job
and try installing again:
```bash
helm -n speedscale uninstall speedscale-operator
kubectl -n speedscale delete job speedscale-operator-pre-install
```
## Uninstall Chart
```bash
helm -n speedscale uninstall speedscale-operator
```
This removes all the Kubernetes components associated with the chart and deletes the release.
_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
CRDs created by this chart are not removed by default and should be manually cleaned up:
```bash
kubectl delete crd trafficreplays.speedscale.com
```
## Upgrading Chart
```bash
helm repo update
helm -n speedscale upgrade speedscale-operator speedscale/speedscale-operator
```
Resources capturing traffic will need to be rolled to pick up the latest
Speedscale sidecar. Use the rollout restart command for each namespace and
resource type:
```bash
kubectl -n <namespace> rollout restart deployment
```
With Helm v3, CRDs created by this chart are not updated by default
and should be manually updated.
Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions).
_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
### Upgrading an existing Release to a new version
A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an
incompatible breaking change needing manual actions.
## Help
Speedscale docs information available at [docs.speedscale.com](https://docs.speedscale.com) or join us
on the [Speedscale community Slack](https://join.slack.com/t/speedscalecommunity/shared_invite/zt-x5rcrzn4-XHG1QqcHNXIM~4yozRrz8A)!

View File

@ -0,0 +1,108 @@
# Speedscale Operator
The [Speedscale](https://www.speedscale.com) Operator is a [Kubernetes operator](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/)
that watches for deployments to be applied to the cluster and takes action based on annotations. The operator
can inject a proxy to capture traffic into or out of applications, or setup an isolation test environment around
a deployment for testing. The operator itself is a deployment that will be always present on the cluster once
the helm chart is installed.
## Prerequisites
- Kubernetes 1.20+
- Helm 3+
- Appropriate [network and firewall configuration](https://docs.speedscale.com/reference/networking) for Speedscale cloud and webhook traffic
## Get Repo Info
```bash
helm repo add speedscale https://speedscale.github.io/operator-helm/
helm repo update
```
_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._
## Install Chart
An API key is required. Sign up for a [free Speedscale trial](https://speedscale.com/free-trial/) if you do not have one.
```bash
helm install speedscale-operator speedscale/speedscale-operator \
-n speedscale \
--create-namespace \
--set apiKey=<YOUR-SPEEDSCALE-API-KEY> \
--set clusterName=<YOUR-CLUSTER-NAME>
```
_See [helm install](https://helm.sh/docs/helm/helm_install/) for command documentation._
### Pre-install job failure
We use pre-install job to check provided API key and provision some of the required resources.
If the job failed during the installation, you'll see the following error during install:
```
Error: INSTALLATION FAILED: failed pre-install: job failed: BackoffLimitExceeded
```
You can inspect the logs using this command:
```bash
kubectl -n speedscale logs job/speedscale-operator-pre-install
```
After fixing the error, uninstall the helm release, delete the failed job
and try installing again:
```bash
helm -n speedscale uninstall speedscale-operator
kubectl -n speedscale delete job speedscale-operator-pre-install
```
## Uninstall Chart
```bash
helm -n speedscale uninstall speedscale-operator
```
This removes all the Kubernetes components associated with the chart and deletes the release.
_See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command documentation._
CRDs created by this chart are not removed by default and should be manually cleaned up:
```bash
kubectl delete crd trafficreplays.speedscale.com
```
## Upgrading Chart
```bash
helm repo update
helm -n speedscale upgrade speedscale-operator speedscale/speedscale-operator
```
Resources capturing traffic will need to be rolled to pick up the latest
Speedscale sidecar. Use the rollout restart command for each namespace and
resource type:
```bash
kubectl -n <namespace> rollout restart deployment
```
With Helm v3, CRDs created by this chart are not updated by default
and should be manually updated.
Consult also the [Helm Documentation on CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions).
_See [helm upgrade](https://helm.sh/docs/helm/helm_upgrade/) for command documentation._
### Upgrading an existing Release to a new version
A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an
incompatible breaking change needing manual actions.
## Help
Speedscale docs information available at [docs.speedscale.com](https://docs.speedscale.com) or join us
on the [Speedscale community Slack](https://join.slack.com/t/speedscalecommunity/shared_invite/zt-x5rcrzn4-XHG1QqcHNXIM~4yozRrz8A)!

View File

@ -0,0 +1,9 @@
questions:
- variable: apiKey
default: "fffffffffffffffffffffffffffffffffffffffffffff"
description: "An API key is required to connect to the Speedscale cloud."
required: true
type: string
label: API Key
group: Authentication

View File

@ -0,0 +1,12 @@
Thank you for installing the Speedscale Operator!
Next you'll need to add the Speedscale Proxy Sidecar to your deployments.
See https://docs.speedscale.com/setup/sidecar/install/
If upgrading use the rollout restart command for each namespace and resource
type to ensure Speedscale sidecars are updated:
kubectl -n <namespace> rollout restart deployment
Once your deployment is running the sidecar your service will show up on
https://app.speedscale.com/.

View File

@ -0,0 +1,199 @@
{{- $cacrt := "" -}}
{{- $crt := "" -}}
{{- $key := "" -}}
{{- $s := (lookup "v1" "Secret" .Release.Namespace "speedscale-webhook-certs") -}}
{{- if $s -}}
{{- $cacrt = index $s.data "ca.crt" | default (index $s.data "tls.crt") | b64dec -}}
{{- $crt = index $s.data "tls.crt" | b64dec -}}
{{- $key = index $s.data "tls.key" | b64dec -}}
{{ else }}
{{- $altNames := list ( printf "speedscale-operator.%s" .Release.Namespace ) ( printf "speedscale-operator.%s.svc" .Release.Namespace ) -}}
{{- $ca := genCA "speedscale-operator" 3650 -}}
{{- $cert := genSignedCert "speedscale-operator" nil $altNames 3650 $ca -}}
{{- $cacrt = $ca.Cert -}}
{{- $crt = $cert.Cert -}}
{{- $key = $cert.Key -}}
{{- end -}}
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: speedscale-operator
annotations:
argocd.argoproj.io/hook: PreSync
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
caBundle: {{ $cacrt | b64enc }}
service:
name: speedscale-operator
namespace: {{ .Release.Namespace }}
path: /mutate
failurePolicy: Ignore
name: sidecar.speedscale.com
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: "NotIn"
values:
- kube-system
- kube-node-lease
{{- if .Values.namespaceSelector }}
- key: kubernetes.io/metadata.name
operator: "In"
values:
{{- range .Values.namespaceSelector }}
- {{ . | quote }}
{{- end }}
{{- end }}
reinvocationPolicy: IfNeeded
rules:
- apiGroups:
- apps
- batch
apiVersions:
- v1
operations:
- CREATE
- UPDATE
- DELETE
resources:
- deployments
- statefulsets
- daemonsets
- jobs
- replicasets
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
- DELETE
resources:
- pods
sideEffects: None
timeoutSeconds: 10
---
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
creationTimestamp: null
name: speedscale-operator-replay
annotations:
argocd.argoproj.io/hook: PreSync
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
caBundle: {{ $cacrt | b64enc }}
service:
name: speedscale-operator
namespace: {{ .Release.Namespace }}
path: /mutate-speedscale-com-v1-trafficreplay
failurePolicy: Fail
name: replay.speedscale.com
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: "NotIn"
values:
- kube-system
- kube-node-lease
{{- if .Values.namespaceSelector }}
- key: kubernetes.io/metadata.name
operator: "In"
values:
{{- range .Values.namespaceSelector }}
- {{ . | quote }}
{{- end }}
{{- end }}
rules:
- apiGroups:
- speedscale.com
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- trafficreplays
sideEffects: None
timeoutSeconds: 10
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
creationTimestamp: null
name: speedscale-operator-replay
annotations:
argocd.argoproj.io/hook: PreSync
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
webhooks:
- admissionReviewVersions:
- v1
clientConfig:
caBundle: {{ $cacrt | b64enc }}
service:
name: speedscale-operator
namespace: {{ .Release.Namespace }}
path: /validate-speedscale-com-v1-trafficreplay
failurePolicy: Fail
name: replay.speedscale.com
namespaceSelector:
matchExpressions:
- key: kubernetes.io/metadata.name
operator: "NotIn"
values:
- kube-system
- kube-node-lease
{{- if .Values.namespaceSelector }}
- key: kubernetes.io/metadata.name
operator: "In"
values:
{{- range .Values.namespaceSelector }}
- {{ . | quote }}
{{- end }}
{{- end }}
rules:
- apiGroups:
- speedscale.com
apiVersions:
- v1
operations:
- CREATE
- UPDATE
- DELETE
resources:
- trafficreplays
sideEffects: None
timeoutSeconds: 10
---
apiVersion: v1
kind: Secret
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
name: speedscale-webhook-certs
namespace: {{ .Release.Namespace }}
type: kubernetes.io/tls
data:
ca.crt: {{ $cacrt | b64enc }}
tls.crt: {{ $crt | b64enc }}
tls.key: {{ $key | b64enc }}

View File

@ -0,0 +1,41 @@
---
apiVersion: v1
kind: ConfigMap
metadata:
name: speedscale-operator
namespace: {{ .Release.Namespace }}
annotations:
argocd.argoproj.io/hook: PreSync
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
data:
CLUSTER_NAME: {{ .Values.clusterName }}
IMAGE_PULL_POLICY: {{ .Values.image.pullPolicy }}
IMAGE_PULL_SECRETS: ""
IMAGE_REGISTRY: {{ .Values.image.registry }}
IMAGE_TAG: {{ .Values.image.tag }}
INSTANCE_ID: '{{- $cm := (lookup "v1" "ConfigMap" .Release.Namespace "speedscale-operator") -}}{{ if $cm }}{{ $cm.data.INSTANCE_ID }}{{ else }}{{ ( printf "%s-%s" .Values.clusterName uuidv4 ) }}{{ end }}'
LOG_LEVEL: {{ .Values.logLevel }}
SPEEDSCALE_DLP_CONFIG: {{ .Values.dlp.config }}
SPEEDSCALE_FILTER_RULE: {{ .Values.filterRule }}
TELEMETRY_INTERVAL: 1s
WITH_DLP: {{ .Values.dlp.enabled | quote }}
WITH_INSPECTOR: {{ .Values.dashboardAccess | quote }}
API_KEY_SECRET_NAME: {{ .Values.apiKeySecret | quote }}
DEPLOY_DEMO: {{ .Values.deployDemo | quote }}
GLOBAL_ANNOTATIONS: {{ .Values.globalAnnotations | toJson | quote }}
GLOBAL_LABELS: {{ .Values.globalLabels | toJson | quote }}
{{- if .Values.http_proxy }}
HTTP_PROXY: {{ .Values.http_proxy }}
{{- end }}
{{- if .Values.https_proxy }}
HTTPS_PROXY: {{ .Values.https_proxy }}
{{- end }}
{{- if .Values.no_proxy }}
NO_PROXY: {{ .Values.no_proxy }}
{{- end }}
PRIVILEGED_SIDECARS: {{ .Values.privilegedSidecars | quote }}
DISABLE_SMARTDNS: {{ .Values.disableSidecarSmartReverseDNS | quote }}
SIDECAR_CONFIG: {{ .Values.sidecar | toJson | quote }}
FORWARDER_CONFIG: {{ .Values.forwarder | toJson | quote }}

View File

@ -0,0 +1,514 @@
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.15.0
creationTimestamp: null
name: trafficreplays.speedscale.com
spec:
group: speedscale.com
names:
kind: TrafficReplay
listKind: TrafficReplayList
plural: trafficreplays
shortNames:
- replay
singular: trafficreplay
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .status.active
name: Active
type: boolean
- jsonPath: .spec.mode
name: Mode
type: string
- jsonPath: .status.conditions[-1:].message
name: Status
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
name: v1
schema:
openAPIV3Schema:
description: TrafficReplay is the Schema for the trafficreplays API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: TrafficReplaySpec defines the desired state of TrafficReplay
properties:
buildTag:
description: |-
BuildTag links a unique tag, build hash, etc. to the generated
traffic replay report. That way you can connect the report results to the
version of the code that was tested.
type: string
cleanup:
description: |-
Cleanup is the name of cleanup mode used for this
TrafficReplay.
enum:
- inventory
- all
- none
type: string
collectLogs:
description: |-
CollectLogs enables or disables log collection from target
workload. Defaults to true.
DEPRECATED: use TestReport.ActualConfig.Cluster.CollectLogs
type: boolean
configChecksum:
description: |-
ConfigChecksum, managed my the operator, is the SHA1 checksum of the
configuration.
type: string
customURL:
description: CustomURL allows to specify custom URL to the SUT.
type: string
generatorLowData:
description: |-
GeneratorLowData forces the generator into a high
efficiency/low data output mode. This is ideal for high volume
performance tests. Defaults to false.
DEPRECATED
type: boolean
mode:
description: Mode is the name of replay mode used for this TrafficReplay.
enum:
- full-replay
- responder-only
- generator-only
type: string
needsReport:
description: Indicates whether a responder-only replay needs a report.
type: boolean
proxyMode:
description: |-
ProxyMode defines proxy operational mode used with injected sidecar.
DEPRECATED
type: string
responderLowData:
description: |-
ResponderLowData forces the responder into a high
efficiency/low data output mode. This is ideal for high volume
performance tests. Defaults to false.
DEPRECATED
type: boolean
secretRefs:
description: |-
SecretRefs hold the references to the secrets which contain
various secrets like (e.g. short-lived JWTs to be used by the generator
for authorization with HTTP calls).
items:
description: |-
LocalObjectReference contains enough information to locate the referenced
Kubernetes resource object.
properties:
name:
description: Name of the referent.
type: string
required:
- name
type: object
type: array
sidecar:
description: |-
Sidecar defines sidecar specific configuration.
DEPRECATED: use Workloads
properties:
inject:
description: 'DEPRECATED: do not use'
type: boolean
patch:
description: Patch is .yaml file patch for the Workload
format: byte
type: string
tls:
properties:
in:
description: In provides configuration for sidecar inbound
TLS.
properties:
private:
description: Private is the filename of the TLS inbound
private key.
type: string
public:
description: Public is the filename of the TLS inbound
public key.
type: string
secret:
description: Secret is a secret with the TLS keys to use
for inbound traffic.
type: string
type: object
mutual:
description: Mutual provides configuration for sidecar mutual
TLS.
properties:
private:
description: Private is the filename of the mutual TLS
private key.
type: string
public:
description: Public is the filename of the mutual TLS
public key.
type: string
secret:
description: Secret is a secret with the mutual TLS keys.
type: string
type: object
out:
description: |-
Out enables or disables TLS out on the
sidecar during replay.
type: boolean
type: object
type: object
snapshotID:
description: |-
SnapshotID is the id of the traffic snapshot for this
TrafficReplay.
type: string
testConfigID:
description: |-
TestConfigID is the id of the replay configuration to be used
by the generator and responder for the TrafficReplay.
type: string
timeout:
description: |-
Timeout is the time to wait for replay test to finish. Defaults
to value of the `TIMEOUT` setting of the operator.
type: string
ttlAfterReady:
description: |-
TTLAfterReady provides a TTL (time to live) mechanism to limit
the lifetime of TrafficReplay object that have finished the execution and
reached its final state (either complete or failed).
type: string
workloadRef:
description: |-
WorkloadRef is the reference to the target workload (SUT) for
TrafficReplay. The operations will be performed in the namespace of the
target object.
DEPRECATED: use Workloads
properties:
apiVersion:
description: API version of the referenced object.
type: string
kind:
description: Kind of the referenced object. Defaults to "Deployment".
type: string
name:
description: Name of the referenced object.
type: string
namespace:
description: Namespace of the referenced object. Defaults to the
TrafficReplay namespace.
type: string
required:
- name
type: object
workloads:
description: |-
Workloads define target workloads (SUT) for a TrafficReplay. Many
workloads may be provided, or none. Workloads may be modified and
restarted during replay to configure communication with a responder.
items:
description: |-
Workload represents a Kubernetes workload to be targeted during replay and
associated settings.
properties:
customURI:
description: CustomURI will be target of the traffic instead
of directly targeting workload
type: string
inTrafficKey:
description: 'DEPRECATED: use InTrafficKeys'
type: string
inTrafficKeys:
description: 'DEPRECATED: use Tests'
items:
type: string
type: array
mocks:
description: |-
Mocks are strings used to identify slices of outbound snapshot traffic to
mock for this workload and maps directly to a snapshot's `OutTraffic`
field. Snapshot egress traffic can be split across multiple slices where
each slice contains part of the traffic. A workload may specify multiple
keys and multiple workloads may specify the same key.
Only the traffic slices defined here will be mocked. A workload with no
keys defined will not mock any traffic. Pass '*' to mock all traffic.
Mock strings may only match part of the snapshot's `OutTraffic` key if the
string matches exactly one key. For example, the test string
`foo.example.com` would match the `OutTraffic` key of
my-service:foo.example.com:8080, as long as no other keys would match
`foo.example.com`. Multiple mocks must be specified for multiple keys
unless using '*'.
items:
type: string
type: array
outTrafficKeys:
description: 'DEPRECATED: use Mocks'
items:
type: string
type: array
ref:
description: |-
Ref is a reference to a cluster workload, like a deployment or a
statefulset.
properties:
apiVersion:
description: API version of the referenced object.
type: string
kind:
description: Kind of the referenced object. Defaults to
"Deployment".
type: string
name:
description: Name of the referenced object.
type: string
namespace:
description: Namespace of the referenced object. Defaults
to the TrafficReplay namespace.
type: string
required:
- name
type: object
routing:
description: Routing configures how workloads route egress traffic
to responders
enum:
- hostalias
- nat
type: string
sidecar:
description: |-
TODO: this is not implemented, come back and replace deprecated Sidecar with workload specific settings
Sidecar defines sidecar specific configuration.
properties:
inject:
description: 'DEPRECATED: do not use'
type: boolean
patch:
description: Patch is .yaml file patch for the Workload
format: byte
type: string
tls:
properties:
in:
description: In provides configuration for sidecar inbound
TLS.
properties:
private:
description: Private is the filename of the TLS
inbound private key.
type: string
public:
description: Public is the filename of the TLS inbound
public key.
type: string
secret:
description: Secret is a secret with the TLS keys
to use for inbound traffic.
type: string
type: object
mutual:
description: Mutual provides configuration for sidecar
mutual TLS.
properties:
private:
description: Private is the filename of the mutual
TLS private key.
type: string
public:
description: Public is the filename of the mutual
TLS public key.
type: string
secret:
description: Secret is a secret with the mutual
TLS keys.
type: string
type: object
out:
description: |-
Out enables or disables TLS out on the
sidecar during replay.
type: boolean
type: object
type: object
tests:
description: |-
Tests are strings used to identify slices of inbound snapshot traffic this
workload is targeting and maps directly to a snapshot's `InTraffic` field.
Snapshot ingress traffic can be split across multiple slices where each
slice contains part of the traffic. A key must only be specified once
across all workloads, but a workload may specify multiple keys.
Test strings may only match part of the snapshot's `InTraffic` key if the
string matches exactly one key. For example, the test string
`foo.example.com` would match the `InTraffic` key of
my-service:foo.example.com:8080, as long as no other keys would match
`foo.example.com`
This field is optional in the spec to provide support for single-workload
and legacy replays, but must be specified for multi-workload replays in
order to provide deterministic replay configuration.
items:
type: string
type: array
type: object
type: array
required:
- snapshotID
- testConfigID
type: object
status:
default:
observedGeneration: -1
description: TrafficReplayStatus defines the observed state of TrafficReplay
properties:
active:
description: Active indicates whether this traffic replay is currently
underway or not.
type: boolean
conditions:
items:
description: "Condition contains details for one aspect of the current
state of this API Resource.\n---\nThis struct is intended for
direct use as an array at the field path .status.conditions. For
example,\n\n\n\ttype FooStatus struct{\n\t // Represents the
observations of a foo's current state.\n\t // Known .status.conditions.type
are: \"Available\", \"Progressing\", and \"Degraded\"\n\t //
+patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t
\ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\"
patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t
\ // other fields\n\t}"
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: |-
type of condition in CamelCase or in foo.example.com/CamelCase.
---
Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be
useful (see .node.status.conditions), the ability to deconflict is important.
The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
finishedTime:
description: Information when the traffic replay has finished.
format: date-time
type: string
initializedTime:
description: Information when the test environment was successfully
prepared.
format: date-time
type: string
lastHeartbeatTime:
description: 'DEPRECATED: will not be set'
format: date-time
type: string
observedGeneration:
description: ObservedGeneration is the last observed generation.
format: int64
type: integer
reconcileFailures:
description: |-
ReconcileFailures is the number of times the traffic replay controller
experienced an error during the reconciliation process. The traffic
replay will be deleted if too many errors occur.
format: int64
type: integer
reportID:
description: The id of the traffic replay report created.
type: string
reportURL:
description: The url to the traffic replay report.
type: string
startedTime:
description: Information when the traffic replay has started.
format: date-time
type: string
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
plural: ""
conditions: null
storedVersions: null

View File

@ -0,0 +1,132 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
operator.speedscale.com/ignore: "true"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
labels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
{{- if .Values.globalLabels }}
{{ toYaml .Values.globalLabels | indent 4}}
{{- end }}
name: speedscale-operator
namespace: {{ .Release.Namespace }}
spec:
replicas: 1
selector:
matchLabels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
strategy:
type: Recreate
template:
metadata:
annotations:
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 8}}
{{- end }}
labels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
{{- if .Values.globalLabels }}
{{ toYaml .Values.globalLabels | indent 8}}
{{- end }}
spec:
containers:
- command:
- /operator
env:
- name: POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
envFrom:
- configMapRef:
name: speedscale-operator
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#container-v1-core
# When a key exists in multiple sources, the value associated with the last source will take precedence.
# Values defined by an Env with a duplicate key will take precedence.
- configMapRef:
name: speedscale-operator-override
optional: true
- secretRef:
name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}'
optional: false
image: '{{ .Values.image.registry }}/operator:{{ .Values.image.tag }}'
imagePullPolicy: {{ .Values.image.pullPolicy }}
livenessProbe:
failureThreshold: 5
httpGet:
path: /healthz
port: health-check
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 30
successThreshold: 1
timeoutSeconds: 5
name: operator
ports:
- containerPort: 443
name: webhook-server
- containerPort: 8081
name: health-check
readinessProbe:
failureThreshold: 10
httpGet:
path: /readyz
port: health-check
scheme: HTTP
initialDelaySeconds: 5
periodSeconds: 5
successThreshold: 1
timeoutSeconds: 5
resources: {{- toYaml .Values.operator.resources | nindent 10 }}
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: false
# Run as root to bind 443 https://github.com/kubernetes/kubernetes/issues/56374
runAsUser: 0
volumeMounts:
- mountPath: /tmp
name: tmp
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: webhook-certs
readOnly: true
- mountPath: /etc/ssl/speedscale
name: speedscale-tls-out
readOnly: true
hostNetwork: {{ .Values.hostNetwork }}
securityContext:
runAsNonRoot: true
serviceAccountName: speedscale-operator
terminationGracePeriodSeconds: 10
volumes:
- emptyDir: {}
name: tmp
- name: webhook-certs
secret:
secretName: speedscale-webhook-certs
- name: speedscale-tls-out
secret:
secretName: speedscale-certs
{{- if .Values.affinity }}
affinity: {{ toYaml .Values.affinity | nindent 8 }}
{{- end }}
{{- if .Values.tolerations }}
tolerations: {{ toYaml .Values.tolerations | nindent 8 }}
{{- end }}
{{- if .Values.nodeSelector }}
nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,73 @@
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "4"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
name: speedscale-operator-pre-install
namespace: {{ .Release.Namespace }}
labels:
{{- if .Values.globalLabels }}
{{ toYaml .Values.globalLabels | indent 4}}
{{- end }}
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 30
template:
metadata:
annotations:
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 8}}
{{- end }}
creationTimestamp: null
labels:
{{- if .Values.globalLabels }}
{{ toYaml .Values.globalLabels | indent 8}}
{{- end }}
spec:
containers:
- args:
- |-
# ensure valid settings before the chart reports a successfull install
{{- if .Values.http_proxy }}
HTTP_PROXY={{ .Values.http_proxy | quote }} \
{{- end }}
{{- if .Values.https_proxy }}
HTTPS_PROXY={{ .Values.https_proxy | quote }} \
{{- end }}
{{- if .Values.no_proxy }}
NO_PROXY={{ .Values.no_proxy | quote }} \
{{- end }}
speedctl init --overwrite --no-rcfile-update \
--api-key $SPEEDSCALE_API_KEY \
--app-url $SPEEDSCALE_APP_URL
# in case we're in istio
curl -X POST http://127.0.0.1:15000/quitquitquit || true
command:
- sh
- -c
envFrom:
- secretRef:
name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}'
optional: false
image: '{{ .Values.image.registry }}/speedscale-cli:{{ .Values.image.tag }}'
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: speedscale-cli
resources: {}
restartPolicy: Never
{{- if .Values.affinity }}
affinity: {{ toYaml .Values.affinity | nindent 8 }}
{{- end }}
{{- if .Values.tolerations }}
tolerations: {{ toYaml .Values.tolerations | nindent 8 }}
{{- end }}
{{- if .Values.nodeSelector }}
nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }}
{{- end }}

View File

@ -0,0 +1,244 @@
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
creationTimestamp: null
name: speedscale-operator
{{- if .Values.globalAnnotations }}
annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }}
{{- end }}
rules:
- apiGroups:
- apps
resources:
- deployments
- statefulsets
- daemonsets
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- apps
resources:
- replicasets
verbs:
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- batch
resources:
- jobs
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- apiextensions.k8s.io
resources:
- customresourcedefinitions
verbs:
- get
- list
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
- validatingwebhookconfigurations
verbs:
- get
- list
- apiGroups:
- rbac.authorization.k8s.io
resources:
- clusterrolebindings
- clusterroles
verbs:
- get
- list
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- pods
- services
- serviceaccounts
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- apiGroups:
- ""
resources:
- events
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- nodes
verbs:
- get
- list
- watch
- apiGroups:
- metrics.k8s.io
resources:
- pods
verbs:
- get
- list
- watch
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- networking.istio.io
resources:
- envoyfilters
- sidecars
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- security.istio.io
resources:
- peerauthentications
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- speedscale.com
resources:
- trafficreplays
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- speedscale.com
resources:
- trafficreplays/status
verbs:
- get
- update
- patch
- apiGroups:
- argoproj.io
resources:
- rollouts
verbs:
- get
- list
- patch
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: speedscale-operator
{{- if .Values.globalAnnotations }}
annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }}
{{- end }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: speedscale-operator
subjects:
- kind: ServiceAccount
name: speedscale-operator
namespace: {{ .Release.Namespace }}
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
creationTimestamp: null
labels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
name: speedscale-operator
namespace: {{ .Release.Namespace }}
{{- if .Values.globalAnnotations }}
annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }}
{{- end }}

View File

@ -0,0 +1,18 @@
---
{{ if .Values.apiKey }}
apiVersion: v1
kind: Secret
metadata:
name: speedscale-apikey
namespace: {{ .Release.Namespace }}
annotations:
helm.sh/hook: pre-install
helm.sh/hook-weight: "3"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
type: Opaque
data:
SPEEDSCALE_API_KEY: {{ .Values.apiKey | b64enc }}
SPEEDSCALE_APP_URL: {{ .Values.appUrl | b64enc }}
{{ end }}

View File

@ -0,0 +1,22 @@
---
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
name: speedscale-operator
namespace: {{ .Release.Namespace }}
{{- if .Values.globalAnnotations }}
annotations: {{ toYaml .Values.globalAnnotations | nindent 4 }}
{{- end }}
spec:
ports:
- port: 443
protocol: TCP
selector:
app: speedscale-operator
controlplane.speedscale.com/component: operator
status:
loadBalancer: {}

View File

@ -0,0 +1,183 @@
{{- $crt := "" -}}
{{- $key := "" -}}
{{- $s := (lookup "v1" "Secret" .Release.Namespace "speedscale-certs") -}}
{{- if $s -}}
{{- $crt = index $s.data "tls.crt" | b64dec -}}
{{- $key = index $s.data "tls.key" | b64dec -}}
{{ else }}
{{- $cert := genCA "Speedscale" 3650 -}}
{{- $crt = $cert.Cert -}}
{{- $key = $cert.Key -}}
{{- end -}}
---
apiVersion: batch/v1
kind: Job
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "5"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
name: speedscale-operator-create-jks
namespace: {{ .Release.Namespace }}
labels:
{{- if .Values.globalLabels }}
{{ toYaml .Values.globalLabels | indent 4}}
{{- end }}
spec:
backoffLimit: 0
ttlSecondsAfterFinished: 30
template:
metadata:
annotations:
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 8}}
{{- end }}
creationTimestamp: null
labels:
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 8}}
{{- end }}
spec:
containers:
- args:
- |-
keytool -keystore /usr/lib/jvm/jre/lib/security/cacerts -importcert -noprompt -trustcacerts -storepass changeit -alias speedscale -file /etc/ssl/speedscale/tls.crt
kubectl -n ${POD_NAMESPACE} delete secret speedscale-jks || true
kubectl -n ${POD_NAMESPACE} create secret generic speedscale-jks --from-file=cacerts.jks=/usr/lib/jvm/jre/lib/security/cacerts
# in case we're in istio
curl -X POST http://127.0.0.1:15000/quitquitquit || true
command:
- sh
- -c
volumeMounts:
- mountPath: /etc/ssl/speedscale
name: speedscale-tls-out
readOnly: true
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
envFrom:
- secretRef:
name: '{{ ne .Values.apiKeySecret "" | ternary .Values.apiKeySecret "speedscale-apikey" }}'
optional: false
image: '{{ .Values.image.registry }}/amazoncorretto'
imagePullPolicy: {{ .Values.image.pullPolicy }}
name: create-jks
resources: {}
restartPolicy: Never
serviceAccountName: speedscale-operator-provisioning
volumes:
- name: speedscale-tls-out
secret:
secretName: speedscale-certs
{{- if .Values.affinity }}
affinity: {{ toYaml .Values.affinity | nindent 8 }}
{{- end }}
{{- if .Values.tolerations }}
tolerations: {{ toYaml .Values.tolerations | nindent 8 }}
{{- end }}
{{- if .Values.nodeSelector }}
nodeSelector: {{ toYaml .Values.nodeSelector | nindent 8 }}
{{- end }}
---
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "1"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
labels:
app: speedscale-operator
controlplane.speedscale.com/component: operator
name: speedscale-operator-provisioning
namespace: {{ .Release.Namespace }}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "2"
creationTimestamp: null
name: speedscale-operator-provisioning
rules:
- apiGroups:
- ""
resources:
- secrets
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
- apiGroups:
- admissionregistration.k8s.io
resources:
- mutatingwebhookconfigurations
- validatingwebhookconfigurations
verbs:
- create
- delete
- deletecollection
- get
- list
- patch
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
helm.sh/hook-weight: "3"
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
name: speedscale-operator-provisioning
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: speedscale-operator-provisioning
subjects:
- kind: ServiceAccount
name: speedscale-operator-provisioning
namespace: {{ .Release.Namespace }}
---
apiVersion: v1
kind: Secret
metadata:
annotations:
helm.sh/hook: pre-install
helm.sh/hook-delete-policy: before-hook-creation
{{- if .Values.globalAnnotations }}
{{ toYaml .Values.globalAnnotations | indent 4}}
{{- end }}
creationTimestamp: null
name: speedscale-certs
namespace: {{ .Release.Namespace }}
type: kubernetes.io/tls
data:
tls.crt: {{ $crt | b64enc }}
tls.key: {{ $key | b64enc }}

View File

@ -0,0 +1,133 @@
# An API key is required to connect to the Speedscale cloud.
# If you need a key email support@speedscale.com.
apiKey: ""
# A secret name can be referenced instead of the api key itself.
# The secret must be of the format:
#
# type: Opaque
# data:
# SPEEDSCALE_API_KEY: <key>
# SPEEDSCALE_APP_URL: <appUrl>
apiKeySecret: ""
# Speedscale domain to use.
appUrl: "app.speedscale.com"
# The name of your cluster.
clusterName: "my-cluster"
# Speedscale components image settings.
image:
registry: gcr.io/speedscale
tag: v2.2.185
pullPolicy: Always
# Log level for Speedscale components.
logLevel: "info"
# Namespaces to be watched by Speedscale Operator as a list of names.
namespaceSelector: []
# Instructs operator to deploy resources necessary to interact with your cluster from the Speedscale dashboard.
dashboardAccess: true
# Filter Rule to apply to the Speedscale Forwarder
filterRule: "standard"
# Data Loss Prevention settings.
dlp:
# Instructs operator to enable data loss prevention features
enabled: false
# Configuration for data loss prevention
config: "standard"
# If the operator pod/webhooks need to be on the host network.
# This is only needed if the control plane cannot connect directly to a pod
# for eg. if Calico is used as EKS's default networking
# https://docs.tigera.io/calico/3.25/getting-started/kubernetes/managed-public-cloud/eks#install-eks-with-calico-networking
hostNetwork: false
# A set of annotations to be applied to all Speedscale related deployments,
# services, jobs, pods, etc.
#
# Example:
# annotation.first: value
# annotation.second: value
globalAnnotations: {}
# A set of labels to be applied to all Speedscale related deployments,
# services, jobs, pods, etc.
#
# Example:
# label1: value
# label2: value
globalLabels: {}
# A full affinity object as detailed: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes-using-node-affinity
affinity: {}
# The list of tolerations as detailed: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/
tolerations: []
# A nodeselector object as detailed: https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/
nodeSelector: {}
# Deploy a demo app at startup. Set this to an empty string to not deploy.
# Valid values: ["java", ""]
deployDemo: "java"
# Proxy connection settings if required by your network. These translate to standard proxy environment
# variables HTTP_PROXY, HTTPS_PROXY, and NO_PROXY
http_proxy: ""
https_proxy: ""
no_proxy: ""
# control if sidecar init containers should run with privileged set
privilegedSidecars: false
# control if the sidecar should enable/disable use of the smart dns lookup feature (requires NET_ADMIN)
disableSidecarSmartReverseDNS: false
# Operator settings. These limits are recommended unless you have a cluster
# with a very large number of workloads (for eg. 10k+ deployments, replicasets, etc.).
operator:
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# Default sidecar settings. Example:
# sidecar:
# resources:
# limits:
# cpu: 500m
# memory: 512Mi
# ephemeral-storage: 100Mi
# requests:
# cpu: 10m
# memory: 32Mi
# ephemeral-storage: 100Mi
# ignore_src_hosts: example.com, example.org
# ignore_src_ips: 8.8.8.8, 1.1.1.1
# ignore_dst_hosts: example.com, example.org
# ignore_dst_ips: 8.8.8.8, 1.1.1.1
# insert_init_first: false
# tls_out: false
# reinitialize_iptables: false
sidecar: {}
# Forwarder settings
# forwarder:
# resources:
# limits:
# cpu: 500m
# memory: 500M
# requests:
# cpu: 300m
# memory: 250M
forwarder: {}

View File

@ -13844,6 +13844,64 @@ entries:
- assets/intel/intel-device-plugins-sgx-0.26.1.tgz
version: 0.26.1
jenkins:
- annotations:
artifacthub.io/category: integration-delivery
artifacthub.io/changes: |
- Update `configuration-as-code` to version `1836.vccda_4a_122a_a_e`
artifacthub.io/images: |
- name: jenkins
image: docker.io/jenkins/jenkins:2.452.3-jdk17
- name: k8s-sidecar
image: docker.io/kiwigrid/k8s-sidecar:1.27.5
- name: inbound-agent
image: jenkins/inbound-agent:3256.v88a_f6e922152-1
artifacthub.io/license: Apache-2.0
artifacthub.io/links: |
- name: Chart Source
url: https://github.com/jenkinsci/helm-charts/tree/main/charts/jenkins
- name: Jenkins
url: https://www.jenkins.io/
- name: support
url: https://github.com/jenkinsci/helm-charts/issues
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Jenkins
catalog.cattle.io/kube-version: '>=1.14-0'
catalog.cattle.io/release-name: jenkins
apiVersion: v2
appVersion: 2.452.3
created: "2024-07-20T00:45:42.908050461Z"
description: 'Jenkins - Build great things at any scale! As the leading open source
automation server, Jenkins provides over 1800 plugins to support building, deploying
and automating any project. '
digest: 9cc470d08ef5c554b9603fa7c50acd7341a34d6afaed7c21a1d89eae06b8ab03
home: https://www.jenkins.io/
icon: file://assets/icons/jenkins.svg
keywords:
- jenkins
- ci
- devops
kubeVersion: '>=1.14-0'
maintainers:
- email: maor.friedman@redhat.com
name: maorfr
- email: mail@torstenwalter.de
name: torstenwalter
- email: garridomota@gmail.com
name: mogaal
- email: wmcdona89@gmail.com
name: wmcdona89
- email: timjacomb1@gmail.com
name: timja
name: jenkins
sources:
- https://github.com/jenkinsci/jenkins
- https://github.com/jenkinsci/docker-inbound-agent
- https://github.com/maorfr/kube-tasks
- https://github.com/jenkinsci/configuration-as-code-plugin
type: application
urls:
- assets/jenkins/jenkins-5.4.3.tgz
version: 5.4.3
- annotations:
artifacthub.io/category: integration-delivery
artifacthub.io/changes: |
@ -30980,6 +31038,37 @@ entries:
- assets/btp/sextant-2.2.21.tgz
version: 2.2.21
speedscale-operator:
- annotations:
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Speedscale Operator
catalog.cattle.io/kube-version: '>= 1.17.0-0'
catalog.cattle.io/release-name: speedscale-operator
apiVersion: v1
appVersion: 2.2.185
created: "2024-07-20T00:45:45.523949439Z"
description: Stress test your APIs with real world scenarios. Collect and replay
traffic without scripting.
digest: 0a77c2f679f7efed44b62d5e660e26bfff9e13cb51772b822f076971b52b4341
home: https://speedscale.com
icon: file://assets/icons/speedscale-operator.png
keywords:
- speedscale
- test
- testing
- regression
- reliability
- load
- replay
- network
- traffic
kubeVersion: '>= 1.17.0-0'
maintainers:
- email: support@speedscale.com
name: Speedscale Support
name: speedscale-operator
urls:
- assets/speedscale/speedscale-operator-2.2.185.tgz
version: 2.2.185
- annotations:
catalog.cattle.io/certified: partner
catalog.cattle.io/display-name: Speedscale Operator
@ -36530,4 +36619,4 @@ entries:
urls:
- assets/netfoundry/ziti-host-1.5.1.tgz
version: 1.5.1
generated: "2024-07-19T00:46:38.819571093Z"
generated: "2024-07-20T00:45:41.75025663Z"