Add 0.3.x docs, add instruction how to run e2e tests on crc
This commit is contained in:
parent
eea28a42a3
commit
ab24e2c8fd
|
|
@ -1,57 +0,0 @@
|
|||
---
|
||||
title: "Tools"
|
||||
linkTitle: "Tools"
|
||||
weight: 30
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
Required tools for building and running Jenkins Operator
|
||||
---
|
||||
|
||||
{{% pageinfo %}}
|
||||
This document explains how to install the Go tools used by the development process.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
## Configure environment variables
|
||||
|
||||
```bash
|
||||
export GOPATH=/home/go # example value
|
||||
export GOROOT=/usr/lib/go-1.12 # example value
|
||||
export PATH=$GOPATH/bin:$PATH
|
||||
```
|
||||
|
||||
## goimports
|
||||
|
||||
```
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
cd $GOPATH/src/golang.org/x/tools/cmd/goimports
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## golint
|
||||
|
||||
```
|
||||
go get -u golang.org/x/lint/golint
|
||||
cd $GOPATH/src/golang.org/x/lint/golint
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## checkmake
|
||||
```
|
||||
go get github.com/mrtazz/checkmake
|
||||
cd $GOPATH/src/github.com/mrtazz/checkmake
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## staticcheck
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/github.com/dominikh/
|
||||
cd $GOPATH/src/github.com/dominikh/
|
||||
git clone https://github.com/dominikh/go-tools.git
|
||||
cd $GOPATH/src/github.com/dominikh/go-tools/staticcheck
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
---
|
||||
title: "Future (v0.3.x)"
|
||||
linkTitle: "Future (v0.3.x)"
|
||||
weight: 10
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
How to work with jenkins-operator latest version
|
||||
---
|
||||
|
||||
{{% pageinfo %}}
|
||||
This document describes a getting started guide for **Jenkins Operator** `v0.3.x` and an additional configuration.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
## First Steps
|
||||
|
||||
Prepare your Kubernetes cluster and set up your `kubectl` access.
|
||||
|
||||
Once you have running Kubernetes cluster you can focus on installing **Jenkins Operator** according to the [Installation](/docs/installation/) guide.
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
title: "AKS"
|
||||
linkTitle: "AKS"
|
||||
weight: 10
|
||||
date: 2019-08-05
|
||||
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.
|
||||
|
|
@ -0,0 +1,325 @@
|
|||
---
|
||||
title: "Configuration"
|
||||
linkTitle: "Configuration"
|
||||
weight: 2
|
||||
date: 2019-08-05
|
||||
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
|
||||
│ └── build.jenkins
|
||||
└── pipelines
|
||||
└── build.jenkins
|
||||
```
|
||||
|
||||
**`cicd/jobs/build.jenkins`** is a job definition:
|
||||
|
||||
```
|
||||
#!/usr/bin/env groovy
|
||||
|
||||
pipelineJob('build-jenkins-operator') {
|
||||
displayName('Build jenkins-operator')
|
||||
|
||||
definition {
|
||||
cpsScm {
|
||||
scm {
|
||||
git {
|
||||
remote {
|
||||
url('https://github.com/jenkinsci/kubernetes-operator.git')
|
||||
credentials('jenkins-operator')
|
||||
}
|
||||
branches('*/master')
|
||||
}
|
||||
}
|
||||
scriptPath('cicd/pipelines/build.jenkins')
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**`cicd/pipelines/build.jenkins`** is an actual Jenkins pipeline:
|
||||
|
||||
```
|
||||
#!/usr/bin/env groovy
|
||||
|
||||
def label = "build-jenkins-operator-${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: 'jnlp', image: 'jenkins/jnlp-slave:alpine'),
|
||||
containerTemplate(name: 'go', image: 'golang:1-alpine', command: 'cat', ttyEnabled: true),
|
||||
],
|
||||
envVars: [
|
||||
envVar(key: 'GOPATH', value: workspace),
|
||||
],
|
||||
) {
|
||||
|
||||
node(label) {
|
||||
dir(workdir) {
|
||||
stage('Init') {
|
||||
timeout(time: 3, unit: 'MINUTES') {
|
||||
checkout scm
|
||||
}
|
||||
container('go') {
|
||||
sh 'apk --no-cache --update add make git gcc libc-dev'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Dep') {
|
||||
container('go') {
|
||||
sh 'make dep'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Test') {
|
||||
container('go') {
|
||||
sh 'make test'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
container('go') {
|
||||
sh 'make build'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
||||

|
||||
|
||||
You can verify if your pipelines were successfully configured in the Jenkins Seed Job console output.
|
||||
|
||||

|
||||
|
||||
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
|
||||
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
|
||||
```
|
||||
|
||||
## 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/
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
---
|
||||
title: "Configure backup and restore"
|
||||
linkTitle: "Configure backup and restore"
|
||||
weight: 10
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
Prevent loss of job history
|
||||
---
|
||||
|
||||
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: <cr_name>
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
master:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
fsGroup: 1000
|
||||
containers:
|
||||
- name: jenkins-master
|
||||
image: jenkins/jenkins:lts
|
||||
- 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.0.7 # look at backup/pvc directory
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- mountPath: /jenkins-home # Jenkins home volume
|
||||
name: jenkins-home
|
||||
- mountPath: /backup # backup volume
|
||||
name: backup
|
||||
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
|
||||
```
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
---
|
||||
title: "Custom Backup and Restore Providers"
|
||||
linkTitle: "Custom Backup and Restore Providers"
|
||||
weight: 10
|
||||
date: 2019-08-05
|
||||
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
|
||||
```
|
||||
|
|
@ -0,0 +1,186 @@
|
|||
---
|
||||
title: "Customization"
|
||||
linkTitle: "Customization"
|
||||
weight: 3
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
How to customize Jenkins
|
||||
---
|
||||
|
||||
Jenkins can be customized using groovy scripts or the [configuration as code plugin](https://github.com/jenkinsci/configuration-as-code-plugin).
|
||||
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`
|
||||
|
||||
For example create a **`ConfigMap`** with name `jenkins-operator-user-configuration`. Then, modify the **Jenkins** manifest to look like this:
|
||||
|
||||
```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.
|
||||
|
||||
### Using secrets from a Groovy script
|
||||
|
||||
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.
|
||||
|
||||
## Install Plugins
|
||||
|
||||
Edit Custom Resource under `spec.master.plugins`:
|
||||
|
||||
```
|
||||
apiVersion: jenkins.io/v1alpha2
|
||||
kind: Jenkins
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
master:
|
||||
plugins:
|
||||
- name: simple-theme-plugin
|
||||
version: 0.5.1
|
||||
```
|
||||
|
||||
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.18.3
|
||||
- name: workflow-job
|
||||
version: "2.34"
|
||||
- name: workflow-aggregator
|
||||
version: "2.6"
|
||||
- name: git
|
||||
version: 3.12.0
|
||||
- name: job-dsl
|
||||
version: "1.76"
|
||||
- name: configuration-as-code
|
||||
version: "1.29"
|
||||
- name: configuration-as-code-support
|
||||
version: "1.19"
|
||||
- name: kubernetes-credentials-provider
|
||||
version: 0.12.1
|
||||
```
|
||||
|
||||
You can change their versions.
|
||||
|
||||
The **Jenkins Operator** will then automatically install plugins after the Jenkins master pod restarts.
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
---
|
||||
title: "Deploy Jenkins"
|
||||
linkTitle: "Deploy Jenkins"
|
||||
weight: 1
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
Deploy production ready Jenkins Operator manifest
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
```bash
|
||||
apiVersion: jenkins.io/v1alpha2
|
||||
kind: Jenkins
|
||||
metadata:
|
||||
name: example
|
||||
spec:
|
||||
master:
|
||||
containers:
|
||||
- name: jenkins-master
|
||||
image: jenkins/jenkins:lts
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 12
|
||||
httpGet:
|
||||
path: /login
|
||||
port: http
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 80
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
httpGet:
|
||||
path: /login
|
||||
port: http
|
||||
scheme: HTTP
|
||||
initialDelaySeconds: 30
|
||||
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`.
|
||||

|
||||
|
|
@ -0,0 +1,224 @@
|
|||
---
|
||||
title: "Developer Guide"
|
||||
linkTitle: "Developer Guide"
|
||||
weight: 60
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
Jenkins Operator for developers
|
||||
---
|
||||
|
||||
{{% pageinfo %}}
|
||||
This document explains how to setup your development environment.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [operator_sdk][operator_sdk] version v0.8.1
|
||||
- [git][git_tool]
|
||||
- [go][go_tool] version v1.12+
|
||||
- [goimports, golint, checkmake and staticcheck][install_dev_tools]
|
||||
- [minikube][minikube] version v1.1.0+ (preferred Hypervisor - [virtualbox][virtualbox])
|
||||
- [docker][docker_tool] version 17.03+
|
||||
|
||||
## Clone repository and download dependencies
|
||||
|
||||
```bash
|
||||
mkdir -p $GOPATH/src/github.com/jenkinsci
|
||||
cd $GOPATH/src/github.com/jenkinsci/
|
||||
git clone git@github.com:jenkinsci/kubernetes-operator.git
|
||||
cd kubernetes-operator
|
||||
make go-dependencies
|
||||
```
|
||||
|
||||
## Build and run with a minikube
|
||||
|
||||
Build and run **Jenkins Operator** locally:
|
||||
|
||||
```bash
|
||||
make build minikube-run EXTRA_ARGS='--jenkins-api-hostname=$(eval minikube ip) --jenkins-api-use-nodeport=true'
|
||||
```
|
||||
|
||||
Once minikube and **Jenkins Operator** are up and running, apply Jenkins custom resource:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/crds/jenkins_v1alpha2_jenkins_cr.yaml
|
||||
kubectl get jenkins -o yaml
|
||||
kubectl get po
|
||||
```
|
||||
|
||||
## Build and run with a remote Kubernetes cluster
|
||||
|
||||
You can also run the controller locally and make it listen to a remote Kubernetes server.
|
||||
|
||||
```bash
|
||||
make run NAMESPACE=default KUBECTL_CONTEXT=remote-k8s EXTRA_ARGS='--kubeconfig ~/.kube/config'
|
||||
```
|
||||
|
||||
Once minikube and **Jenkins Operator** are up and running, apply Jenkins custom resource:
|
||||
|
||||
```bash
|
||||
kubectl --context remote-k8s --namespace default apply -f deploy/crds/jenkins_v1alpha2_jenkins_cr.yaml
|
||||
kubectl --context remote-k8s --namespace default get jenkins -o yaml
|
||||
kubectl --context remote-k8s --namespace default get po
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run unit tests:
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
||||
|
||||
### Running E2E tests on Linux
|
||||
|
||||
Run e2e tests with minikube:
|
||||
|
||||
```bash
|
||||
make minikube-start
|
||||
eval $(minikube docker-env)
|
||||
make build e2e config=config.minikube.env CR=podman
|
||||
```
|
||||
|
||||
`config.minikube.env` is the E2E test profile which provides all connection info to operator to run on minikube.
|
||||
|
||||
Run the specific e2e test:
|
||||
|
||||
```bash
|
||||
make build e2e E2E_TEST_SELECTOR='^TestConfiguration$' config=config.minikube.env CR=podman
|
||||
```
|
||||
|
||||
If you want to run E2E tests on CRC (Code Ready Containers by OpenShift), you should use `config.crc.env` profile instead of `config.minikube.env`.
|
||||
|
||||
### Running E2E tests on macOS
|
||||
|
||||
At first, you need to start minikube:
|
||||
```bash
|
||||
$ make minikube-start
|
||||
$ eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
Build a Docker image inside the provided Linux container by:
|
||||
```bash
|
||||
$ make indocker
|
||||
```
|
||||
|
||||
Build **Jenkins Operator** inside a container using:
|
||||
|
||||
|
||||
```bash
|
||||
$ make build
|
||||
```
|
||||
|
||||
Then exit the container and run:
|
||||
```
|
||||
make e2e CONFIG=config.minikube.env
|
||||
```
|
||||
|
||||
or with CRC:
|
||||
```
|
||||
make e2e CONFIG=config.crc.env
|
||||
```
|
||||
|
||||
### Use Docker image instead of podman (Code Ready Containers)
|
||||
|
||||
If you have trouble to build image with `podman`, you can set additional flag `USE_ORGANIZATION` to pull image from organization.
|
||||
|
||||
At first, edit you `config.base.env` and change `DOCKER_ORGANIZATION` to your account/organization name from [hub](https://hub.docker.com/).
|
||||
Next, you need to pull image to your repository:
|
||||
|
||||
```bash
|
||||
$ make cr-build cr-snapshot-push
|
||||
```
|
||||
|
||||
When image will be uploaded to repository, you can now write this command to run E2E tests:
|
||||
|
||||
```bash
|
||||
$ make e2e E2E_TEST_SELECTOR='^TestConfiguration$' config=config.crc.env USE_ORGANIZATION=true
|
||||
```
|
||||
|
||||
## Tips & Tricks
|
||||
|
||||
### Building docker image on minikube (for e2e tests)
|
||||
|
||||
To be able to work with the docker daemon on `minikube` machine run the following command before building an image:
|
||||
|
||||
```bash
|
||||
eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
### When `pkg/apis/jenkinsio/*/jenkins_types.go` has changed
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
make deepcopy-gen
|
||||
```
|
||||
|
||||
### Getting the Jenkins URL and basic credentials
|
||||
|
||||
```bash
|
||||
minikube service jenkins-operator-http-<cr_name> --url
|
||||
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
|
||||
```
|
||||
|
||||
# Tools
|
||||
|
||||
## Configure environment variables
|
||||
|
||||
```bash
|
||||
export GOPATH=/home/go # example value
|
||||
export GOROOT=/usr/lib/go-1.12 # example value
|
||||
export PATH=$GOPATH/bin:$PATH
|
||||
```
|
||||
|
||||
## goimports
|
||||
|
||||
```
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
cd $GOPATH/src/golang.org/x/tools/cmd/goimports
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## golint
|
||||
|
||||
```
|
||||
go get -u golang.org/x/lint/golint
|
||||
cd $GOPATH/src/golang.org/x/lint/golint
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## checkmake
|
||||
```
|
||||
go get github.com/mrtazz/checkmake
|
||||
cd $GOPATH/src/github.com/mrtazz/checkmake
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## staticcheck
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/github.com/dominikh/
|
||||
cd $GOPATH/src/github.com/dominikh/
|
||||
git clone https://github.com/dominikh/go-tools.git
|
||||
cd $GOPATH/src/github.com/dominikh/go-tools/staticcheck
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
|
||||
[dep_tool]:https://golang.github.io/dep/docs/installation.html
|
||||
[git_tool]:https://git-scm.com/downloads
|
||||
[go_tool]:https://golang.org/dl/
|
||||
[operator_sdk]:https://github.com/operator-framework/operator-sdk
|
||||
[fork_guide]:https://help.github.com/articles/fork-a-repo/
|
||||
[docker_tool]:https://docs.docker.com/install/
|
||||
[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
[minikube]:https://kubernetes.io/docs/tasks/tools/install-minikube/
|
||||
[virtualbox]:https://www.virtualbox.org/wiki/Downloads
|
||||
[jenkins-operator]:../README.md
|
||||
[install_dev_tools]:install_dev_tools.md
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
title: "Diagnostics"
|
||||
linkTitle: "Diagnostics"
|
||||
weight: 40
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
How to deal with Jenkins Operator problems
|
||||
---
|
||||
|
||||
|
||||
Turn on debug in **Jenkins Operator** deployment:
|
||||
|
||||
```bash
|
||||
sed -i 's|\(args:\).*|\1\ ["--debug"\]|' deploy/operator.yaml
|
||||
kubectl apply -f deploy/operator.yaml
|
||||
```
|
||||
|
||||
Watch Kubernetes events:
|
||||
|
||||
```bash
|
||||
kubectl get events --sort-by='{.lastTimestamp}'
|
||||
```
|
||||
|
||||
Verify Jenkins master logs:
|
||||
|
||||
```bash
|
||||
kubectl logs -f jenkins-<cr_name>
|
||||
```
|
||||
|
||||
Verify the `jenkins-operator` logs:
|
||||
|
||||
```bash
|
||||
kubectl logs deployment/jenkins-operator
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Delete the Jenkins master pod and wait for the new one to come up:
|
||||
|
||||
```bash
|
||||
kubectl delete pod jenkins-<cr_name>
|
||||
```
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -137,6 +137,53 @@ kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.us
|
|||
kubectl get secret jenkins-operator-credentials-<cr_name> -o 'jsonpath={.data.password}' | base64 -d
|
||||
```
|
||||
|
||||
# Tools
|
||||
|
||||
## Configure environment variables
|
||||
|
||||
```bash
|
||||
export GOPATH=/home/go # example value
|
||||
export GOROOT=/usr/lib/go-1.12 # example value
|
||||
export PATH=$GOPATH/bin:$PATH
|
||||
```
|
||||
|
||||
## goimports
|
||||
|
||||
```
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
cd $GOPATH/src/golang.org/x/tools/cmd/goimports
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## golint
|
||||
|
||||
```
|
||||
go get -u golang.org/x/lint/golint
|
||||
cd $GOPATH/src/golang.org/x/lint/golint
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## checkmake
|
||||
```
|
||||
go get github.com/mrtazz/checkmake
|
||||
cd $GOPATH/src/github.com/mrtazz/checkmake
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## staticcheck
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/github.com/dominikh/
|
||||
cd $GOPATH/src/github.com/dominikh/
|
||||
git clone https://github.com/dominikh/go-tools.git
|
||||
cd $GOPATH/src/github.com/dominikh/go-tools/staticcheck
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
|
||||
[dep_tool]:https://golang.github.io/dep/docs/installation.html
|
||||
[git_tool]:https://git-scm.com/downloads
|
||||
|
|
@ -0,0 +1,198 @@
|
|||
---
|
||||
title: "Developer Guide"
|
||||
linkTitle: "Developer Guide"
|
||||
weight: 60
|
||||
date: 2019-08-05
|
||||
description: >
|
||||
Jenkins Operator for developers
|
||||
---
|
||||
|
||||
{{% pageinfo %}}
|
||||
This document explains how to setup your development environment.
|
||||
{{% /pageinfo %}}
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- [operator_sdk][operator_sdk] version v0.8.1
|
||||
- [git][git_tool]
|
||||
- [go][go_tool] version v1.12+
|
||||
- [goimports, golint, checkmake and staticcheck][install_dev_tools]
|
||||
- [minikube][minikube] version v1.1.0+ (preferred Hypervisor - [virtualbox][virtualbox])
|
||||
- [docker][docker_tool] version 17.03+
|
||||
|
||||
## Clone repository and download dependencies
|
||||
|
||||
```bash
|
||||
mkdir -p $GOPATH/src/github.com/jenkinsci
|
||||
cd $GOPATH/src/github.com/jenkinsci/
|
||||
git clone git@github.com:jenkinsci/kubernetes-operator.git
|
||||
cd kubernetes-operator
|
||||
make go-dependencies
|
||||
```
|
||||
|
||||
## Build and run with a minikube
|
||||
|
||||
Build and run **Jenkins Operator** locally:
|
||||
|
||||
```bash
|
||||
make build minikube-run EXTRA_ARGS='--minikube --local'
|
||||
```
|
||||
|
||||
Once minikube and **Jenkins Operator** are up and running, apply Jenkins custom resource:
|
||||
|
||||
```bash
|
||||
kubectl apply -f deploy/crds/jenkins_v1alpha2_jenkins_cr.yaml
|
||||
kubectl get jenkins -o yaml
|
||||
kubectl get po
|
||||
```
|
||||
|
||||
## Build and run with a remote Kubernetes cluster
|
||||
|
||||
You can also run the controller locally and make it listen to a remote Kubernetes server.
|
||||
|
||||
```bash
|
||||
make run NAMESPACE=default KUBECTL_CONTEXT=remote-k8s EXTRA_ARGS='--kubeconfig ~/.kube/config'
|
||||
```
|
||||
|
||||
Once minikube and **Jenkins Operator** are up and running, apply Jenkins custom resource:
|
||||
|
||||
```bash
|
||||
kubectl --context remote-k8s --namespace default apply -f deploy/crds/jenkins_v1alpha2_jenkins_cr.yaml
|
||||
kubectl --context remote-k8s --namespace default get jenkins -o yaml
|
||||
kubectl --context remote-k8s --namespace default get po
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
Run unit tests:
|
||||
|
||||
```bash
|
||||
make test
|
||||
```
|
||||
|
||||
### Running E2E tests on Linux
|
||||
|
||||
Run e2e tests with minikube:
|
||||
|
||||
```bash
|
||||
make minikube-start
|
||||
eval $(minikube docker-env)
|
||||
make build e2e
|
||||
```
|
||||
|
||||
Run the specific e2e test:
|
||||
|
||||
```bash
|
||||
make build e2e E2E_TEST_SELECTOR='^TestConfiguration$'
|
||||
```
|
||||
|
||||
### Running E2E tests on macOS
|
||||
|
||||
At first, you need to start minikube:
|
||||
```bash
|
||||
$ make minikube-start
|
||||
$ eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
Build a Docker image inside the provided Linux container by:
|
||||
```bash
|
||||
$ make indocker
|
||||
```
|
||||
|
||||
Build **Jenkins Operator** inside a container using:
|
||||
|
||||
|
||||
```bash
|
||||
$ make build
|
||||
```
|
||||
|
||||
Then exit the container and run:
|
||||
```
|
||||
make e2e
|
||||
```
|
||||
|
||||
## Tips & Tricks
|
||||
|
||||
### Building docker image on minikube (for e2e tests)
|
||||
|
||||
To be able to work with the docker daemon on `minikube` machine run the following command before building an image:
|
||||
|
||||
```bash
|
||||
eval $(minikube docker-env)
|
||||
```
|
||||
|
||||
### When `pkg/apis/jenkinsio/*/jenkins_types.go` has changed
|
||||
|
||||
Run:
|
||||
|
||||
```bash
|
||||
make deepcopy-gen
|
||||
```
|
||||
|
||||
### Getting the Jenkins URL and basic credentials
|
||||
|
||||
```bash
|
||||
minikube service jenkins-operator-http-<cr_name> --url
|
||||
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
|
||||
```
|
||||
|
||||
# Tools
|
||||
|
||||
## Configure environment variables
|
||||
|
||||
```bash
|
||||
export GOPATH=/home/go # example value
|
||||
export GOROOT=/usr/lib/go-1.12 # example value
|
||||
export PATH=$GOPATH/bin:$PATH
|
||||
```
|
||||
|
||||
## goimports
|
||||
|
||||
```
|
||||
go get golang.org/x/tools/cmd/goimports
|
||||
cd $GOPATH/src/golang.org/x/tools/cmd/goimports
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## golint
|
||||
|
||||
```
|
||||
go get -u golang.org/x/lint/golint
|
||||
cd $GOPATH/src/golang.org/x/lint/golint
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## checkmake
|
||||
```
|
||||
go get github.com/mrtazz/checkmake
|
||||
cd $GOPATH/src/github.com/mrtazz/checkmake
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
## staticcheck
|
||||
|
||||
```
|
||||
mkdir -p $GOPATH/src/github.com/dominikh/
|
||||
cd $GOPATH/src/github.com/dominikh/
|
||||
git clone https://github.com/dominikh/go-tools.git
|
||||
cd $GOPATH/src/github.com/dominikh/go-tools/staticcheck
|
||||
go build
|
||||
go install
|
||||
```
|
||||
|
||||
|
||||
[dep_tool]:https://golang.github.io/dep/docs/installation.html
|
||||
[git_tool]:https://git-scm.com/downloads
|
||||
[go_tool]:https://golang.org/dl/
|
||||
[operator_sdk]:https://github.com/operator-framework/operator-sdk
|
||||
[fork_guide]:https://help.github.com/articles/fork-a-repo/
|
||||
[docker_tool]:https://docs.docker.com/install/
|
||||
[kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/
|
||||
[minikube]:https://kubernetes.io/docs/tasks/tools/install-minikube/
|
||||
[virtualbox]:https://www.virtualbox.org/wiki/Downloads
|
||||
[jenkins-operator]:../README.md
|
||||
[install_dev_tools]:install_dev_tools.md
|
||||
Loading…
Reference in New Issue