Merge remote-tracking branch 'origin/master' into version-9.0

This commit is contained in:
brokenpip3 2024-02-23 00:04:43 +01:00
commit e7dcbb6ad3
No known key found for this signature in database
GPG Key ID: 1D9BDC803797B4B6
74 changed files with 9867 additions and 5483 deletions

View File

@ -1,4 +0,0 @@
# Configuration for devbots-needs-triage - https://devbots.xyz/documentation/needs-triage/
enabled: true
label: "needs triage"

View File

@ -0,0 +1,56 @@
// For format details, see https://aka.ms/devcontainer.json
{
"name": "Jenkins kubernetes operator devcontainer",
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {
"enableNonRootDocker": "true",
"moby": "true"
},
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {
"version": "latest",
"helm": "latest",
"minikube": "none"
},
"ghcr.io/devcontainers/features/go:1": {
"version": "1.15",
"golangciLintVersion": "1.26.0"
},
"ghcr.io/mpriscella/features/kind:1": {
"version": "latest"
},
"ghcr.io/edouard-lopez/devcontainer-features/bats:0": {
"version": "latest"
},
"ghcr.io/brokenpip3/devcontainers-bats/bats-libs:0": {
}
},
// "forwardPorts": [],
"postCreateCommand": "go version",
// "postStartCommand": "nohup bash -c 'minikube start &' > minikube.log 2>&1",
// Configure tool-specific properties.
"customizations": {
"codespaces": {
"openFiles": [
"Makefile"
]
},
// install some vscode extensions
"vscode": {
"extensions": [
"golang.Go",
"jetmartin.bats",
"ms-kubernetes-tools.vscode-kubernetes-tools",
"budparr.language-hugo-vscode",
"GitHub.copilot",
"GitHub.copilot-chat"
]
}
},
// "remoteUser": "root"
}

View File

@ -4,11 +4,25 @@ updates:
directory: "/"
schedule:
interval: "daily"
groups:
golang:
patterns:
- "*"
- package-ecosystem: "npm"
directory: "/"
directory: "/website"
schedule:
interval: "daily"
groups:
npm:
patterns:
- "*"
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
interval: "daily"
groups:
actions:
patterns:
- "*"

47
.github/stale.yml vendored
View File

@ -1,47 +0,0 @@
# Configuration for probot-stale - https://github.com/probot/stale
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 30
# Number of days of inactivity before a stale Issue or Pull Request is closed.
# Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale.
daysUntilClose: 30
# Issues with these labels will never be considered stale
exemptLabels:
- frozen
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Label to use when marking an issue as stale
staleLabel: stale
issues:
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had recent activity.
It will be closed if no further activity occurs.
If this issue is still affecting you, just comment with any updates and we'll keep it open.
Thank you for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: >
Closing this issue after a prolonged period of inactivity.
If this issue is still present in the latest release, please create a new issue with up-to-date information. Thank you!
pulls:
# Comment to post when marking a pull request as stale.
markComment: >
This pull request has been automatically marked as stale because it has not had recent activity.
It will be closed if no further activity occurs.
If this pull request is still relevant, just comment with any updates and we'll keep it open.
Thank you for your contributions.
# Comment to post when closing a stale pull request. Set to `false` to disable
closeComment: >
Closing this pull request after a prolonged period of inactivity.
If this issue is still present in the latest release, please ask for this pull request to be reopened. Thank you!
# Limit the number of actions per hour, from 1-30. Default is 30
limitPerRun: 30

View File

@ -18,4 +18,4 @@ jobs:
with:
check_filenames: true
ignore_words_list: aks,ags,startin
skip: "*.js,package-lock.json,*.lock,*/Font-Awesome/*,*.toml,*.svg,*assets/vendor/bootstrap*"
skip: "*.js,package-lock.json,*.lock,*/Font-Awesome/*,*.toml,*.svg,*assets/vendor/bootstrap*,cert-manager.crds.yaml"

View File

@ -23,7 +23,7 @@ jobs:
steps:
# Checks out a copy of your repository on the ubuntu-latest machine
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
submodules: recursive # Fetch the Docsy theme
fetch-depth: 0
@ -39,7 +39,7 @@ jobs:
if: env.IS_CHANGED == 'true'
uses: peaceiris/actions-hugo@v2
with:
hugo-version: '0.62.2'
hugo-version: '0.113.0'
extended: true
# Sets up node - required by Hugo
@ -77,7 +77,7 @@ jobs:
# Creates pull request with generated docs
- name: Create Pull Request
if: env.IS_CHANGED == 'true'
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v5
with:
commit-message: Auto-updated docs
branch: docs-generator

View File

@ -0,0 +1,60 @@
name: Update k8s manifests
on:
push:
branches:
- master
- main
paths-ignore:
- 'docs/**'
- 'website/**'
- 'assets/**'
- 'backup/**'
- '*.md'
workflow_dispatch:
release:
types: [published]
jobs:
update-manifest:
name: Update k8s manifests
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up env vars
run: |
echo "HELM_VERSION=v$(sed -n 's/HELM_VERSION=//p' config.base.env)" >> $GITHUB_ENV
- name: Helm lint
run: make helm-lint
#TODO: add also the webhook part and understand if is necessary
- name: Helm update plain manifests
run: |
helm template --set fullnameOverride=jenkins-operator \
--set jenkins.enabled=false \
--set jenkins.backup.enabled=false \
--set jenkins.backup.pvc.enabled=false \
--set operator.resources.limits.cpu=100m \
--set operator.resources.limits.memory=120Mi \
--set operator.resources.requests.cpu=100m \
--set operator.resources.requests.memory=120Mi \
chart/jenkins-operator/ > deploy/all-in-one-v1alpha2.yaml
sed -i '/namespace: default/d' deploy/all-in-one-v1alpha2.yaml
sed -i 's/# Source: .*//g' deploy/all-in-one-v1alpha2.yaml
sed -i 's/app\.kubernetes\.io\/instance: release-name//g' deploy/all-in-one-v1alpha2.yaml
sed -i 's/app\.kubernetes\.io\/managed-by: Helm//g' deploy/all-in-one-v1alpha2.yaml
sed -i 's/helm\.sh\/chart: [a-zA-Z0-9]+//g' deploy/all-in-one-v1alpha2.yaml
sed -i '/^[[:space:]]*$/d' deploy/all-in-one-v1alpha2.yaml
cp chart/jenkins-operator/crds/jenkins-crd.yaml deploy/crds/jenkins.io_jenkins_crd.yaml
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
commit-message: Auto-updated Kubernetes Manifests
branch: manifest-deploy-update
title: Auto-updated Kubernetes Manifests
body: |
Auto-updated Kubernetes Manifests from master commit ${{ github.sha }}

22
.github/workflows/auto-stale-issue.yaml vendored Normal file
View File

@ -0,0 +1,22 @@
name: "Stale issue automation"
on:
workflow_dispatch:
schedule:
- cron: "0 9 * * *"
permissions:
issues: write
pull-requests: write
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v8
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 200
days-before-issue-stale: 60
days-before-issue-close: 10
exempt-pr-labels: "not-stale"
exempt-issue-labels: "not-stale"

View File

@ -44,13 +44,13 @@ jobs:
- name: Ensure Golang runtime dependencies
run: make go-dependencies
- name: Setup BATS
uses: mig4/setup-bats@v1
- name: Setup Bats and libs
uses: brokenpip3/setup-bats-libs@1.5.2
with:
bats-version: 1.9.0
- name: Setup Bats libs
uses: brokenpip3/setup-bats-libs@0.1.0
support-path: "${{ github.workspace }}/.bats/bats-support"
assert-path: "${{ github.workspace }}/.bats/bats-assert"
detik-path: "${{ github.workspace }}/.bats/bats-detik"
file-path: "${{ github.workspace }}/.bats/bats-file"
- name: Kind setup
uses: helm/kind-action@v1.5.0
@ -58,4 +58,6 @@ jobs:
cluster_name: ${{env.KIND_CLUSTER_NAME}}
- name: Jenkins Operator - bats tests
env:
BATS_LIB_PATH: "${{ github.workspace }}/.bats"
run: make bats-tests

View File

@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up env vars
run: |

View File

@ -30,7 +30,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Set up env vars
run: |

View File

@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Check envs
run: make -C backup/pvc check-env
@ -40,11 +40,13 @@ jobs:
- name: Bump the version
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request'
shell: bash
run: make -C backup/pvc sembump && make -C backup/pvc bump-version
run: |
make -C backup/pvc sembump
make -C backup/pvc bump-version
- name: Login to Quay.io
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request'
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAYIO_USERNAME }}

View File

@ -17,7 +17,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Deploy Helm chart
run: |
@ -31,7 +31,7 @@ jobs:
# Creates pull request with new chart version
- name: Create Pull Request
uses: peter-evans/create-pull-request@v3
uses: peter-evans/create-pull-request@v5
with:
commit-message: Release Helm chart ${{ github.event.inputs.chartVersion }}
branch: helm-chart-release-${{ github.event.inputs.chartVersion }}

View File

@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Prep - check out code
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Prep - Set up env vars
run: |
@ -92,7 +92,7 @@ jobs:
run: make bats-tests
- name: Post - Login to Quay.io
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAYIO_USERNAME }}

View File

@ -9,7 +9,7 @@ jobs:
steps:
- name: Checkout code
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
@ -45,7 +45,7 @@ jobs:
tag_name: ${{ env.VERSION }}
- name: Login to Quay.io
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: quay.io
username: ${{ secrets.QUAYIO_USERNAME }}

View File

@ -147,6 +147,7 @@ update-lts-version: ## Update the latest lts version
sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' chart/jenkins-operator/values.yaml
sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' test/e2e/test_utility.go
sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' test/helm/helm_test.go
sed -i 's|jenkins/jenkins:[0-9]\+.[0-9]\+.[0-9]\+|jenkins/jenkins:$(LATEST_LTS_VERSION)|g' pkg/constants/constants.go
.PHONY: run
run: export WATCH_NAMESPACE = $(NAMESPACE)
@ -387,11 +388,11 @@ ifndef BUILD_PRESENT
bats-tests: container-runtime-build-amd64 ## Run bats tests
@echo "+ $@"
kind load docker-image ${IMAGE_NAME} --name $(KIND_CLUSTER_NAME)
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p -x test/bats
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats
else
bats-tests: ## Run bats tests
@echo "+ $@"
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p -x test/bats
OPERATOR_IMAGE="${IMAGE_NAME}" TERM=xterm bats -T -p test/bats
endif
.PHONY: crc-start
@ -479,7 +480,7 @@ helm-release-latest: helm
# Download and build hugo extended locally if necessary
HUGO_PATH = $(shell pwd)/bin/hugo
HUGO_VERSION = v0.111.3
HUGO_VERSION = v0.113.0
HAS_HUGO := $(shell $(HUGO_PATH)/hugo version 2>&- | grep $(HUGO_VERSION))
.PHONY: hugo
hugo:

View File

@ -1,11 +1,16 @@
# Jenkins Operator
[![Version](https://img.shields.io/badge/version-v0.7.1-brightgreen.svg)](https://github.com/jenkinsci/kubernetes-operator/releases/tag/v0.7.1)
[![Version](https://img.shields.io/badge/version-v0.8.0-brightgreen.svg)](https://github.com/jenkinsci/kubernetes-operator/releases/tag/v0.8.0)
[![Build status](https://github.com/jenkinsci/kubernetes-operator/actions/workflows/auto-tests-e2e.yaml/badge.svg)](https://github.com/jenkinsci/kubernetes-operator/actions/workflows/auto-tests-e2e.yaml)
[![Go Report Card](https://goreportcard.com/badge/github.com/jenkinsci/kubernetes-operator "Go Report Card")](https://goreportcard.com/report/github.com/jenkinsci/kubernetes-operator)
[![Gitter chat](https://badges.gitter.im/jenkinsci/kubernetes-operator.png)](https://gitter.im/jenkinsci/kubernetes-operator)
![logo](/assets/jenkins_gopher_wide.png)
<a href="">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins_gopher_wide_exp_dark.png">
<img src="https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins_gopher_wide_exp.png">
</picture>
</a>
## What's the Jenkins Operator?

View File

@ -1 +1 @@
v0.8.0-beta
v0.8.0

View File

@ -373,7 +373,8 @@ type JenkinsMaster struct {
// Allow to override jenkins-plugin-cli default behavior
// while downloading the plugin and dependencies
// see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options
LatestPlugins bool `json:"latestPlugins"`
// +optional
LatestPlugins *bool `json:"latestPlugins,omitempty"`
// DisableCSRFProtection allows you to toggle CSRF Protection on Jenkins
DisableCSRFProtection bool `json:"disableCSRFProtection"`

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

View File

@ -1,4 +1,4 @@
FROM debian:bullseye-slim
FROM debian:bookworm-slim
LABEL maintainer="Jenkins Kubernetes Operator Community" \
org.opencontainers.image.authors="Jenkins Kubernetes Operator Community" \
@ -6,14 +6,17 @@ LABEL maintainer="Jenkins Kubernetes Operator Community" \
org.opencontainers.image.description="Jenkins Operator Backup img via pvc volume" \
org.opencontainers.image.url="quay.io/jenkins-kubernetes-operator/backup-pvc" \
org.opencontainers.image.source="https://github.com/jenkinsci/kubernetes-operator/tree/master/backup/pvc" \
org.opencontainers.image.base.name="debian:bullseye-slim"
org.opencontainers.image.base.name="debian:bookworm-slim"
ARG UID
ARG GID
ENV USER=user
RUN addgroup --gid "$GID" "$USER" && \
RUN apt update \
&& apt install -y procps zstd \
&& rm -rf /var/lib/apt/lists/* \
&& addgroup --gid "$GID" "$USER" && \
adduser \
--disabled-password \
--gecos "" \
@ -21,9 +24,9 @@ RUN addgroup --gid "$GID" "$USER" && \
--uid "$UID" \
"$USER"
COPY bin/*.sh /home/user/bin/
RUN chmod +x /home/user/bin/*.sh
WORKDIR /home/user/bin
COPY bin .
RUN chmod +x *.sh
USER user
CMD ./run.sh

View File

@ -1 +1 @@
v0.2.2
v0.2.5

View File

@ -6,7 +6,7 @@ set -eo pipefail
[[ -z "${BACKUP_DIR}" ]] && echo "Required 'BACKUP_DIR' env not set" && exit 1;
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
BACKUP_TMP_DIR=$(mktemp -d)
trap "test -d "${BACKUP_TMP_DIR}" && rm -fr "${BACKUP_TMP_DIR}"" EXIT ERR SIGINT SIGTERM
trap "test -d "${BACKUP_TMP_DIR}" && rm -fr "${BACKUP_TMP_DIR}"" EXIT SIGINT SIGTERM
backup_number=$1
echo "Running backup"
@ -15,12 +15,22 @@ echo "Running backup"
# config.xml in child directories is state that should. For example-
# branches/myorg/branches/myrepo/branches/master/config.xml should be retained while
# branches/myorg/config.xml should not
tar -C "${JENKINS_HOME}" -czf "${BACKUP_TMP_DIR}/${backup_number}.tar.gz" --exclude jobs/*/workspace* --no-wildcards-match-slash --anchored --exclude jobs/*/config.xml -c jobs && \
mv "${BACKUP_TMP_DIR}/${backup_number}.tar.gz" "${BACKUP_DIR}/${backup_number}.tar.gz"
tar --zstd -C "${JENKINS_HOME}" -cf "${BACKUP_TMP_DIR}/${backup_number}.tar.zstd" \
--exclude jobs/*/workspace* \
--no-wildcards-match-slash --anchored \
--ignore-failed-read \
--exclude jobs/*/config.xml -c jobs || ret=$?
if [[ "$ret" -eq 0 ]]; then
echo "Backup was completed without warnings"
mv "${BACKUP_TMP_DIR}/${backup_number}.tar.zstd" "${BACKUP_DIR}/${backup_number}.tar.zstd"
elif [[ "$ret" -eq 1 ]]; then
echo "Backup was completed with some warnings"
mv "${BACKUP_TMP_DIR}/${backup_number}.tar.zstd" "${BACKUP_DIR}/${backup_number}.tar.zstd"
fi
rm -rf "${BACKUP_TMP_DIR}"
[[ ! -s ${BACKUP_DIR}/${backup_number}.tar.gz ]] && echo "backup file '${BACKUP_DIR}/${backup_number}.tar.gz' is empty" && exit 1;
[[ ! -s ${BACKUP_DIR}/${backup_number}.tar.zstd ]] && echo "backup file '${BACKUP_DIR}/${backup_number}.tar.zstd' is empty" && exit 1;
echo Done
exit 0

View File

@ -3,8 +3,8 @@
set -eo pipefail
[[ -z "${BACKUP_DIR}" ]] && echo "Required 'BACKUP_DIR' env not set" && exit 1
latest=$(find ${BACKUP_DIR} -name '*.tar.gz' -exec basename {} \; | sort -g | tail -n 1)
# Search for all the tar.* inside the backup dir to support the migration between gzip vs zstd
latest=$(find ${BACKUP_DIR} -name '*.tar.*' -exec basename {} \; | sort -g | tail -n 1)
if [[ "${latest}" == "" ]]; then
echo "-1"

View File

@ -7,9 +7,23 @@ set -eo pipefail
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
backup_number=$1
backup_file="${BACKUP_DIR}/${backup_number}"
echo "Running restore backup with backup number #${backup_number}"
tar -C ${JENKINS_HOME} -zxf "${BACKUP_DIR}/${backup_number}.tar.gz"
if [[ -f "$backup_file.tar.gz" ]]; then
echo "Old format tar.gz found, restoring it"
OPTS=""
EXT="tar.gz"
elif [[ -f "$backup_file.tar.zstd" ]]; then
echo "Backup file found, proceeding"
OPTS="--zstd"
EXT="tar.zstd"
else
echo "ERR: Backup file not found: $backup_file"
exit 1
fi
tar $OPTS -C "${JENKINS_HOME}" -xf "${BACKUP_DIR}/${backup_number}.${EXT}"
echo Done
exit 0

View File

@ -11,6 +11,6 @@ do
if [[ ! -z "${BACKUP_COUNT}" ]]; then
echo "Trimming to only ${BACKUP_COUNT} recent backups in preparation for new backup"
#TODO: add the list of exceeding backup before delete
find ${BACKUP_DIR} -maxdepth 1 -name '*.tar.gz' -exec basename {} \; | sort -gr | tail -n +$((BACKUP_COUNT +1)) | xargs -I '{}' rm ${BACKUP_DIR}/'{}'
find ${BACKUP_DIR} -maxdepth 1 -name '*.tar.zstd' -exec basename {} \; | sort -gr | tail -n +$((BACKUP_COUNT +1)) | xargs -I '{}' rm ${BACKUP_DIR}/'{}'
fi
done

View File

@ -30,7 +30,7 @@ trap "docker rm -vf $cid > /dev/null;rm -rf ${BACKUP_DIR};rm -rf ${RESTORE_FOLDE
backup_number=1
docker exec ${cid} /home/user/bin/backup.sh ${backup_number}
backup_file="${BACKUP_DIR}/${backup_number}.tar.gz"
backup_file="${BACKUP_DIR}/${backup_number}.tar.zstd"
[[ ! -f ${backup_file} ]] && echo "Backup file ${backup_file} not found" && exit 1;
docker exec ${cid} /bin/bash -c "JENKINS_HOME=${RESTORE_FOLDER};/home/user/bin/restore.sh ${backup_number}"
@ -38,4 +38,4 @@ docker exec ${cid} /bin/bash -c "JENKINS_HOME=${RESTORE_FOLDER};/home/user/bin/r
echo "Compare directories"
diff --brief --recursive "${RESTORE_FOLDER}" "${JENKINS_HOME_AFTER_RESTORE}"
echo "Directories are the same"
echo PASS
echo PASS

View File

@ -19,17 +19,17 @@ mkdir -p ${BACKUP_DIR}
mkdir -p ${JENKINS_HOME}
mkdir -p ${BACKUP_DIR}/lost+found
touch ${BACKUP_DIR}/1.tar.gz
touch ${BACKUP_DIR}/2.tar.gz
touch ${BACKUP_DIR}/3.tar.gz
touch ${BACKUP_DIR}/4.tar.gz
touch ${BACKUP_DIR}/5.tar.gz
touch ${BACKUP_DIR}/6.tar.gz
touch ${BACKUP_DIR}/7.tar.gz
touch ${BACKUP_DIR}/8.tar.gz
touch ${BACKUP_DIR}/9.tar.gz
touch ${BACKUP_DIR}/10.tar.gz
touch ${BACKUP_DIR}/11.tar.gz
touch ${BACKUP_DIR}/1.tar.zstd
touch ${BACKUP_DIR}/2.tar.zstd
touch ${BACKUP_DIR}/3.tar.zstd
touch ${BACKUP_DIR}/4.tar.zstd
touch ${BACKUP_DIR}/5.tar.zstd
touch ${BACKUP_DIR}/6.tar.zstd
touch ${BACKUP_DIR}/7.tar.zstd
touch ${BACKUP_DIR}/8.tar.zstd
touch ${BACKUP_DIR}/9.tar.zstd
touch ${BACKUP_DIR}/10.tar.zstd
touch ${BACKUP_DIR}/11.tar.zstd
# Create an instance of the container under testing
cid="$(docker run -e JENKINS_HOME=${JENKINS_HOME} -v ${JENKINS_HOME}:${JENKINS_HOME}:ro -e BACKUP_DIR=${BACKUP_DIR} -v ${BACKUP_DIR}:${BACKUP_DIR}:rw -d ${docker_image})"
@ -39,7 +39,7 @@ echo "Docker container ID '${cid}'"
trap "docker rm -vf $cid > /dev/null;rm -rf ${BACKUP_DIR};rm -rf ${JENKINS_HOME}" EXIT
latest=$(docker exec ${cid} /bin/bash -c "JENKINS_HOME=${RESTORE_FOLDER};/home/user/bin/get-latest.sh")
rm ${BACKUP_DIR}/*.tar.gz
rm ${BACKUP_DIR}/*.tar.zstd
empty_latest=$(docker exec ${cid} /bin/bash -c "JENKINS_HOME=${RESTORE_FOLDER};/home/user/bin/get-latest.sh")
if [[ "${DEBUG}" ]]; then

View File

@ -19,17 +19,17 @@ mkdir -p ${BACKUP_DIR}
mkdir -p ${JENKINS_HOME}
mkdir -p ${BACKUP_DIR}/lost+found
touch ${BACKUP_DIR}/1.tar.gz
touch ${BACKUP_DIR}/2.tar.gz
touch ${BACKUP_DIR}/3.tar.gz
touch ${BACKUP_DIR}/4.tar.gz
touch ${BACKUP_DIR}/5.tar.gz
touch ${BACKUP_DIR}/6.tar.gz
touch ${BACKUP_DIR}/7.tar.gz
touch ${BACKUP_DIR}/8.tar.gz
touch ${BACKUP_DIR}/9.tar.gz
touch ${BACKUP_DIR}/10.tar.gz
touch ${BACKUP_DIR}/11.tar.gz
touch ${BACKUP_DIR}/1.tar.zstd
touch ${BACKUP_DIR}/2.tar.zstd
touch ${BACKUP_DIR}/3.tar.zstd
touch ${BACKUP_DIR}/4.tar.zstd
touch ${BACKUP_DIR}/5.tar.zstd
touch ${BACKUP_DIR}/6.tar.zstd
touch ${BACKUP_DIR}/7.tar.zstd
touch ${BACKUP_DIR}/8.tar.zstd
touch ${BACKUP_DIR}/9.tar.zstd
touch ${BACKUP_DIR}/10.tar.zstd
touch ${BACKUP_DIR}/11.tar.zstd
# Create an instance of the container under testing
cid="$(docker run -e BACKUP_COUNT=2 -e JENKINS_HOME=${JENKINS_HOME} -v ${JENKINS_HOME}:${JENKINS_HOME}:ro -e BACKUP_DIR=${BACKUP_DIR} -v ${BACKUP_DIR}:${BACKUP_DIR}:rw -d ${docker_image})"
@ -39,7 +39,7 @@ echo "Docker container ID '${cid}'"
trap "docker rm -vf $cid > /dev/null;rm -rf ${BACKUP_DIR};rm -rf ${JENKINS_HOME}" EXIT
sleep 11
touch ${BACKUP_DIR}/12.tar.gz
touch ${BACKUP_DIR}/12.tar.zstd
sleep 11
if [[ "${DEBUG}" ]]; then
@ -48,7 +48,7 @@ if [[ "${DEBUG}" ]]; then
fi
# only two latest backup should exists
[[ $(ls -1 ${BACKUP_DIR} | grep 'tar.gz' | wc -l) -eq 2 ]] || exit 1
[[ -f ${BACKUP_DIR}/11.tar.gz ]] || exit 2
[[ -f ${BACKUP_DIR}/12.tar.gz ]] || exit 3
[[ $(ls -1 ${BACKUP_DIR} | grep 'tar.zstd' | wc -l) -eq 2 ]] || exit 1
[[ -f ${BACKUP_DIR}/11.tar.zstd ]] || exit 2
[[ -f ${BACKUP_DIR}/12.tar.zstd ]] || exit 3
echo PASS

View File

@ -29,8 +29,8 @@ docker exec ${cid} /home/user/bin/backup.sh ${backup_number}
[ "$(docker exec ${cid} ls /tmp | grep 'tmp')" ] && echo "tmp directory not empty" && exit 1;
backup_file="${BACKUP_DIR}/${backup_number}.tar.gz"
backup_file="${BACKUP_DIR}/${backup_number}.tar.zstd"
[[ ! -f ${backup_file} ]] && echo "Backup file ${backup_file} not found" && exit 1;
echo "tmp directory empty, backup in backup directory present"
echo PASS
echo PASS

View File

@ -1,6 +1,36 @@
apiVersion: v1
entries:
jenkins-operator:
- apiVersion: v2
appVersion: 0.8.0
created: "2023-09-13T06:54:41.369295961Z"
dependencies:
- condition: webhook.enabled
name: cert-manager
repository: https://charts.jetstack.io
version: 1.5.1
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
digest: da8ae04166cb1b64a9dd3d741c6a50d63846ebe8e2e92f09313ad3c6a0dd9ca4
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
name: jenkins-operator
urls:
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.8.0.tgz
version: 0.8.0
- apiVersion: v2
appVersion: 0.8.0-beta.2
created: "2023-06-30T21:22:53.308590035Z"
dependencies:
- condition: webhook.enabled
name: cert-manager
repository: https://charts.jetstack.io
version: 1.5.1
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
digest: b2502f91dffa1136190a8a98d73ac997c70387e100d79200b7403039ca98411e
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
name: jenkins-operator
urls:
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.8.0-beta.2.tgz
version: 0.8.0-beta.2
- apiVersion: v2
appVersion: v0.8.0-beta
created: "2023-04-17T22:11:04.706959723Z"
@ -348,4 +378,4 @@ entries:
urls:
- https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart/jenkins-operator/jenkins-operator-0.0.1.tgz
version: 0.0.1
generated: "2023-04-17T22:11:04.68789848Z"
generated: "2023-09-13T06:54:41.354056045Z"

View File

@ -1,8 +1,8 @@
apiVersion: v2
appVersion: "v0.8.0-beta"
appVersion: "0.8.0"
description: Kubernetes native operator which fully manages Jenkins on Kubernetes
name: jenkins-operator
version: v0.8.0-beta
version: 0.8.0
icon: https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/assets/jenkins-operator-icon.png
dependencies:
- name: cert-manager

View File

@ -1,6 +1,6 @@
# jenkins-operator
![Version: 0.6.2](https://img.shields.io/badge/Version-0.6.2-informational?style=flat-square) ![AppVersion: 0.7.1](https://img.shields.io/badge/AppVersion-0.7.1-informational?style=flat-square)
![Version: 0.8.0-beta.2](https://img.shields.io/badge/Version-0.8.0--beta.2-informational?style=flat-square) ![AppVersion: 0.8.0-beta.2](https://img.shields.io/badge/AppVersion-0.8.0--beta.2-informational?style=flat-square)
Kubernetes native operator which fully manages Jenkins on Kubernetes
@ -28,7 +28,7 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
| jenkins.backup.env[2].name | string | `"BACKUP_COUNT"` | |
| jenkins.backup.env[2].value | string | `"3"` | |
| jenkins.backup.getLatestAction[0] | string | `"/home/user/bin/get-latest.sh"` | |
| jenkins.backup.image | string | `"quay.io/jenkins-kubernetes-operator/backup-pvc:v0.2.1"` | |
| jenkins.backup.image | string | `"quay.io/jenkins-kubernetes-operator/backup-pvc:v0.2.6"` | |
| jenkins.backup.interval | int | `30` | |
| jenkins.backup.makeBackupBeforePodDeletion | bool | `true` | |
| jenkins.backup.pvc.className | string | `""` | |
@ -52,7 +52,7 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
| jenkins.enabled | bool | `true` | |
| jenkins.env | list | `[]` | |
| jenkins.hostAliases | object | `{}` | |
| jenkins.image | string | `"jenkins/jenkins:2.387.2-lts"` | |
| jenkins.image | string | `"jenkins/jenkins:2.414.1-lts"` | |
| jenkins.imagePullPolicy | string | `"Always"` | |
| jenkins.imagePullSecrets | list | `[]` | |
| jenkins.labels | object | `{}` | |
@ -88,13 +88,14 @@ Kubernetes native operator which fully manages Jenkins on Kubernetes
| jenkins.seedJobAgentImage | string | `""` | |
| jenkins.seedJobs | list | `[]` | |
| jenkins.serviceAccount.annotations | object | `{}` | |
| jenkins.tolerations | list | `[]` | |
| jenkins.validateSecurityWarnings | bool | `false` | |
| jenkins.volumeMounts | list | `[]` | |
| jenkins.volumes[0].name | string | `"backup"` | |
| jenkins.volumes[0].persistentVolumeClaim.claimName | string | `"jenkins-backup"` | |
| operator.affinity | object | `{}` | |
| operator.fullnameOverride | string | `""` | |
| operator.image | string | `"quay.io/jenkins-kubernetes-operator/operator:v0.8.0-beta"` | |
| operator.image | string | `"quay.io/jenkins-kubernetes-operator/operator:v0.8.0"` | |
| operator.imagePullPolicy | string | `"IfNotPresent"` | |
| operator.imagePullSecrets | list | `[]` | |
| operator.nameOverride | string | `""` | |

View File

@ -157,11 +157,11 @@ spec:
type: object
basePlugins:
description: 'BasePlugins contains plugins required by operator
Defaults to : - name: kubernetes version: "1.31.3" - name:
workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version:
"2.6" - name: git version: "4.11.3" - name: job-dsl version:
"1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name:
kubernetes-credentials-provider version: "0.20"'
Defaults to : - name: configuration-as-code version: "1625.v27444588cc3d"
- name: git version: "5.0.0" - name: job-dsl version: "1.83"
- name: kubernetes version: "3909.v1f2c633e8590" - name: kubernetes-credentials-provider
version: "1.211.vc236a_f5a_2f3c" - name: workflow-aggregator
version: "596.v8c21c963d92d" - name: workflow-job version: "1289.vd1c337fd5354"'
items:
description: Plugin defines Jenkins plugin.
properties:
@ -1100,11 +1100,6 @@ spec:
- resources
type: object
type: array
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies, see:
https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
disableCSRFProtection:
description: DisableCSRFProtection allows you to toggle CSRF Protection
on Jenkins
@ -1150,6 +1145,10 @@ spec:
selectors of replication controllers and services. More info:
http://kubernetes.io/docs/user-guide/labels'
type: object
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
nodeSelector:
additionalProperties:
type: string
@ -3124,8 +3123,10 @@ spec:
type: object
type: array
seedJobAgentImage:
description: SeedJobAgentImage defines the image that will be used
by the seed job agent. If not defined jenkins/inbound-agent:4.9-1
will be used.
type: string
description: 'SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:4.10-3 will be used.'
seedJobs:
description: 'SeedJobs defines list of Jenkins Seed Job configurations
More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines'

Binary file not shown.

View File

@ -95,6 +95,9 @@ spec:
{{- with .Values.jenkins.nodeSelector }}
nodeSelector: {{ toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.jenkins.tolerations }}
tolerations: {{ toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.jenkins.annotations }}
annotations: {{ toYaml . | nindent 6 }}
{{- end }}
@ -134,7 +137,7 @@ spec:
{{- if .Values.jenkins.backup.enabled }}
- name: {{ .Values.jenkins.backup.containerName }}
image: {{ .Values.jenkins.backup.image }}
imagePullPolicy: IfNotPresent
imagePullPolicy: {{ .Values.jenkins.imagePullPolicy }}
{{- with .Values.jenkins.backup.resources }}
resources: {{ toYaml . | nindent 10 }}
{{- end }}

View File

@ -31,7 +31,7 @@ spec:
protocol: TCP
command:
- /manager
args:
args:
{{- if .Values.webhook.enabled }}
- --validate-security-warnings
{{- end }}
@ -41,9 +41,29 @@ spec:
name: webhook-certs
readOnly: true
{{- end }}
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
env:
- name: WATCH_NAMESPACE
{{- if .Values.jenkins.enabled }}
value: {{ .Values.jenkins.namespace }}
{{- else if .Values.operator.watchNamespace }}
value: {{ .Values.operator.watchNamespace }}
{{- else }}
valueFrom:
fieldRef:
fieldPath: metadata.namespace
{{- end }}
- name: POD_NAME
valueFrom:
fieldRef:
@ -71,4 +91,4 @@ spec:
defaultMode: 420
secretName: jenkins-{{ .Values.webhook.certificate.name }}
terminationGracePeriodSeconds: 10
{{- end }}
{{- end }}

View File

@ -27,13 +27,16 @@ jenkins:
# nodeSelector are injected into metadata nodeSelector field
nodeSelector: {}
# tolerations are injected into metadata tolerations field
tolerations: []
# annotations are injected into metadata annotations field
annotations: {}
# image is the name (and tag) of the Jenkins instance
# Default: jenkins/jenkins:lts
# It's recommended to use LTS (tag: "lts") version
image: jenkins/jenkins:2.387.2-lts
image: jenkins/jenkins:2.414.1-lts
# env contains jenkins container environment variables
env: []
@ -87,19 +90,19 @@ jenkins:
#
# basePlugins:
# - name: kubernetes
# version: 3909.v1f2c633e8590
# version: 4029.v5712230ccb_f8
# - name: workflow-job
# version: 1289.vd1c337fd5354
# version: 1342.v046651d5b_dfe
# - name: workflow-aggregator
# version: 596.v8c21c963d92d
# - name: git
# version: 5.0.0
# version: 5.2.1
# - name: job-dsl
# version: "1.83"
# version: "1.85"
# - name: configuration-as-code
# version: 1625.v27444588cc3d
# version: 1647.ve39ca_b_829b_42
# - name: kubernetes-credentials-provider
# version: 1.211.vc236a_f5a_2f3c
# version: 1.234.vf3013b_35f5b_a
basePlugins: []
@ -207,7 +210,7 @@ jenkins:
# image used by backup feature
# By default using prebuilt backup PVC image
image: quay.io/jenkins-kubernetes-operator/backup-pvc:v0.2.1
image: quay.io/jenkins-kubernetes-operator/backup-pvc:v0.2.6
# containerName is backup container name
containerName: backup
@ -273,10 +276,10 @@ jenkins:
# configuration is section where we can configure Jenkins instance
# See https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/customization/ for details
configuration:
configurationAsCode: {}
configurationAsCode: []
# - configMapName: jenkins-casc
# content: {}
groovyScripts: {}
groovyScripts: []
# - configMapName: jenkins-gs
# content: {}
@ -291,7 +294,7 @@ operator:
replicaCount: 1
# image is the name (and tag) of the Jenkins Operator image
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0-beta
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0
# imagePullPolicy defines policy for pulling images
imagePullPolicy: IfNotPresent
@ -305,6 +308,10 @@ operator:
# fullnameOverride overrides the deployment name
fullnameOverride: ""
# Select a different namespace to look for the Jenkins CR and deploy Jenkins in. Defaults to the same namespace as
# the operator.
# watchNamespace: "jenkins-namespace"
resources: {}
nodeSelector: {}
tolerations: []

View File

@ -11,7 +11,7 @@ API_VERSION_NEXT=v1alpha3
ALL_IN_ONE_DEPLOY_FILE_PREFIX=all-in-one
GEN_CRD_API=gen-crd-api-reference-docs
IMAGE_PULL_MODE=local
HELM_VERSION=3.1.2
HELM_VERSION=3.12.3
CLUSTER_DOMAIN=cluster.local
LATEST_LTS_VERSION=2.387.2
LATEST_LTS_VERSION=2.414.1
KIND_CLUSTER_NAME=jenkins

View File

@ -32,6 +32,176 @@ rules:
- create
- patch
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins-operator
rules:
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- '*'
- apiGroups:
- apps
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
- builds
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- services
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- jenkins.io
resources:
- jenkins/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- "route.openshift.io"
resources:
- routes
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- "image.openshift.io"
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- "build.openshift.io"
resources:
- builds
- buildconfigs
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
@ -43,236 +213,76 @@ roleRef:
subjects:
- kind: ServiceAccount
name: jenkins-operator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jenkins-operator
rules:
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- '*'
- apiGroups:
- apps
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
- builds
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- services
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- jenkins.io
resources:
- jenkins
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- jenkins.io
resources:
- jenkins/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- route.openshift.io
resources:
- routes
verbs:
- create
- get
- list
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: manager-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins-operator
subjects:
- kind: ServiceAccount
- kind: ServiceAccount
name: jenkins-operator
roleRef:
kind: Role
name: jenkins-operator
apiGroup: rbac.authorization.k8s.io
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-operator
labels:
control-plane: controller-manager
app.kubernetes.io/name: jenkins-operator
helm.sh/chart: jenkins-operator-0.8.0
app.kubernetes.io/version: "0.8.0"
spec:
replicas: 1
selector:
matchLabels:
control-plane: controller-manager
replicas: 1
app.kubernetes.io/name: jenkins-operator
template:
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: jenkins-operator
spec:
serviceAccountName: jenkins-operator
securityContext:
runAsUser: 65532
containers:
- command:
- /manager
args:
- --leader-elect
image: virtuslab/jenkins-operator:v0.7.1
name: jenkins-operator
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 100m
memory: 90Mi
requests:
cpu: 100m
memory: 60Mi
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
terminationGracePeriodSeconds: 10
- name: jenkins-operator
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
command:
- /manager
args:
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: OPERATOR_NAME
value: "jenkins-operator"
resources:
limits:
cpu: 100m
memory: 120Mi
requests:
cpu: 100m
memory: 120Mi

File diff suppressed because it is too large Load Diff

View File

@ -68,13 +68,11 @@ func buildConfigMapTypeMeta() metav1.TypeMeta {
}
func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
defaultlatestPlugin := true
latestP := jenkins.Spec.Master.LatestPlugins
if !latestP {
latestP = defaultlatestPlugin
if latestP == nil {
latestP = new(bool)
*latestP = true
}
data := struct {
JenkinsHomePath string
InitConfigurationPath string
@ -90,7 +88,7 @@ func buildInitBashScript(jenkins *v1alpha2.Jenkins) (*string, error) {
UserPlugins: jenkins.Spec.Master.Plugins,
InstallPluginsCommand: installPluginsCommand,
JenkinsScriptsVolumePath: JenkinsScriptsVolumePath,
LatestPlugins: latestP,
LatestPlugins: *latestP,
}
output, err := render.Render(initBashTemplate, data)

View File

@ -56,6 +56,10 @@ func (r *reconcileUserConfiguration) ReconcileCasc() (reconcile.Result, error) {
func (r *reconcileUserConfiguration) ReconcileOthers() (reconcile.Result, error) {
backupAndRestore := backuprestore.New(r.Configuration, r.logger)
if err := backupAndRestore.Restore(r.jenkinsClient); err != nil {
return reconcile.Result{}, err
}
result, err := r.ensureSeedJobs()
if err != nil {
return reconcile.Result{}, err
@ -64,10 +68,6 @@ func (r *reconcileUserConfiguration) ReconcileOthers() (reconcile.Result, error)
return result, nil
}
if err := backupAndRestore.Restore(r.jenkinsClient); err != nil {
return reconcile.Result{}, err
}
if err := backupAndRestore.Backup(false); err != nil {
return reconcile.Result{}, err
}

View File

@ -8,7 +8,7 @@ const (
// SeedJobSuffix is a suffix added for all seed jobs
SeedJobSuffix = "job-dsl-seed"
// DefaultJenkinsMasterImage is the default Jenkins master docker image
DefaultJenkinsMasterImage = "jenkins/jenkins:2.319.3-lts"
DefaultJenkinsMasterImage = "jenkins/jenkins:2.414.1-lts"
// DefaultHTTPPortInt32 is the default Jenkins HTTP port
DefaultHTTPPortInt32 = int32(8080)
// DefaultSlavePortInt32 is the default Jenkins port for slaves

View File

@ -1,13 +1,13 @@
package plugins
const (
configurationAsCodePlugin = "configuration-as-code:1625.v27444588cc3d"
gitPlugin = "git:5.0.0"
jobDslPlugin = "job-dsl:1.83"
kubernetesPlugin = "kubernetes:3909.v1f2c633e8590"
kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:1.211.vc236a_f5a_2f3c"
configurationAsCodePlugin = "configuration-as-code:1700.v6f448841296e"
gitPlugin = "git:5.2.1"
jobDslPlugin = "job-dsl:1.85"
kubernetesPlugin = "kubernetes:4029.v5712230ccb_f8"
kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:1.234.vf3013b_35f5b_a"
workflowAggregatorPlugin = "workflow-aggregator:596.v8c21c963d92d"
workflowJobPlugin = "workflow-job:1289.vd1c337fd5354"
workflowJobPlugin = "workflow-job:1342.v046651d5b_dfe"
)
// basePluginsList contains plugins to install by operator.

View File

@ -23,6 +23,8 @@ diag() {
--set jenkins.namespace=${DETIK_CLIENT_NAMESPACE} \
--set namespace=${DETIK_CLIENT_NAMESPACE} \
--set operator.image=${OPERATOR_IMAGE} \
--set jenkins.latestPlugins=true \
--set jenkins.backup.makeBackupBeforePodDeletion=false \
chart/jenkins-operator
assert_success
assert ${HELM} status default
@ -98,6 +100,19 @@ diag() {
assert_success
}
#bats test_tags=phase:helm
@test "1.9 Helm: check Jenkins crd" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
run verify "there is 1 crd named 'jenkins.jenkins.io'"
assert_success
}
@test "1.9 Helm: Clean" {
run ${HELM} uninstall default
assert_success
# Wait for the complete removal
sleep 30
run verify "there is 0 pvc named 'jenkins backup'"
assert_success
rm "chart/jenkins-operator/deploy.tmp"
}

View File

@ -0,0 +1,90 @@
setup() {
load 'test_helper'
_common_setup
}
#bats test_tags=phase:helm
@test "2.1 Install helm chart with options" {
# The kind storage class provider needs some sec to delete the old pvc
sleep 30
run ${HELM} dependency update chart/jenkins-operator
assert_success
run ${KUBECTL} label node jenkins-control-plane batstest=yep
${HELM} status options && skip "Helm release 'options' already exists"
run ${HELM} install options \
--set jenkins.namespace=${DETIK_CLIENT_NAMESPACE} \
--set namespace=${DETIK_CLIENT_NAMESPACE} \
--set operator.image=${OPERATOR_IMAGE} \
--set jenkins.latestPlugins=true \
--set jenkins.nodeSelector.batstest=yep \
--set jenkins.backup.makeBackupBeforePodDeletion=false \
chart/jenkins-operator
assert_success
assert ${HELM} status options
touch "chart/jenkins-operator/deploy.tmp"
}
#bats test_tags=phase:helm
@test "2.2 Helm: check Jenkins operator pods status" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
run verify "there is 1 deployment named 'options-jenkins-operator'"
assert_success
run verify "there is 1 pod named 'options-jenkins-operator-'"
assert_success
run try "at most 20 times every 10s to get pods named 'options-jenkins-operator-' and verify that '.status.containerStatuses[?(@.name==\"jenkins-operator\")].ready' is 'true'"
assert_success
}
#bats test_tags=phase:helm
@test "2.3 Helm: check Jenkins Pod status" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
run try "at most 20 times every 10s to get pods named 'jenkins-jenkins' and verify that '.status.containerStatuses[?(@.name==\"jenkins-master\")].ready' is 'true'"
assert_success
run try "at most 20 times every 5s to get pods named 'jenkins-jenkins' and verify that '.status.containerStatuses[?(@.name==\"jenkins-master\")].ready' is 'true'"
assert_success
}
@test "2.4 check node selector" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
NODENAME=$(${KUBECTL} get pod jenkins-jenkins -o jsonpath={.spec.nodeName})
run ${KUBECTL} get node -l batstest=yep -o name
assert_success
assert_output "node/$NODENAME"
}
@test "2.5 check jenkins-plugin-cli command" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
run ${KUBECTL} logs -c jenkins-master jenkins-jenkins
assert_success
assert_output --partial 'jenkins-plugin-cli --verbose --latest true -f /var/lib/jenkins/base-plugins.txt'
assert_output --partial 'jenkins-plugin-cli --verbose --latest true -f /var/lib/jenkins/user-plugins.txt'
}
@test "2.7 check backup" {
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
sleep 120
run ${KUBECTL} logs -l app.kubernetes.io/name=jenkins-operator --tail 10000
assert_success
assert_output --partial "Performing backup '1'"
assert_output --partial "Backup completed '1', updating status"
}
@test "2. Helm: Clean" {
skip
[[ ! -f "chart/jenkins-operator/deploy.tmp" ]] && skip "Jenkins helm chart have not been deployed correctly"
run ${HELM} uninstall options
assert_success
rm "chart/jenkins-operator/deploy.tmp"
}

View File

@ -1,5 +1,5 @@
_common_setup() {
export BATS_LIB_PATH="/usr/lib/"
export BATS_LIB_PATH="${BATS_LIB_PATH}:/usr/lib"
bats_load_library bats-support
bats_load_library bats-assert
bats_load_library bats-file

View File

@ -24,13 +24,13 @@ import (
const e2e = "e2e"
var expectedBasePluginsList = []plugins.Plugin{
plugins.Must(plugins.New("configuration-as-code:1625.v27444588cc3d")),
plugins.Must(plugins.New("git:5.0.0")),
plugins.Must(plugins.New("kubernetes:3909.v1f2c633e8590")),
plugins.Must(plugins.New("kubernetes-credentials-provider:1.211.vc236a_f5a_2f3c")),
plugins.Must(plugins.New("job-dsl:1.83")),
plugins.Must(plugins.New("configuration-as-code:1700.v6f448841296e")),
plugins.Must(plugins.New("git:5.2.1")),
plugins.Must(plugins.New("kubernetes:4029.v5712230ccb_f8")),
plugins.Must(plugins.New("kubernetes-credentials-provider:1.234.vf3013b_35f5b_a")),
plugins.Must(plugins.New("job-dsl:1.85")),
plugins.Must(plugins.New("workflow-aggregator:596.v8c21c963d92d")),
plugins.Must(plugins.New("workflow-job:1289.vd1c337fd5354")),
plugins.Must(plugins.New("workflow-job:1342.v046651d5b_dfe")),
}
func createUserConfigurationSecret(namespace string, stringData map[string]string) {

View File

@ -244,7 +244,7 @@ func restartJenkinsMasterPod(jenkins *v1alpha2.Jenkins) {
Eventually(func() (bool, error) {
jenkinsPod = getJenkinsMasterPod(jenkins)
return jenkinsPod.DeletionTimestamp != nil, nil
}, 30*retryInterval, retryInterval).Should(BeTrue())
}, 45*retryInterval, retryInterval).Should(BeTrue())
_, _ = fmt.Fprintf(GinkgoWriter, "Jenkins master pod has been restarted\n")
}

View File

@ -21,7 +21,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
const JenkinsTestImage = "jenkins/jenkins:2.387.2-lts"
const JenkinsTestImage = "jenkins/jenkins:2.414.1-lts"
var (
Cfg *rest.Config

View File

@ -47,7 +47,7 @@ var _ = Describe("Jenkins Controller", func() {
cmd := exec.Command("../../bin/helm", "upgrade", "jenkins", "../../chart/jenkins-operator", "--namespace", namespace.Name, "--debug",
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name),
"--set-string", fmt.Sprintf("jenkins.image=%s", "jenkins/jenkins:2.387.2-lts"),
"--set-string", fmt.Sprintf("jenkins.image=%s", "jenkins/jenkins:2.414.1-lts"),
"--set-string", fmt.Sprintf("operator.image=%s", *imageName), "--install")
output, err := cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred(), string(output))
@ -77,12 +77,12 @@ var _ = Describe("Jenkins Controller with security validator", func() {
invalidPlugins = []v1alpha2.Plugin{
{Name: "simple-theme-plugin", Version: "0.6"},
{Name: "audit-trail", Version: "3.8"},
{Name: "github", Version: "1.31.0"},
{Name: "github", Version: "1.36.0"},
}
validPlugins = []v1alpha2.Plugin{
{Name: "simple-theme-plugin", Version: "136.v23a_15f86c53d"},
{Name: "audit-trail", Version: "3.11"},
{Name: "github", Version: "1.36.0"},
{Name: "github", Version: "1.37.3.1"},
}
)
@ -117,7 +117,7 @@ var _ = Describe("Jenkins Controller with security validator", func() {
jenkins := e2e.RenderJenkinsCR(jenkinsCRName, namespace.Name, seedJobs, groovyScripts, casc, "")
jenkins.Spec.Master.Plugins = invalidPlugins
jenkins.Spec.ValidateSecurityWarnings = true
Expect(e2e.K8sClient.Create(context.TODO(), jenkins)).Should(MatchError("admission webhook \"vjenkins.kb.io\" denied the request: security vulnerabilities detected in the following user-defined plugins: \ngithub:1.31.0"))
Expect(e2e.K8sClient.Create(context.TODO(), jenkins)).Should(MatchError("admission webhook \"vjenkins.kb.io\" denied the request: security vulnerabilities detected in the following user-defined plugins: \ngithub:1.36.0"))
})
})
Context("When Jenkins CR doesn't contain plugins with security warnings", func() {
@ -127,6 +127,7 @@ var _ = Describe("Jenkins Controller with security validator", func() {
"--set-string", fmt.Sprintf("jenkins.namespace=%s", namespace.Name),
"--set-string", fmt.Sprintf("operator.image=%s", *imageName),
"--set", fmt.Sprintf("webhook.enabled=%t", true),
"--set", fmt.Sprintf("jenkins.latestPlugins=%t", true),
"--set", fmt.Sprintf("jenkins.enabled=%t", false), "--install")
output, err := cmd.CombinedOutput()
Expect(err).NotTo(HaveOccurred(), string(output))

View File

@ -2,7 +2,7 @@
title: "Getting Started"
linkTitle: "Getting Started"
weight: 2
date: 2021-08-19
date: 2023-06-04
description: >
How to work with Jenkins Operator
---

View File

@ -1,19 +1,19 @@
---
title: "Latest (v0.7.x)"
linkTitle: "Latest (v0.7.x)"
title: "Latest (v0.8.x)"
linkTitle: "Latest (v0.8.x)"
weight: 1
date: 2021-12-08
date: 2023-31-05
description: >
How to work with the latest, currently supported Jenkins Operator version.
---
{{% pageinfo %}}
This document describes a getting started guide for **Jenkins Operator** `v0.7.x` and also additional configuration.
This document describes a getting started guide for **Jenkins Operator** `v0.8.x` and also additional configuration.
{{% /pageinfo %}}
## First Steps
Prepare your Kubernetes cluster and set up your `kubectl` access.
Once you have a running Kubernetes cluster you can focus on installing **Jenkins Operator** according to the
Once you have a running Kubernetes cluster you can focus on installing **Jenkins Operator** according to the
[Installation](/kubernetes-operator/docs/getting-started/latest/installing-the-operator/) guide.

View File

@ -7,8 +7,8 @@ description: >
Prevent loss of job history
---
> Because of Jenkins Operator's architecture, the configuration of Jenkins should be done using ConfigurationAsCode
> or GroovyScripts and jobs should be defined as SeedJobs. It means that there is no point in backing up any job configuration
> Because of Jenkins Operator's architecture, the configuration of Jenkins should be done using ConfigurationAsCode
> or GroovyScripts and jobs should be defined as SeedJobs. It means that there is no point in backing up any job configuration
> up. Therefore, the backup script makes a copy of jobs history only.
Backup and restore is done by a container sidecar.
@ -54,7 +54,7 @@ spec:
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.277.4-lts-alpine
image: jenkins/jenkins:2.401.1-lts
imagePullPolicy: IfNotPresent
resources:
limits:
@ -71,7 +71,7 @@ spec:
value: /jenkins-home
- name: BACKUP_COUNT
value: "3" # keep only the 2 most recent backups
image: virtuslab/jenkins-operator-backup-pvc:v0.1.1 # look at backup/pvc directory
image: quay.io/jenkins-kubernetes-operator/backup-pvc:v0.2.3 # look at backup/pvc directory
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /jenkins-home # Jenkins home volume

View File

@ -14,7 +14,7 @@ This document describes the procedure for deploying Jenkins.
## Prerequisites
The Operator needs to have been deployed beforehand. The procedure for deploying Jenkins described here doesn't apply to
installation of Operator via Helm chart unless `jenkins.enabled` was set to false.
installation of Operator via Helm chart unless `jenkins.enabled` was set to false.
Thats because by default, installation via Helm chart also covers deploying Jenkins.
@ -43,7 +43,7 @@ spec:
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.319.1-lts-alpine
image: jenkins/jenkins:2.401.1-lts
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12

View File

@ -127,11 +127,13 @@ Name of resource. The pod name will be <code>jenkins-&lt;name&gt;</code> (name w
<code>namespace</code>
</td>
<td>
default
""
</td>
<td>
Namespace the resources will be deployed to. It's not recommended to use default namespace.
Create new namespace for jenkins (e.g. <code>kubectl create -n jenkins</code>)
Namespace the resources will be deployed to. If omitted, the resources will be deployed to the same namespace as the operator.
It's not recommended to use default namespace. Create new namespace for jenkins (e.g. <code>kubectl create -n jenkins</code>).
<b>Note:</b> If the Jenkins instance is disabled, this property will be ignored. Use the `operator.watchNamespace` property instead.
</td>
</tr>
<tr>
@ -941,7 +943,7 @@ spec:
args:
- --leader-elect
<b>- --validate-security-warnings</b>
image: virtuslab/jenkins-operator:v0.7.0
image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0
name: jenkins-operator
imagePullPolicy: IfNotPresent
securityContext:

View File

@ -7,4 +7,6 @@ description: >
Additional configuration for OpenShift
---
## Release 0.7.0 is not compatible with OpenShift.
## Release 0.8.0 is not compatible with jenkins image shipped by redhat in OpenShift.
But probably it will run correctly with the jenkins lts version. If you find any issue please report it here: https://github.com/jenkinsci/kubernetes-operator/issues/826.

View File

@ -281,7 +281,7 @@ spec:
- /manager
args:
- --leader-elect
image: virtuslab/jenkins-operator:v0.7.0
image: image: quay.io/jenkins-kubernetes-operator/operator:v0.8.0
name: jenkins-operator
imagePullPolicy: IfNotPresent
securityContext:
@ -536,7 +536,7 @@ spec:
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.319.1-lts-alpine
image: jenkins/jenkins:2.401.1-lts
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12

View File

@ -0,0 +1,19 @@
---
title: "Latest (v0.8.x)"
linkTitle: "Latest (v0.8.x)"
weight: 1
date: 2021-12-08
description: >
How to work with the latest, currently supported Jenkins Operator version.
---
{{% pageinfo %}}
This document describes a getting started guide for **Jenkins Operator** `v0.8.x` and also additional configuration.
{{% /pageinfo %}}
## First Steps
Prepare your Kubernetes cluster and set up your `kubectl` access.
Once you have a running Kubernetes cluster you can focus on installing **Jenkins Operator** according to the
[Installation](/kubernetes-operator/docs/getting-started/latest/installing-the-operator/) guide.

View File

@ -0,0 +1,24 @@
---
title: "AKS"
linkTitle: "AKS"
weight: 8
date: 2021-12-08
description: >
Additional configuration for Azure Kubernetes Service
---
Azure AKS managed Kubernetes service adds to every pod the following environment variables:
```yaml
- name: KUBERNETES_PORT_443_TCP_ADDR
value:
- name: KUBERNETES_PORT
value: tcp://
- name: KUBERNETES_PORT_443_TCP
value: tcp://
- name: KUBERNETES_SERVICE_HOST
value:
```
The operator is aware of it and omits these environment variables when checking if a Jenkins pod environment has been changed. It prevents the
restart of a Jenkins pod over and over again.

View File

@ -0,0 +1,111 @@
---
title: "Configuring backup and restore"
linkTitle: "Configuring backup and restore"
weight: 5
date: 2023-01-08
description: >
Prevent loss of job history
---
> Because of Jenkins Operator's architecture, the configuration of Jenkins should be done using ConfigurationAsCode
> or GroovyScripts and jobs should be defined as SeedJobs. It means that there is no point in backing up any job configuration
> up. Therefore, the backup script makes a copy of jobs history only.
Backup and restore is done by a container sidecar.
### PVC
#### Create PVC
Save to the file named pvc.yaml:
```yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <pvc_name>
namespace: <namespace>
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 500Gi
```
Run the following command:
```bash
$ kubectl -n <namespace> create -f pvc.yaml
```
#### Configure Jenkins CR
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: jenkins-cr
spec:
jenkinsAPISettings:
authorizationStrategy: createUser
master:
securityContext:
runAsUser: 1000
fsGroup: 1000
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.277.4-lts-alpine
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1500m
memory: 3Gi
requests:
cpu: "1"
memory: 500Mi
- name: backup # container responsible for the backup and restore
env:
- name: BACKUP_DIR
value: /backup
- name: JENKINS_HOME
value: /jenkins-home
- name: BACKUP_COUNT
value: "3" # keep only the 2 most recent backups
image: virtuslab/jenkins-operator-backup-pvc:v0.1.1 # look at backup/pvc directory
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: /jenkins-home # Jenkins home volume
name: jenkins-home
- mountPath: /backup # backup volume
name: backup
resources:
limits:
cpu: 1000m
memory: 3Gi
requests:
cpu: "1"
memory: 500Mi
volumes:
- name: backup # PVC volume where backups will be stored
persistentVolumeClaim:
claimName: <pvc_name>
backup:
containerName: backup # container name is responsible for backup
action:
exec:
command:
- /home/user/bin/backup.sh # this command is invoked on "backup" container to make backup, for example /home/user/bin/backup.sh <backup_number>, <backup_number> is passed by operator
interval: 30 # how often make backup in seconds
makeBackupBeforePodDeletion: true # make a backup before pod deletion
restore:
containerName: backup # container name is responsible for restore backup
action:
exec:
command:
- /home/user/bin/restore.sh # this command is invoked on "backup" container to make restore backup, for example /home/user/bin/restore.sh <backup_number>, <backup_number> is passed by operator
#recoveryOnce: <backup_number> # if want to restore specific backup configure this field and then Jenkins will be restarted and desired backup will be restored
getLatestAction:
exec:
command:
- /home/user/bin/get-latest.sh # this command is invoked on "backup" container to get last backup number before pod deletion; not having it in the CR may cause loss of data
```

View File

@ -0,0 +1,336 @@
---
title: "Configuring Seed Jobs and Pipelines"
linkTitle: "Configuring Seed Jobs and Pipelines"
weight: 4
date: 2021-12-08
description: >
How to configure Jenkins with Operator
---
## Configure Seed Jobs and Pipelines
Jenkins operator uses [job-dsl][job-dsl] and [kubernetes-credentials-provider][kubernetes-credentials-provider] plugins for configuring jobs
and deploy keys.
## Prepare job definitions and pipelines
First you have to prepare pipelines and job definition in your GitHub repository using the following structure:
```
cicd/
├── jobs
│   └── k8s.jenkins
└── pipelines
└── k8s.jenkins
```
**`cicd/jobs/k8s.jenkins`** is a job definition:
```
#!/usr/bin/env groovy
pipelineJob('k8s-e2e') {
displayName('Kubernetes Plugin E2E Test')
logRotator {
numToKeep(10)
daysToKeep(30)
}
configure { project ->
project / 'properties' / 'org.jenkinsci.plugins.workflow.job.properties.DurabilityHintJobProperty' {
hint('PERFORMANCE_OPTIMIZED')
}
}
definition {
cpsScm {
scm {
git {
remote {
url('https://github.com/jenkinsci/kubernetes-operator.git')
credentials('jenkins-operator')
}
branches('*/master')
}
}
scriptPath('cicd/pipelines/k8s.jenkins')
}
}
}
```
**`cicd/pipelines/k8s.jenkins`** is an actual Jenkins pipeline:
```
#!/usr/bin/env groovy
def label = "k8s-${UUID.randomUUID().toString()}"
def home = "/home/jenkins"
def workspace = "${home}/workspace/build-jenkins-operator"
def workdir = "${workspace}/src/github.com/jenkinsci/kubernetes-operator/"
podTemplate(label: label,
containers: [
containerTemplate(name: 'alpine', image: 'alpine:3.11', ttyEnabled: true, command: 'cat'),
],
) {
node(label) {
stage('Run shell') {
container('alpine') {
sh 'echo "hello world"'
}
}
}
}
```
## Configure Seed Jobs
Jenkins Seed Jobs are configured using `Jenkins.spec.seedJobs` section from your custom resource manifest:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
**Jenkins Operator** will automatically discover and configure all the seed jobs.
You can verify if deploy keys were successfully configured in the Jenkins **Credentials** tab.
![jenkins](/kubernetes-operator/img/jenkins-credentials.png)
You can verify if your pipelines were successfully configured in the Jenkins Seed Job console output.
![jenkins](/kubernetes-operator/img/jenkins-seed.png)
If your GitHub repository is **private** you have to configure SSH or username/password authentication.
### SSH authentication
#### Generate SSH Keys
There are two methods of SSH private key generation:
```bash
$ openssl genrsa -out <filename> 2048
```
or
```bash
$ ssh-keygen -t rsa -b 2048
$ ssh-keygen -p -f <filename> -m pem
```
Then copy content from generated file.
#### Public key
If you want to upload your public key to your Git server you need to extract it.
If key was generated by `openssl` then you need to type this to extract public key:
```bash
$ openssl rsa -in <filename> -pubout > <filename>.pub
```
If key was generated by `ssh-keygen` the public key content is located in <filename>.pub and there is no need to extract public key
#### Configure SSH authentication
Configure a seed job like this:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator-ssh
credentialType: basicSSHUserPrivateKey
credentialID: k8s-ssh
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: git@github.com:jenkinsci/kubernetes-operator.git
```
and create a Kubernetes Secret (name of secret should be the same from `credentialID` field):
```
apiVersion: v1
kind: Secret
metadata:
name: k8s-ssh
labels:
"jenkins.io/credentials-type": "basicSSHUserPrivateKey"
annotations:
"jenkins.io/credentials-description" : "ssh github.com:jenkinsci/kubernetes-operator"
stringData:
privateKey: |
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAxxDpleJjMCN5nusfW/AtBAZhx8UVVlhhhIKXvQ+dFODQIdzO
oDXybs1zVHWOj31zqbbJnsfsVZ9Uf3p9k6xpJ3WFY9b85WasqTDN1xmSd6swD4N8
...
username: github_user_name
```
### Username & password authentication
Configure the seed job like:
```
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator-user-pass
credentialType: usernamePassword
credentialID: k8s-user-pass
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
and create a Kubernetes Secret (name of secret should be the same from `credentialID` field):
```
apiVersion: v1
kind: Secret
metadata:
name: k8s-user-pass
stringData:
username: github_user_name
password: password_or_token
```
### External authentication
You can use `external` credential type if you want to configure authentication using Configuration As Code or Groovy Script.
Example:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
seedJobs:
- id: jenkins-operator-external
credentialType: external
credentialID: k8s-external
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
Remember that `credentialID` must match the id of the credentials configured in Jenkins. Consult the
[Jenkins docs for using credentials][jenkins-using-credentials] for details.
## HTTP Proxy for downloading plugins
To use forwarding proxy with an operator to download plugins you need to add the following environment variable to Jenkins Custom Resource (CR), e.g.:
```yaml
spec:
master:
containers:
- name: jenkins-master
env:
- name: CURL_OPTIONS
value: -L -x <proxy_url>
```
In `CURL_OPTIONS` var you can set additional arguments to `curl` command.
## Pulling Docker images from private repositories
To pull a Docker Image from private repository you can use `imagePullSecrets`.
Please follow the instructions on [creating a secret with a docker config](https://kubernetes.io/docs/concepts/containers/images/?origin_team=T42NTAGHM#creating-a-secret-with-a-docker-config).
### Docker Hub Configuration
To use Docker Hub additional steps are required.
Edit the previously created secret:
```bash
kubectl -n <namespace> edit secret <name>
```
The `.dockerconfigjson` key's value needs to be replaced with a modified version.
After modifications, it needs to be encoded as a Base64 value before setting the `.dockerconfigjson` key.
Example config file to modify and use:
```
{
"auths":{
"https://index.docker.io/v1/":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"auth.docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry.docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"docker.io":{
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"https://registry-1.docker.io/v2/": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry-1.docker.io/v2/": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"registry-1.docker.io": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
},
"https://registry-1.docker.io": {
"username":"user",
"password":"password",
"email":"yourdockeremail@gmail.com",
"auth":"base64 of string user:password"
}
}
}
```
[job-dsl]:https://github.com/jenkinsci/job-dsl-plugin
[kubernetes-credentials-provider]:https://jenkinsci.github.io/kubernetes-credentials-provider-plugin/
[jenkins-using-credentials]:https://www.jenkins.io/doc/book/using/using-credentials/

View File

@ -0,0 +1,184 @@
---
title: "Custom backup and restore providers"
linkTitle: "Custom backup and restore providers"
weight: 7
date: 2021-12-08
description: >
Custom backup and restore provider
---
With enough effort one can create a custom backup and restore provider
for the Jenkins Operator.
## Requirements
Two commands (e.g. scripts) are required:
- a backup command, e.g. `backup.sh` that takes one argument, a **backup number**
- a restore command, e.g. `backup.sh` that takes one argument, a **backup number**
Both scripts need to return an exit code of `0` on success and `1` or greater for failure.
One of those scripts (or the entry point of the container) needs to be responsible
for backup cleanup or rotation if required, or an external system.
## How it works
The mechanism relies on basic Kubernetes and UNIX functionalities.
The backup (and restore) container runs as a sidecar in the same
Kubernetes pod as the Jenkins master.
Name of the backup and restore containers can be set as necessary using
`spec.backup.containerName` and `spec.restore.containerName`.
In most cases it will be the same container, but we allow for less common use cases.
The operator will call a backup or restore commands inside a sidecar container when necessary:
- backup command (defined in `spec.backup.action.exec.command`)
will be called every `N` seconds configurable in: `spec.backup.interval`
and on pod shutdown (if enabled in `spec.backup.makeBackupBeforePodDeletion`)
with an integer representing the current backup number as first and only argument
- restore command (defined in `spec.restore.action.exec.command`)
will be called at Jenkins startup
with an integer representing the backup number to restore as first and only argument
(can be overridden using `spec.restore.recoveryOnce`)
## Example AWS S3 backup using the CLI
This example shows abbreviated version of a simple AWS S3 backup implementation
using: `aws-cli`, `bash` and `kube2iam`.
In addition to your normal `Jenkins` `CustomResource` some additional settings
for backup and restore are required, e.g.:
```yaml
kind: Jenkins
apiVersion: jenkins.io/v1alpha1
metadata:
name: example
namespace: jenkins
spec:
master:
masterAnnotations:
iam.amazonaws.com/role: "my-example-backup-role" # tell kube2iam where the AWS IAM role is
containers:
- name: jenkins-master
...
- name: backup # container responsible for backup and restore
image: quay.io/virtuslab/aws-cli:1.16.263-2
workingDir: /home/user/bin/
command: # our container entry point
- sleep
- infinity
env:
- name: BACKUP_BUCKET
value: my-example-bucket # the S3 bucket name to use
- name: BACKUP_PATH
value: my-backup-path # the S3 bucket path prefix to use
- name: JENKINS_HOME
value: /jenkins-home # the path to mount jenkins home dir in the backup container
volumeMounts:
- mountPath: /jenkins-home # Jenkins home volume
name: jenkins-home
- mountPath: /home/user/bin/backup.sh
name: backup-scripts
subPath: backup.sh
readOnly: true
- mountPath: /home/user/bin/restore.sh
name: backup-scripts
subPath: restore.sh
readOnly: true
volumes:
- name: backup-scripts
configMap:
defaultMode: 0754
name: jenkins-operator-backup-s3
securityContext: # make sure both containers use the same UID and GUID
runAsUser: 1000
fsGroup: 1000
...
backup:
containerName: backup # container name responsible for backup
interval: 3600 # how often make a backup in seconds
makeBackupBeforePodDeletion: true # trigger backup just before deleting the pod
action:
exec:
command:
# this command is invoked on "backup" container to create a backup,
# <backup_number> is passed by operator,
# for example /home/user/bin/backup.sh <backup_number>
- /home/user/bin/backup.sh
restore:
containerName: backup # container name is responsible for restore backup
action:
exec:
command:
# this command is invoked on "backup" container to restore a backup,
# <backup_number> is passed by operator
# for example /home/user/bin/restore.sh <backup_number>
- /home/user/bin/restore.sh
# recoveryOnce: <backup_number> # if want to restore specific backup configure this field and then Jenkins will be restarted and desired backup will be restored
```
The actual backup and restore scripts will be provided in a `ConfigMap`:
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: jenkins-operator-backup-s3
namespace: jenkins
labels:
app: jenkins-operator
data:
backup.sh: |-
#!/bin/bash -xeu
[[ ! $# -eq 1 ]] && echo "Usage: $0 backup_number" && exit 1;
[[ -z "${BACKUP_BUCKET}" ]] && echo "Required 'BACKUP_BUCKET' env not set" && exit 1;
[[ -z "${BACKUP_PATH}" ]] && echo "Required 'BACKUP_PATH' env not set" && exit 1;
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
backup_number=$1
echo "Running backup #${backup_number}"
BACKUP_TMP_DIR=$(mktemp -d)
tar -C ${JENKINS_HOME} -czf "${BACKUP_TMP_DIR}/${backup_number}.tar.gz" --exclude jobs/*/workspace* -c jobs && \
aws s3 cp ${BACKUP_TMP_DIR}/${backup_number}.tar.gz s3://${BACKUP_BUCKET}/${BACKUP_PATH}/${backup_number}.tar.gz
echo Done
restore.sh: |-
#!/bin/bash -xeu
[[ ! $# -eq 1 ]] && echo "Usage: $0 backup_number" && exit 1
[[ -z "${BACKUP_BUCKET}" ]] && echo "Required 'BACKUP_BUCKET' env not set" && exit 1;
[[ -z "${BACKUP_PATH}" ]] && echo "Required 'BACKUP_PATH' env not set" && exit 1;
[[ -z "${JENKINS_HOME}" ]] && echo "Required 'JENKINS_HOME' env not set" && exit 1;
backup_number=$1
echo "Running restore #${backup_number}"
BACKUP_TMP_DIR=$(mktemp -d)
aws s3 cp s3://${BACKUP_BUCKET}/${BACKUP_PATH}/${backup_number}.tar.gz ${BACKUP_TMP_DIR}/${backup_number}.tar.gz
tar -C ${JENKINS_HOME} -zxf "${BACKUP_TMP_DIR}/${backup_number}.tar.gz"
echo Done
```
In our example we will use S3 bucket lifecycle policy to keep
the number of backups under control, e.g. Cloud Formation fragment:
```yaml
Type: AWS::S3::Bucket
Properties:
BucketName: my-example-bucket
...
LifecycleConfiguration:
Rules:
- Id: BackupCleanup
Status: Enabled
Prefix: my-backup-path
ExpirationInDays: 7
NoncurrentVersionExpirationInDays: 14
AbortIncompleteMultipartUpload:
DaysAfterInitiation: 3
```

View File

@ -0,0 +1,203 @@
---
title: "Customizing Jenkins"
linkTitle: "Customizing Jenkins"
weight: 3
date: 2021-12-08
description: >
How to customize Jenkins
---
## How to customize Jenkins
Jenkins can be customized with plugins.
Plugin's configuration is applied as groovy scripts or the [configuration as code plugin](https://github.com/jenkinsci/configuration-as-code-plugin).
Any plugin working for Jenkins can be installed by the Jenkins Operator.
Pre-installed plugins:
* configuration-as-code v1.55
* git v4.10.0
* job-dsl v1.78.1
* kubernetes-credentials-provider v0.20
* kubernetes v1.30.11
* workflow-aggregator v2.6
* workflow-job v2.42
Rest of the plugins can be found in [plugins repository](https://plugins.jenkins.io/).
#### Install plugins
Edit Custom Resource under `spec.master.plugins`:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
master:
plugins:
- name: simple-theme-plugin
version: "0.7"
```
Under `spec.master.basePlugins` you can find plugins for a valid **Jenkins Operator**:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
master:
basePlugins:
- name: kubernetes
version: "1.30.11"
- name: workflow-job
version: "2.42"
- name: workflow-aggregator
version: "2.6"
- name: git
version: "4.10.0"
- name: job-dsl
version: "1.78.1"
- name: configuration-as-code
version: "1.55"
- name: kubernetes-credentials-provider
version: "0.20"
```
You can change their versions.
The **Jenkins Operator** will then automatically install plugins after the Jenkins master pod restart.
#### Apply plugin's config
By using a [ConfigMap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/) you can create your own **Jenkins** customized configuration.
Then you must reference the **`ConfigMap`** in the **Jenkins** pod customization file in `spec.groovyScripts` or `spec.configurationAsCode`
Create a **`ConfigMap`** with specific name (eg. `jenkins-operator-user-configuration`). Then, modify the **Jenkins** manifest:
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
configurationAsCode:
configurations:
- name: jenkins-operator-user-configuration
groovyScripts:
configurations:
- name: jenkins-operator-user-configuration
```
Here is an example of `jenkins-operator-user-configuration`:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-configure-theme.groovy: |
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
import org.jenkinsci.plugins.simpletheme.ThemeElement
import org.jenkinsci.plugins.simpletheme.CssTextThemeElement
import org.jenkinsci.plugins.simpletheme.CssUrlThemeElement
Jenkins jenkins = Jenkins.getInstance()
def decorator = Jenkins.instance.getDescriptorByType(org.codefirst.SimpleThemeDecorator.class)
List<ThemeElement> configElements = new ArrayList<>();
configElements.add(new CssTextThemeElement("DEFAULT"));
configElements.add(new CssUrlThemeElement("https://cdn.rawgit.com/afonsof/jenkins-material-theme/gh-pages/dist/material-light-green.css"));
decorator.setElements(configElements);
decorator.save();
jenkins.save()
1-system-message.yaml: |
jenkins:
systemMessage: "Configuration as Code integration works!!!"
```
* `*.groovy` is Groovy script configuration
* `*.yaml is` configuration as code
If you want to correct your configuration you can edit it while the **Jenkins Operator** is running.
Jenkins will reconcile and apply the new configuration.
## How to use secrets from a Groovy scripts
If you configured `spec.groovyScripts.secret.name`, then this secret is available to use from map Groovy scripts.
The secrets are loaded to `secrets` map.
Create a [secret](https://kubernetes.io/docs/concepts/configuration/secret/) with for example the name `jenkins-conf-secrets`.
```yaml
kind: Secret
apiVersion: v1
type: Opaque
metadata:
name: jenkins-conf-secrets
namespace: default
data:
SYSTEM_MESSAGE: SGVsbG8gd29ybGQ=
```
Then modify the **Jenkins** pod manifest by changing `spec.groovyScripts.secret.name` to `jenkins-conf-secrets`.
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
configurationAsCode:
configurations:
- name: jenkins-operator-user-configuration
secret:
name: jenkins-conf-secrets
groovyScripts:
configurations:
- name: jenkins-operator-user-configuration
secret:
name: jenkins-conf-secrets
```
Now you can test that the secret is mounted by applying this `ConfigMap` for Groovy script:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-system-message.groovy: |
import jenkins.*
import jenkins.model.*
import hudson.*
import hudson.model.*
Jenkins jenkins = Jenkins.getInstance()
jenkins.setSystemMessage(secrets["SYSTEM_MESSAGE"])
jenkins.save()
```
Or by applying this configuration as code:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-operator-user-configuration
data:
1-system-message.yaml: |
jenkins:
systemMessage: ${SYSTEM_MESSAGE}
```
After this, you should see the `Hello world` system message from the **Jenkins** homepage.

View File

@ -0,0 +1,114 @@
---
title: "Deploying Jenkins"
linkTitle: "Deploying Jenkins"
weight: 2
date: 2021-12-08
description: >
Deploy production ready Jenkins manifest
---
{{% pageinfo %}}
This document describes the procedure for deploying Jenkins.
{{% /pageinfo %}}
## Prerequisites
The Operator needs to have been deployed beforehand. The procedure for deploying Jenkins described here doesn't apply to
installation of Operator via Helm chart unless `jenkins.enabled` was set to false.
Thats because by default, installation via Helm chart also covers deploying Jenkins.
## Deploying Jenkins instance
Once Jenkins Operator is up and running let's deploy actual Jenkins instance.
Create manifest e.g. **`jenkins_instance.yaml`** with following data and save it on drive.
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
namespace: default
spec:
configurationAsCode:
configurations: []
secret:
name: ""
groovyScripts:
configurations: []
secret:
name: ""
jenkinsAPISettings:
authorizationStrategy: createUser
master:
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.319.1-lts-alpine
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 100
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
failureThreshold: 10
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 80
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 1500m
memory: 3Gi
requests:
cpu: "1"
memory: 500Mi
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
Deploy a Jenkins to Kubernetes:
```bash
kubectl create -f jenkins_instance.yaml
```
Watch the Jenkins instance being created:
```bash
kubectl get pods -w
```
Get the Jenkins credentials:
```bash
kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.user}' | base64 -d
kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.password}' | base64 -d
```
Connect to the Jenkins instance (minikube):
```bash
minikube service jenkins-operator-http-<cr_name> --url
```
Connect to the Jenkins instance (actual Kubernetes cluster):
```bash
kubectl port-forward jenkins-<cr_name> 8080:8080
```
Then open browser with address `http://localhost:8080`.
![jenkins](/kubernetes-operator/img/jenkins.png)

View File

@ -0,0 +1,988 @@
---
title: "Installing the Operator"
linkTitle: "Installing the Operator"
weight: 1
date: 2023-01-08
description: >
How to install Jenkins Operator
---
{{% pageinfo %}}
This document describes installation procedure for **Jenkins Operator**.
All container images can be found at [virtuslab/jenkins-operator](https://hub.docker.com/r/virtuslab/jenkins-operator) Docker Hub repository.
{{% /pageinfo %}}
## Requirements
To run **Jenkins Operator**, you will need:
- access to a Kubernetes cluster version `1.17+`
- `kubectl` version `1.17+`
Listed below are the two ways to deploy Jenkins Operator.
## Deploy Jenkins Operator using YAML's
First, install Jenkins Custom Resource Definition:
```bash
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/config/crd/bases/jenkins.io_jenkins.yaml
```
Then, install the Operator and other required resources:
```bash
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/all-in-one-v1alpha2.yaml
```
Watch **Jenkins Operator** instance being created:
```bash
kubectl get pods -w
```
Now **Jenkins Operator** should be up and running in the `default` namespace.
For deploying Jenkins, refer to [Deploy Jenkins section](/kubernetes-operator/docs/getting-started/latest/deploying-jenkins/).
## Deploy Jenkins Operator using Helm Chart
Alternatively, you can also use Helm to install the Operator (and optionally, by default, Jenkins). It requires the Helm 3+ for deployment.
Create a namespace for the operator:
```bash
$ kubectl create namespace <your-namespace>
```
To install, you need only to type these commands:
```bash
$ helm repo add jenkins https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/chart
$ helm install <name> jenkins/jenkins-operator -n <your-namespace>
```
To add custom labels and annotations, you can use `values.yaml` file or pass them into `helm install` command, e.g.:
```bash
$ helm install <name> jenkins/jenkins-operator -n <your-namespace> --set jenkins.labels.LabelKey=LabelValue,jenkins.annotations.AnnotationKey=AnnotationValue
```
You can further customize Jenkins using `values.yaml`:
<h3 id="JenkinsConfiguration">Jenkins instance configuration
</h3>
<table aria-colspan="4">
<thead aria-colspan="4">
<tr>
<th></th>
<th>Field</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody aria-colspan="4">
<tr></tr>
<tr>
<td colspan="1">
<code>jenkins</code>
</td>
<td colspan="3">
<p>operator is section for configuring operator deployment</p>
<table>
<tr>
<td>
<code>enabled</code>
</td>
<td>
true
</td>
<td>
Enabled can enable or disable the Jenkins instance.
Set to false if you have configured CR already and/or you want to deploy an operator only.
</td>
</tr>
<tr>
<td>
<code>apiVersion</code>
</td>
<td>jenkins.io/v1alpha2</td>
<td>
Version of the CR manifest. The recommended and default value is <code>jenkins.io/v1alpha2</code>.
<a href="#github.io/kubernetes-operator/docs/getting-started/v0.1.x/migration-guide-v1alpha1-to-v1alpha2/">More info</a>
</td>
</tr>
<tr>
<td>
<code>name</code>
</td>
<td>
jenkins
</td>
<td>
Name of resource. The pod name will be <code>jenkins-&lt;name&gt;</code> (name will be set as suffix).
</td>
</tr>
<tr>
<td>
<code>namespace</code>
</td>
<td>
default
</td>
<td>
Namespace the resources will be deployed to. It's not recommended to use default namespace.
Create new namespace for jenkins (e.g. <code>kubectl create -n jenkins</code>)
</td>
</tr>
<tr>
<td>
<code>labels</code>
</td>
<td>
{}
</td>
<td>
Labels are injected into metadata labels field.
</td>
</tr>
<tr>
<td>
<code>annotations</code>
</td>
<td>
{}
</td>
<td>
Annotations are injected into metadata annotations field.
</td>
</tr>
<tr>
<td>
<code>image</code>
</td>
<td>
jenkins/jenkins:lts
</td>
<td>
Image is the name (and tag) of the Jenkins instance.
It's recommended to use LTS (tag: "lts") version.
</td>
</tr>
<tr>
<td>
<code>env</code>
</td>
<td>
[]
</td>
<td>
Env contains jenkins container environment variables.
</td>
</tr>
<tr>
<td>
<code>imagePullPolicy</code>
</td>
<td>
Always
</td>
<td>
Defines policy for pulling images
</td>
</tr>
<tr>
<td>
<code>priorityClassName</code>
</td>
<td>
""
</td>
<td>
PriorityClassName indicates the importance of a Pod relative to other Pods.
<a href="https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/">More info</a>
</td>
</tr>
<tr>
<td>
<code>disableCSRFProtection</code>
</td>
<td>
false
</td>
<td>
disableCSRFProtection can enable or disable operator built-in CSRF protection.
Set it to true if you are using OpenShift Jenkins Plugin.
<a href="https://github.com/jenkinsci/kubernetes-operator/pull/193">More info</a>
</td>
</tr>
<tr>
<td>
<code>imagePullSecrets</code>
</td>
<td>
[]
</td>
<td>
Used if you want to pull images from private repository
<a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration/#pulling-docker-images-from-private-repositories">More info</a>
</td>
</tr>
<tr>
<td>
<code>notifications</code>
</td>
<td>
[]
</td>
<td>
Notifications is feature that notify user about Jenkins reconciliation status
<a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/notifications/">More info</a>
</td>
</tr>
<tr>
<td>
<code>basePlugins</code>
</td>
<td>
<pre>
- name: kubernetes
version: "1.25.2"
- name: workflow-job
version: "2.39"
- name: workflow-aggregator
version: "2.6"
- name: git
version: "4.2.2"
- name: job-dsl
version: "1.77"
- name: configuration-as-code
version: "1.38"
- name: kubernetes-credentials
-provider
version: "0.13"
</pre>
</td>
<td>
Plugins installed and required by the operator
shouldn't contain plugins defined by user
You can change their versions here
<a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/customization/#install-plugins">More info</a>
</td>
</tr>
<tr>
<td>
<code>plugins</code>
</td>
<td>
[]
</td>
<td>
Plugins required by the user. You can define plugins here.
<a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/customization/#install-plugins">More info</a>
Example:
<pre>
plugins:
- name: simple-theme-plugin
version: 0.5.1
</pre>
</td>
</tr>
<tr>
<td>
<code>seedJobs</code>
</td>
<td>
[]
</td>
<td>
Placeholder for jenkins seed jobs
For seed job creation tutorial, check:<br /> <a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-seed-jobs-and-pipelines/#prepare-job-definitions-and-pipelines">Prepare seed jobs</a>
<br /><a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-seed-jobs-and-pipelines/#configure-seed-jobs">Configure seed jobs</a>
<br />Example:
<code>
<pre>
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl:
- https://github.com/jenkinsci/kubernetes-operator.git
</pre>
</code>
</td>
</tr>
<tr>
<td>
<code>resources</code>
</td>
<td>
<pre>
limits:
cpu: 1500m
memory: 3Gi
requests:
cpu: 1
memory: 500M
</pre>
</td>
<td>
Resource limit/request for Jenkins
<a href="https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container">More info</a>
</td>
</tr>
<tr>
<td>
<code>volumes</code>
</td>
<td>
<pre>
- name: backup
persistentVolumeClaim:
claimName: jenkins-backup
</pre>
</td>
<td>
Volumes used by Jenkins
By default, we are only using PVC volume for storing backups.
</td>
</tr>
<tr>
<td>
<code>volumeMounts</code>
</td>
<td>
[]
</td>
<td>
volumeMounts are mounts for Jenkins pod.
</td>
</tr>
<tr>
<td>
<code>securityContext</code>
</td>
<td>
runAsUser: 1000
fsGroup: 1000
</td>
<td>
SecurityContext for pod.
</td>
</tr>
<tr>
<td><code>service</code></td>
<td>not implemented</td>
<td>Http Jenkins service. See https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/schema/#github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Service for details.</td>
</tr>
<tr>
<td><code>slaveService</code></td>
<td>not implemented</td>
<td>Slave Jenkins service. See https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/schema/#github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2.Service for details.</td>
</tr>
<tr>
<td>
<code>livenessProbe</code>
</td>
<td>
<pre>
livenessProbe:
failureThreshold: 12
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 80
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
</pre>
</td>
<td>
livenessProbe for Pod
</td>
</tr>
<tr>
<td>
<code>readinessProbe</code>
</td>
<td>
<pre>
readinessProbe:
failureThreshold: 3
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
</pre>
</td>
<td>
readinessProbe for Pod
</td>
</tr>
<tr>
<td>
<code>
backup
</code>
<p>
<em>
<a href="#Backup">
Backup
</a>
</em>
</p>
</td>
<td>
</td>
<td>
Backup is section for configuring operator's backup feature
By default backup feature is enabled and pre-configured
This section simplifies the configuration described here: <a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuring-backup-and-restore/">Configuring backup and restore</a>
For customization tips see <a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/custom-backup-and-restore">Custom backup and restore</a>
</td>
</tr>
<tr>
<td>
<code>configuration</code>
<p>
<em>
<a href="#Configuration">
Configuration
</a>
</em>
</p>
</td>
<td></td>
<td>
Section where we can configure Jenkins instance.
See <a href="https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/customizing-jenkins/">Customizing Jenkins</a> for details
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
### Configuring operator deployment
<table aria-colspan="4">
<thead aria-colspan="4">
<tr>
<th></th>
<th>Field</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody aria-colspan="4">
<tr></tr>
<tr>
<td colspan="1">
<code>operator</code>
</td>
<td colspan="3">
<p>operator is section for configuring operator deployment</p>
<table>
<tr>
<td>
<code>replicaCount</code></br>
</td>
<td>
1
</td>
<td>
Number of Replicas.
</td>
</tr>
<tr>
<td>
<code>image</code>
</td>
<td>
virtuslab/jenkins-operator:v0.4.0
</td>
<td>
Name (and tag) of the Jenkins Operator image.
</td>
</tr>
<tr>
<td>
<code>imagePullPolicy</code>
</td>
<td>
IfNotPresent
</td>
<td>
Defines policy for pulling images.
</td>
</tr>
<tr>
<td>
<code>imagePullSecrets</code>
</td>
<td>
[]
</td>
<td>
Used if you want to pull images from private repository.
</td>
</tr>
<tr>
<td>
<code>nameOverride</code>
</td>
<td>
""
</td>
<td>
nameOverride overrides the app name.
</td>
</tr>
<tr>
<td>
<code>fullnameOverride</code>
</td>
<td>
""
</td>
<td>
fullnameOverride overrides the deployment name
</td>
</tr>
<tr>
<td>
<code>resources</code>
</td>
<td>
{}
</td>
<td>
</td>
</tr>
<tr>
<td>
<code>nodeSelector</code>
</td>
<td>
{}
</td>
<td>
</td>
</tr>
<tr>
<td>
<code>tolerations</code>
</td>
<td>
{}
</td>
<td>
</td>
</tr>
<tr>
<td>
<code>affinity</code>
</td>
<td>
{}
</td>
<td>
</td>
</tr>
</table>
</td>
</tr>
</tbody>
</table>
<h3 id="Backup">Backup
</h3>
<p>
(<em>Appears on:</em>
<a href="#JenkinsConfiguration">JenkinsConfiguration</a>)
</p>
<p>
Backup defines configuration of Jenkins backup.
</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>enabled</code>
</td>
<td>
true
</td>
<td>
Enabled is enable/disable switch for backup feature.
</td>
</tr>
<tr>
<td>
<code>image</code>
</td>
<td>
virtuslab/jenkins-operator-backup-pvc:v0.1.1
</td>
<td>
Image used by backup feature.
</td>
</tr>
<tr>
<td>
<code>containerName</code>
</td>
<td>
backup
</td>
<td>
Backup container name.
</td>
</tr>
<tr>
<td>
<code>interval</code>
</td>
<td>
30
</td>
<td>
Defines how often make backup in seconds.
</td>
</tr>
<tr>
<td>
<code>makeBackupBeforePodDeletion</code>
</td>
<td>
true
</td>
<td>
When enabled will make backup before pod deletion.
</td>
</tr>
<tr>
<td>
<code>backupCommand</code>
</td>
<td>
/home/user/bin/backup.sh
</td>
<td>
Backup container command.
</td>
</tr>
<tr>
<td>
<code>restoreCommand</code>
</td>
<td>
/home/user/bin/restore.sh
</td>
<td>
Backup restore command.
</td>
</tr>
<tr>
<td>
<code>pvc</code>
</td>
<td colspan="2">
<p>Persistent Volume Claim Kubernetes resource</p>
<br/>
<table colspan="2" style="width:100%">
<tbody>
<tr>
<td>
<code>enabled</code>
</td>
<td>
true
</td>
<td>
Enable/disable switch for PVC
</td>
</tr>
<tr>
<td>
<code>enabled</code>
</td>
<td>
true
</td>
<td>
Enable/disable switch for PVC
</td>
</tr>
<tr>
<td>
<code>size</code>
</td>
<td>
5Gi
</td>
<td>
Size of PVC
</td>
</tr>
<tr>
<td>
<code>className</code>
</td>
<td>
""
</td>
<td>
StorageClassName for PVC
<a href="https://kubernetes.io/docs/concepts/storage/persistent-volumes/#class-1">More info</a>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>
<code>env</code>
</td>
<td>
<pre>
- name: BACKUP_DIR
value: /backup
- name: JENKINS_HOME
value: /jenkins-home
- name: BACKUP_COUNT
value: "3"
</pre>
</td>
<td>
Contains container environment variables.
PVC backup provider handles these variables:<br />
BACKUP_DIR - path for storing backup files (default: "/backup")<br />
JENKINS_HOME - path to jenkins home (default: "/jenkins-home")<br />
BACKUP_COUNT - define how much recent backups will be kept<br />
</td>
</td>
</tr>
<tr>
<td>
<code>volumeMounts</code>
</td>
<td>
<pre>
- name: jenkins-home
mountPath: /jenkins-home
- mountPath: /backup
name: backup
</pre>
</td>
<td>
Holds the mount points for volumes.
</td>
</tr>
</tbody>
</table>
<h4 id="Configuration">Configuration
</h3>
<p>
(<em>Appears on:</em>
<a href="#JenkinsConfiguration">Jenkins instance configuration</a>)
</p>
<table>
<thead>
<tr>
<th>Field</th>
<th>Default value</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<code>configurationAsCode</code>
</td>
<td>
{}
</td>
<td>
ConfigurationAsCode defines configuration of Jenkins customization via Configuration as Code Jenkins plugin.
Example:<br />
<pre>
- configMapName: jenkins-casc
content: {}
</pre>
</td>
</tr>
<tr>
<td>
<code>groovyScripts</code>
</td>
<td>
{}
</td>
<td>
GroovyScripts defines configuration of Jenkins customization via groovy scripts.
Example:<br />
<pre>
- configMapName: jenkins-gs
content: {}
</pre>
</td>
</tr>
<tr>
<td>
<code>secretRefName</code>
</td>
<td>
""
</td>
<td>
secretRefName of existing secret (previously created).
</td>
</tr>
<tr>
<td>
<code>secretData</code>
</td>
<td>
{}
</td>
<td>
If secretRefName is empty, secretData creates new secret and fills with data provided in secretData.
</td>
</tr>
</tbody>
</table>
## Note on Operator's nightly built images
If you wish to use the newest, not yet released version of the Operator, you can use one of nightly built snapshot images, however the maintainers of this project cannot guarantee their stability.
You can find nightly built images by heading to [virtuslab/jenkins-operator](https://hub.docker.com/r/virtuslab/jenkins-operator) Docker Hub repository and looking for images with tag in the form of `{git-hash}`, {git-hash} being the hash of master branch commit that you want to use snapshot of.
## Note on restricted Jenkins controller pod volumeMounts
Current design of the Operator puts an emphasis on creating a full GitOps flow of work for Jenkins users.
One of the key points of this design is maintaining an immutable state of Jenkins.
One of the prerequisites of this is an ephemeral Jenkins home directory. To achieve that, Operator mounts emptyDir Volume
(jenkins-home) as Jenkins home directory.
It is not possible to overwrite volumeMount and specify any other Volume for Jenkins home directory,
as attempting to do so will result in Operator error.
jenkins-home is not the only Jenkins controller pod volumeMount that is non-configurable and managed by Operator,
below is the full list of those volumeMounts:
* jenkins-home
* scripts
* init-configuration
* operator-credentials
## Validating Webhook
Validating webhook can be used in order to increase the Operator's capabilities to monitor security issues. It will look for security vulnerabilities in the base and requested plugins. It can be easily installed via Helm charts by setting webhook.enabled in values.yaml.
**Note**: The webhook takes some time to get up and running. It's recommended to first deploy the Operator and later Jenkins Custom Resource by using toggles in `values.yaml`.
For the installation with yaml manifests (without using Helm chart), first, install cert-manager:
```bash
kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.yaml
```
It takes some time to get cert-manager up and running.
Then, install the webhook and other required resources:
```bash
kubectl apply -f https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/all-in-one-webhook.yaml
```
Now, download the manifests for the operator and other resources from [here](https://raw.githubusercontent.com/jenkinsci/kubernetes-operator/master/deploy/all-in-one-v1alpha2.yaml) and provide these additional fields in the Operator manifest:
<pre>
<code>
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-operator
labels:
control-plane: controller-manager
spec:
selector:
matchLabels:
control-plane: controller-manager
replicas: 1
template:
metadata:
labels:
control-plane: controller-manager
spec:
serviceAccountName: jenkins-operator
securityContext:
runAsUser: 65532
containers:
- command:
- /manager
args:
- --leader-elect
<b>- --validate-security-warnings</b>
image: virtuslab/jenkins-operator:v0.7.0
name: jenkins-operator
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 200m
memory: 100Mi
requests:
cpu: 100m
memory: 20Mi
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
<b>volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: webhook-certs
readOnly: true
volumes:
- name: webhook-certs
secret:
defaultMode: 420
secretName: jenkins-webhook-certificate
terminationGracePeriodSeconds: 10</b>
</code>
</pre>
To enable security validation in the Jenkins Custom Resource, set
>jenkins.ValidateSecurityWarnings=true

View File

@ -0,0 +1,126 @@
---
title: "LDAP"
linkTitle: "LDAP"
weight: 9
date: 2021-12-08
description: >
Additional configuration for LDAP
---
Configuring LDAP is not supported out of the box, but can be achieved through
plugins and some well tuned configurations.
The plugin we will use is: <https://plugins.jenkins.io/ldap/>
> Note: This is an example of how LDAP authentication can be achieved. The LDAP
> plugin is from a third-party, and there may be other alternatives that suits
> your use case better. Use this guide with a grain of salt.
## Requirements
- LDAP server accessible from the Kubernetes cluster where your Jenkins
instance will live.
- Credentials to a manager account in your AD. Jenkins Operator will use
this account to authenticate with Jenkins for health checks, seed jobs, etc.
## Steps
In your Jenkins configuration, add the following plugin:
```yaml
plugins:
# Check https://plugins.jenkins.io/ldap/ to find the latest version.
- name: ldap
version: "2.7"
```
Easiest step is to then start up Jenkins then navigate to your instance's
"Configure Global Security" page and configure it accordingly.
`http://jenkins.example.com/configureSecurity/`
Once it's set up and tested, you can navigate to your JCasC page and export
the LDAP settings.
`https://jenkins.example.com/configuration-as-code/`
Feed the relevant new settings into your Kubernetes ConfigMap for your JCasC
settings.
Here's a snippet of the LDAP-related configurations:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jenkins-casc
data:
ldap.yaml: |
jenkins:
securityRealm:
ldap:
configurations:
- displayNameAttributeName: "name"
groupSearchBase: "OU=Groups,OU=MyCompany"
groupSearchFilter: "(& (cn={0}) (objectclass=group) )"
inhibitInferRootDN: false
managerDN: "CN=Jenkins Admin,OU=UsersSystem,OU=UsersOther,OU=MyCompany,DC=mycompany,DC=local"
managerPasswordSecret: "${LDAP_MANAGER_PASSWORD}"
rootDN: "DC=mycompany,DC=local"
server: "MyCompany.local"
userSearch: "SamAccountName={0}"
userSearchBase: "OU=MyCompany"
disableMailAddressResolver: false
disableRolePrefixing: true
groupIdStrategy: "caseInsensitive"
userIdStrategy: "caseInsensitive"
```
>Note the use of `${LDAP_MANAGER_PASSWORD}` above. You can reference
>Kubernetes secrets in your JCasC ConfigMaps by adding the following to your
Jenkins object:
```yaml
kind: Jenkins
spec:
configurationAsCode:
configurations:
- name: jenkins-casc
secret:
# This here
name: jenkins-casc-secrets
```
```yaml
apiVersion: v1
kind: Secret
metadata:
name: jenkins-cred-conf-secrets
stringData:
LDAP_MANAGER_PASSWORD: <password-for-manager-created-in-ldap>
```
Schema reference: [v1alpha2.ConfigurationAsCode](./schema/#github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2.ConfigurationAsCode)
Finally you must configure the Jenkins operator to use the manager's
credentials from the AD.
This is because this procedure will disable Jenkins' own user database, and the
Jenkins operator still needs to be able to talk to Jenkins in an authorized
manner.
Create the following Kubernetes secret:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: jenkins-operator-credentials-<jenkins-cr-name>
namespace: <jenkins-cr-namespace>
stringData:
user: <username-for-manager-created-in-ldap>
password: <password-for-manager-created-in-ldap>
```
> Note: Values in stringData do not need to be base64 encoded. They are
> encoded by Kubernetes when the manifest is applied.

View File

@ -0,0 +1,10 @@
---
title: "OpenShift"
linkTitle: "OpenShift"
weight: 10
date: 2021-12-08
description: >
Additional configuration for OpenShift
---
## Release 0.7.0 is not compatible with OpenShift.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,583 @@
---
title: "Separate namespaces for Jenkins and Operator"
linkTitle: "Separate namespaces for Jenkins and Operator"
weight: 6
date: 2021-12-08
description: >
How to install Jenkins and Jenkins Operator in separate namespaces
---
## Create namespaces
You need to create two namespaces, for example we'll call them **jenkins** for Jenkins and **jenkins-operator** for Jenkins Operator.
```bash
$ kubectl create ns jenkins-operator
$ kubectl create ns jenkins
```
## Create necessary resources in Jenkins Operator namespace
Next, you need to install resources necessary for the Operator to work in the `jenkins-operator` namespace. To do that,
copy the manifest you see below to `jenkins-operator-rbac.yaml`file.
```yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-operator
---
# permissions to do leader election.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leader-election-role
rules:
- apiGroups:
- ""
- coordination.k8s.io
resources:
- configmaps
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leader-election-rolebinding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: leader-election-role
subjects:
- kind: ServiceAccount
name: jenkins-operator
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jenkins-operator
rules:
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- '*'
- apiGroups:
- apps
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
- builds
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- services
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- jenkins.io
resources:
- jenkins
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- jenkins.io
resources:
- jenkins/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- route.openshift.io
resources:
- routes
verbs:
- create
- get
- list
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins-operator
subjects:
- kind: ServiceAccount
name: jenkins-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins-operator
```
Now install the required resources in `jenkins-operator` namespace with:
```bash
kubectl apply -n jenkins-operator -f jenkins-operator-rbac.yaml
```
There's only one thing left to install in `jenkins-operator` namespace, and that is the Operator itself. The manifest
below contains the Operator as defined in all-in-one manifest found in [Installing the Operator](/kubernetes-operator/docs/getting-started/latest/installing-the-operator/)
page, the only difference is that the one here sets `WATCH_NAMESPACE` to the `jenkins` namespace we created.
Copy its content to `jenkins-operator.yaml` file.
```bash
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins-operator
labels:
control-plane: controller-manager
spec:
selector:
matchLabels:
control-plane: controller-manager
replicas: 1
template:
metadata:
labels:
control-plane: controller-manager
spec:
serviceAccountName: jenkins-operator
securityContext:
runAsUser: 65532
containers:
- command:
- /manager
args:
- --leader-elect
image: virtuslab/jenkins-operator:v0.7.0
name: jenkins-operator
imagePullPolicy: IfNotPresent
securityContext:
allowPrivilegeEscalation: false
livenessProbe:
httpGet:
path: /healthz
port: 8081
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /readyz
port: 8081
initialDelaySeconds: 5
periodSeconds: 10
resources:
limits:
cpu: 100m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
env:
- name: WATCH_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
terminationGracePeriodSeconds: 10
```
Install the Operator in `jenkins-operator` namespace with:
```bash
kubectl apply -n jenkins-operator -f jenkins-operator.yaml
```
You have installed the Operator in `jenkins-operator` namespace, watching for Jenkins in `jenkins` namespace. Now
there are two things left to do: creating necessary Role and RoleBinding for the Operator in `jenkins` namespace, and
deploying actual Jenkins instance there.
## Create necessary resources in Jenkins namespace
Below you can find manifest with RBAC that needs to be created in `jenkins` namespace. Copy its content to `jenkins-ns-rbac.yaml` file.
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: jenkins-operator
rules:
- apiGroups:
- apps
resources:
- daemonsets
- deployments
- replicasets
- statefulsets
verbs:
- '*'
- apiGroups:
- apps
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- build.openshift.io
resources:
- buildconfigs
- builds
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- configmaps
- secrets
- services
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- ""
resources:
- events
verbs:
- create
- get
- list
- patch
- watch
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- '*'
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- image.openshift.io
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- jenkins.io
resources:
- jenkins
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- jenkins.io
resources:
- jenkins/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- jenkins/status
verbs:
- get
- patch
- update
- apiGroups:
- rbac.authorization.k8s.io
resources:
- rolebindings
- roles
verbs:
- create
- get
- list
- update
- watch
- apiGroups:
- route.openshift.io
resources:
- routes
verbs:
- create
- get
- list
- update
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jenkins-operator
subjects:
- kind: ServiceAccount
name: jenkins-operator
namespace: jenkins-operator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: jenkins-operator
```
Now apply it with:
```bash
kubectl apply -n jenkins -f jenkins-ns-rbac.yaml
```
The last thing to do is to deploy Jenkins. Below you can find an example Jenkins resource manifest.
It's the same as one used in [Deploying Jenkins](/kubernetes-operator/docs/getting-started/latest/deploying-jenkins/).
Copy it to `jenkins-instance.yaml`
```yaml
apiVersion: jenkins.io/v1alpha2
kind: Jenkins
metadata:
name: example
spec:
configurationAsCode:
configurations: []
secret:
name: ""
groovyScripts:
configurations: []
secret:
name: ""
jenkinsAPISettings:
authorizationStrategy: createUser
master:
disableCSRFProtection: false
containers:
- name: jenkins-master
image: jenkins/jenkins:2.319.1-lts-alpine
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 100
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 5
readinessProbe:
failureThreshold: 10
httpGet:
path: /login
port: http
scheme: HTTP
initialDelaySeconds: 80
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
resources:
limits:
cpu: 1500m
memory: 3Gi
requests:
cpu: "1"
memory: 500Mi
seedJobs:
- id: jenkins-operator
targets: "cicd/jobs/*.jenkins"
description: "Jenkins Operator repository"
repositoryBranch: master
repositoryUrl: https://github.com/jenkinsci/kubernetes-operator.git
```
Now you can deploy it with:
```bash
kubectl apply -n jenkins -f jenkins-instance.yaml
```
With this, you have just set up Jenkins Operator and Jenkins in separate namespaces. Now the Operator will run in
its own namespace (`jenkins-operator`), watch for CRs in `jenkins` namespace, and deploy Jenkins there.

2368
website/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@
},
"homepage": "https://github.com/bep/tech-doc-hugo#readme",
"devDependencies": {
"autoprefixer": "^9.8.8",
"postcss-cli": "^5.0.1"
"autoprefixer": "^10.4.17",
"postcss-cli": "^11.0.0"
}
}