basic
[!NOTE]
Java 11 end of life in Jenkins
SUPPORTED JAVA VERSION
LTS RELEASE
WEEKLY RELEASE
Java 11, Java 17 or Java 21
Java 8, Java 11 or Java 17
CPS
The default rule set results in the following:
No JavaScript allowed at all
No plugins (object/embed) allowed
No inline CSS, or CSS from other sites allowed
No images from other sites allowed
Copy job url : http: //localhost:8080/job/<job-name>/
conig url : http: //localhost:8080/job/<job-name>/config.xml
using style in Jenkins
success
Copy <div style="position:relative; padding:1rem 1rem; margin-bottom:1rem; border:1px solid transparent; border-radius:.375rem; padding-right:3rem; color:#0f5132; background-color:#d1e7dd; border-color:#badbcc">
<h4 style="font-size: 1.5rem; color: inherit; margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2">Success Alert !</h4>
This is a success alert with <a href="#" style="font-weight:700; color:#0c4128">an example link</a>. Give it a click if you like.
</div>
warning
Copy <div style="position:relative; padding:1rem 1rem; margin-bottom:1rem; border:1px solid transparent; border-radius:.375rem; padding-right:3rem; color:#664d03; background-color:#fff3cd; border-color:#ffecb5">
<h4 style="font-size: 1.5rem; color: #523e02; margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2">Warning Alert !</h4>
This is a warning alert with <a href="#" style="font-weight:700; color:#523e02">an example link</a>. Give it a click if you like.
</div>
info
Copy <div style="position:relative; padding:1rem 1rem; margin-bottom:1rem; border:1px solid transparent; border-radius:.375rem; padding-right:3rem; color:#055160; background-color:#cff4fc; border-color:#b6effb">
<h4 style="font-size: 1.5rem; color:inherit; margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2">Info Alert !</h4>
This is a info alert with <a href="#" style="font-weight:700; color:#04414d">an example link</a>. Give it a click if you like.
</div>
crumb issuer
get crumb
via groovy script
Copy import hudson.security.csrf.DefaultCrumbIssuer
DefaultCrumbIssuer issuer = jenkins.model.Jenkins.instance.crumbIssuer
jenkinsCrumb = "${issuer.crumbRequestField}:${issuer.crumb}"
result
Copy println jenkinsCrumb
Jenkins-Crumb:7248f4a5***********
via curl
Copy $ domain='jenkins.marslo.com'
$ COOKIEJAR="$(mktemp)"
$ curl -s \
--cookie-jar "${COOKIEJAR} \
https://${domain}/crumbIssuer/api/json |
jq -r '[.crumbRequestField, .crumb] | "\(.[0]):\(.[1])"'
Jenkins-Crumb:8b87b6ed98ef923******
Copy $ domain='jenkins.marslo.com'
$ COOKIEJAR="$(mktemp)"
$ curl -sSLg \
--cookie-jar "${COOKIEJAR} \
https://${domain}/crumbIssuer/api/json |
jq -r '.crumbRequestField + ":" + .crumb'
Copy $ COOKIEJAR="$(mktemp)"
$ curl -s \
--cookie-jar "${COOKIEJAR} \
http://jenkins.marslo.com/crumbIssuer/api/json |
jq -r '[.crumbRequestField, .crumb] | join(":")'
Copy $ COOKIEJAR="$(mktemp)"
$ curl -sSLg \
--cookie-jar "${COOKIEJAR} \
"http://${JENKINS_URL}/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)"
Jenkins-Crumb:8b87b6ed98ef923******
Copy # via xml api
$ COOKIEJAR="$(mktemp)"
$ wget --user=admin \
--password=admin \
--auth-no-challenge \
--save-cookies "${COOKIEJAR}" \
--keep-session-cookies \
-q \
--output-document \
- \
"https://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,%22:%22,//crumb)")"
# via json api
$ COOKIEJAR="$(mktemp)"
$ wget --user=admin \
--password=admin \
--auth-no-challenge \
--save-cookies "${COOKIEJAR}" \
--keep-session-cookies \
-q \
--output-document \
- \
'https://jenkins.marslo.com/crumbIssuer/api/json' |
jq -r '[.crumbRequestField, .crumb] | join(":")'
Copy # via xml
$ wget --user=admin \
--password=admin \
--auth-no-challenge \
-q \
--output-document \
- \
'http://localhost:8080/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
# via json
$ wget --user=admin \
--password=admin \
--auth-no-challenge \
-q \
--output-document \
- \
'https://jenkins.marslo.com/crumbIssuer/api/json' |
jq -r '[.crumbRequestField, .crumb] | join(":")'
visit API via crumb
Copy $ COOKIEJAR="$(mktemp)"
$ CRUMB=$(curl -u "admin:admin" \
--cookie-jar "${COOKIEJAR}" \
'https://jenkins.marslo.com/crumbIssuer/api/json' |
jq -r '[.crumbRequestField, .crumb] | join(":")'
)
$ curl -H "${CRUMB}" \
-d 'cities=Lanzhou' \
http://jenkins.marslo.com/job/marslo/job/sandbox/buildWithParameters
or
Copy $ domain='jenkins.marslo.com'
$ url="https://${domain}"
$ COOKIEJAR="$(mktemp)"
$ curl -H "$(curl -s \
--cookie-jar "${COOKIEJAR}" \
${url}/crumbIssuer/api/json |
jq -r '.crumbRequestField + ":" + .crumb' \
)" \
-d 'cities=Lanzhou' \
${url}/job/marslo/job/sandbox/buildWithParameters
Copy $ curl -H "Jenkins-Crumb:${CRUMB}" \
--data 'cities=Leshan,Chengdu' \
--data 'provinces=Sichuan' \
http://jenkins.marslo.com/job/marslo/job/sandbox/buildWithParameters
or
Copy $ domain='jenkins.marslo.com'
$ url="https://${domain}"
$ curl -H "$(curl -s ${url}/crumbIssuer/api/json | jq -r '.crumbRequestField + ":" + .crumb')" \
--data 'cities=Leshan,Chengdu' \
--data 'provinces=Sichuan' \
${url}/job/marslo/job/sandbox/buildWithParameters
Copy $ curl -X POST http://developer:developer@localhost:8080/job/test/build
# build with parameters
$ curl -X POST \
http://developer:developer@localhost:8080/job/test/build \
--data-urlencode json='{"parameter": [{"name":"paramA", "value":"123"}]}'
[!TIP]
https://jenkins.sample.com/safeRestart
https://jenkins.sample.com/restart
Copy $ curl -X POST \
-H "${CRUMB}" \
http://jenkins.marslo.com/safeRestart
or
Copy $ domain='jenkins.marslo.com'
$ url="https://${domain}"
$ COOKIEJAR="$(mktemp)"
$ curl -X POST \
-H "$(curl -s \
--cookie-jar "${COOKIEJAR}" \
${url}/crumbIssuer/api/json |
jq -r '.crumbRequestField + ":" + .crumb' \
)" \
${url}/safeRestart
run Jenkins
[!TIP|label: latest jdk11 JAVA_OPT:]
Copy -Duser.timezone='America/Los_Angeles'
-Dhudson.model.DirectoryBrowserSupport.CSP=""
-Djenkins.slaves.NioChannelSelector.disabled=true
-Djenkins.slaves.JnlpSlaveAgentProtocol3.enabled=false
-Djava.awt.headless=true
-Djenkins.security.ClassFilterImpl.SUPPRESS_WHITELIST=true
-Dhudson.model.ParametersAction.keepUndefinedParameters=true
-Dcom.cloudbees.workflow.rest.external.ChangeSetExt.resolveCommitAuthors=true
-Djenkins.install.runSetupWizard=true
-Dpermissive-script-security.enabled=true
-DsessionTimeout=1440
-DsessionEviction=43200
-Dgroovy.grape.report.downloads=true
-Divy.message.logger.level=4
-Dhudson.plugins.active_directory.ActiveDirectorySecurityRealm.forceLdaps=false
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=utf-8
-Djenkins.model.Jenkins.logStartupPerformance=true
-Dhudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID=true
-Xms192g
-Xmx192g
-XX:+AlwaysPreTouch
-XX:+HeapDumpOnOutOfMemoryError
-XX:+UseG1GC
-XX:+UseStringDeduplication
-XX:+UseCompressedClassPointers
-XX:+UseCompressedOops
-XX:+ParallelRefProcEnabled
-XX:+UnlockDiagnosticVMOptions
-XX:+UnlockExperimentalVMOptions
-XX:G1NewSizePercent=20
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+LogVMOutput
-XX:InitialRAMPercentage=50.0
-XX:MaxRAMPercentage=50.0
-XX:HeapDumpPath=/var/jenkins_home/logs
-XX:ErrorFile=/var/jenkins_home/logs/hs_err_%p.log
-XX:LogFile=/var/jenkins_home/logs/jvm.log
-Xlog:gc*=info,gc+heap=debug,gc+ref*=debug,gc+ergo*=trace,gc+age*=trace:file=/var/jenkins_home/logs/gc-%t.log:utctime,pid,level,tags:filecount=2,filesize=100M
in docker
Copy $ docker run \
--name jenkins \
--rm \
--detach \
--network jenkins \
--env DOCKER_HOST=tcp://docker:2376 \
--env DOCKER_CERT_PATH=/certs/client \
--env DOCKER_TLS_VERIFY=1 \
--publish 8080:8080 \
--publish 50000:50000 \
--volume jenkins-data:/var/jenkins_home \
--volume jenkins-docker-certs:/certs/client:ro \
jenkins/jenkins:latest
docker run with JAVA_OPTS
Copy $ docker run \
--name jenkins \
--detach \
--rm \
--network jenkins \
--env DOCKER_HOST=tcp://docker:2376 \
--env DOCKER_CERT_PATH=/certs/client \
--env DOCKER_TLS_VERIFY=1 \
--publish 8080:8080 \
--publish 50000:50000 \
--env JENKINS_ADMIN_ID=admin \
--env JENKINS_ADMIN_PW=admin \
--env JAVA_OPTS=" \
-XX:+UseG1GC \
-Xms8G \
-Xmx16G \
-Dfile.encoding=UTF-8 \
-Dsun.jnu.encoding=utf-8 \
-DsessionTimeout=1440 \
-DsessionEviction=43200 \
-Djava.awt.headless=true \
-Djenkins.ui.refresh=true \
-Divy.message.logger.level=4 \
-Dhudson.Main.development=true \
-Duser.timezone='Asia/Chongqing' \
-Dgroovy.grape.report.downloads=true \
-Djenkins.install.runSetupWizard=true \
-Dpermissive-script-security.enabled=true \
-Dhudson.footerURL=https://jenkins.marslo.com \
-Djenkins.slaves.NioChannelSelector.disabled=true \
-Djenkins.slaves.JnlpSlaveAgentProtocol3.enabled=false \
-Dhudson.model.ParametersAction.keepUndefinedParameters=true \
-Djenkins.security.ClassFilterImpl.SUPPRESS_WHITELIST=true \
-Dhudson.security.ArtifactsPermission=true \
-Dhudson.security.LDAPSecurityRealm.groupSearch=true \
-Dhudson.security.csrf.DefaultCrumbIssuer.EXCLUDE_SESSION_ID=true \
-Dcom.cloudbees.workflow.rest.external.ChangeSetExt.resolveCommitAuthors=true \
-Dhudson.plugins.active_directory.ActiveDirectorySecurityRealm.forceLdaps=false \
-Dhudson.model.DirectoryBrowserSupport.CSP=\"sandbox allow-same-origin allow-scripts; default-src 'self'; script-src * 'unsafe-eval'; img-src *; style-src * 'unsafe-inline'; font-src *;\" \
" \
--env JNLP_PROTOCOL_OPTS="-Dorg.jenkinsci.remoting.engine.JnlpProtocol3.disabled=false" \
--volume /opt/JENKINS_HOME:/var/jenkins_home \
--volume /var/run/docker.sock:/var/run/docker.sock \
jenkins/jenkins:latest
backup the docker volume
Copy $ docker run --rm \
-v jenkins_home:/var/jenkins_home \
-v $(pwd):/backup \
ubuntu \
tar cvf /backup/backup.tar /var/jenkins_home
running docker images as services
Copy $ cat /etc/systemd/system/docker-jenkins.service
[Unit]
Description=Jenkins
[Service]
SyslogIdentifier=docker-jenkins
ExecStartPre=-/usr/bin/docker create -m 0b -p 8080:8080 -p 50000:50000 --restart=always --name jenkins jenkins/jenkins:lts-jdk11
ExecStart=/usr/bin/docker start -a jenkins
ExecStop=-/usr/bin/docker stop --time=0 jenkins
[Install]
WantedBy=multi-user.target
$ sudo systemctl daemon-reload
$ sudo systemctl enable docker-jenkins
$ sudo systemctl start docker-jenkins
# check log
$ sudo journalctl -u docker-jenkins -f
in kubernetes
Copy $ cat << EOF | kubectl apply -f -
# namespace
---
kind: Namespace
apiVersion: v1
metadata:
name: devops
labels:
name: devops
# quota
---
apiVersion: v1
kind: ResourceQuota
metadata:
name: quota
namespace: devops
spec:
hard:
requests.cpu: "48"
requests.memory: 48Gi
limits.cpu: "48"
limits.memory: 48Gi
# sa
---
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: jenkins
name: jenkins-admin
namespace: devops
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: jenkins-admin
labels:
k8s-app: jenkins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: jenkins-admin
namespace: devops
# pv & pvc
---
kind: PersistentVolume
apiVersion: v1
metadata:
name: jenkins-pv
spec:
capacity:
storage: 200Gi
accessModes:
- ReadWriteMany
nfs:
server: 1.2.3.4
path: "/jenkins_vol/jenkins/DEVOPS_JENKINS"
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: jenkins-pvc
namespace: devops
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
storageClassName: ""
volumeName: jenkins-pv
# deploy
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: jenkins
namespace: devops
spec:
replicas: 1
selector:
matchLabels:
app: jenkins
template:
metadata:
labels:
app: jenkins
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- aws-hostname-01
- aws-hostname-02
containers:
- name: jenkins
image: jenkins/jenkins:latest
imagePullPolicy: IfNotPresent
env:
- name: JAVA_OPTS
value: -Xms2048m
-Xmx10240m
-XX:PermSize=2048m
-XX:MaxPermSize=10240m
-DsessionTimeout=1440
-DsessionEviction=43200
-Djava.awt.headless=true
-Divy.message.logger.level=4
-Dfile.encoding=UTF-8
-Dsun.jnu.encoding=utf-8
-Duser.timezone='Asia/Chongqing'
-Djenkins.install.runSetupWizard=true
-Dpermissive-script-security.enabled=true
-Djenkins.slaves.NioChannelSelector.disabled=true
-Djenkins.slaves.JnlpSlaveAgentProtocol3.enabled=false
-Djenkins.security.ClassFilterImpl.SUPPRESS_WHITELIST=true
-Dhudson.model.ParametersAction.keepUndefinedParameters=true
-Dcom.cloudbees.workflow.rest.external.ChangeSetExt.resolveCommitAuthors=true
-Dhudson.plugins.active_directory.ActiveDirectorySecurityRealm.forceLdaps=false
-Dhudson.model.DirectoryBrowserSupport.CSP="sandbox allow-same-origin allow-scripts; default-src 'self'; script-src * 'unsafe-eval'; img-src *; style-src * 'unsafe-inline'; font-src *;"
- name: JNLP_PROTOCOL_OPTS
value: -Dorg.jenkinsci.remoting.engine.JnlpProtocol3.disabled=false
ports:
- name: http-port
containerPort: 8080
- name: jnlp-port
containerPort: 50000
- name: cli-port
containerPort: 38338
volumeMounts:
- name: jenkins-home
mountPath: /var/jenkins_home
resources:
requests:
memory: '8Gi'
cpu: '8'
limits:
memory: '16Gi'
cpu: '16'
volumes:
- name: jenkins-home
persistentVolumeClaim:
claimName: jenkins-pvc
serviceAccount: "jenkins-admin"
# svc
---
apiVersion: v1
kind: Service
metadata:
name: jenkins
namespace: devops
spec:
template:
metadata:
labels:
name: jenkins
spec:
type: ClusterIP
ports:
- name: jenkins
port: 8080
targetPort: 8080
selector:
app: jenkins
---
apiVersion: v1
kind: Service
metadata:
name: jenkins-discovery
namespace: devops
spec:
template:
metadata:
labels:
name: jenkins-discovery
spec:
type: NodePort
ports:
- name: jenkins-agent
port: 50000
targetPort: 50000
- name: cli-agent
port: 38338
targetPort: 38338
selector:
app: jenkins
# ing (for traefik ingress)
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins
namespace: devops
annotations:
kubernetes.io/ingress.class: traefik
ingress.kubernetes.io/whitelist-x-forwarded-for: "false"
traefik.frontend.redirect.entryPoint: https
ingress.kubernetes.io/ssl-redirect: "true"
labels:
app: jenkins
spec:
rules:
- host: jenkins.mysite.com
http:
paths:
- backend:
serviceName: jenkins
servicePort: 8080
tls:
- hosts:
- jenkins.mysite.com
secretName: mysite-tls
EOF
for nginx ingress
Copy ---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: jenkins
namespace: devops
annotations:
kubernetes.io/ingress.class: "nginx"
nginx.ingress.kubernetes.io/secure-backends: "true"
nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
kubernetes.io/ingress.allow-http: "false"
spec:
tls:
- hosts:
- jenkins.mysite.com
secretName: mysite-certs
rules:
- host: jenkins.mysite.com
http:
paths:
- path:
backend:
serviceName: jenkins
servicePort: 8080
via helm
[!TIP]
Copy $ helm repo add jenkins https://charts.jenkins.io
$ helm repo update
$ helm upgrade --install myjenkins jenkins/jenkins
$ kubectl exec --namespace default \
-it svc/myjenkins \
-c jenkins -- /bin/cat /run/secrets/chart-admin-password && echo
forward port
Copy $ kubectl --namespace default port-forward svc/myjenkins 8080:8080
show Load Balancer
[!TIP]
Copy $ helm show values jenkins/jenkins
...
controller:
serviceType: LoadBalancer
...
upgrade
Copy $ helm upgrade --install -f values.yaml myjenkins jenkins/jenkins
get info
Copy $ kubectl get svc --namespace default myjenkins --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}"
a84aa6226d6e5496882cfafdd6564a35-901117307.us-west-1.elb.amazonaws.com
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
java-9-k0hmj-vcvdz-wknh4 0/1 ContainerCreating 0 1s
myjenkins-0 2/2 Running 0 49m
customizing
installing additional plugins
Copy ...
controller:
additionalPlugins:
- octopusdeploy:3.1.6
...
customizing jenkins docker image
Copy ...
controller:
image: "docker.io/mcasperson/myjenkins"
tag: "latest"
installPlugins: false
...
adding jenkins agents
Copy ...
agent:
podName: default
customJenkinsLabels: default
resources:
limits:
cpu: "1"
memory: "2048Mi"
...
defines a second pod template
Copy ...
agent:
podName: default
customJenkinsLabels: default
resources:
limits:
cpu: "1"
memory: "2048Mi"
additionalAgents:
maven:
podName: maven
customJenkinsLabels: maven
image: jenkins/jnlp-agent-maven
tag: latest
...
jenkinsfile
Copy pipeline {
agent {
kubernetes {
inheritFrom 'maven'
}
}
// ...
}
backup jenkins home
Copy $ kubectl exec -c jenkins myjenkins-0 -- tar czf /tmp/backup.tar.gz /var/jenkins_home
$ kubectl cp -c jenkins myjenkins-0:/tmp/backup.tar.gz ./backup.tar.gz
build Jenkins docker image
[!TIP|label: references:]
Copy FROM jenkins/jenkins:lts-jdk11
USER root
RUN apt update && \
apt install -y --no-install-recommends gnupg curl ca-certificates apt-transport-https && \
curl -sSfL https://apt.octopus.com/public.key | apt-key add - && \
sh -c "echo deb https://apt.octopus.com/ stable main > /etc/apt/sources.list.d/octopus.com.list" && \
apt update && apt install -y octopuscli
RUN jenkins-plugin-cli --plugins octopusdeploy:3.1.6 kubernetes:1.29.2 workflow-aggregator:2.6 git:4.7.1 configuration-as-code:1.52
USER jenkins
run Jenkins API out of Jenkins
Copy @GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/public/')
@Grapes([
@Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.167')
])
import hudson.model.*
Copy @GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/public/')
@Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377')
jenkins-core
Copy @GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases')
@Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377')
import hudson.Util
println Util.XS_DATETIME_FORMATTER.format( new Date() )
org.jenkinsci.plugins.workflow
Copy // Groovy Version: 3.0.13 JVM: 11.0.15.1
@GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases')
@Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-job', version='1254.v3f64639b_11dd')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-basic-steps', version='991.v43d80fea_ff66', scope='test')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-api', version='1192.v2d0deb_19d212')
import jenkins.model.Jenkins
import hudson.model.Job
import hudson.Util
import org.jenkinsci.plugins.workflow.job.WorkflowJob
import org.jenkinsci.plugins.workflow.flow.BlockableResume
String rootUrl = 'https://jenkins.sample.com'
Map<String, WorkflowJob> jobs = jenkins.getJobs()
println jobs
// output
// Caught: groovy.lang.MissingPropertyException: No such property: jenkins for class: jenkins-job
Copy @GrabResolver(name='jenkins', root='https://repo.jenkins-ci.org/releases')
@Grab(group='org.jenkins-ci.main', module='jenkins-core', version='2.377')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-api', version='1200.v8005c684b_a_c6')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-job', version='1254.v3f64639b_11dd')
@Grab(group='org.jenkins-ci.plugins.workflow', module='workflow-step-api', version='639.v6eca_cd8c04a_a_')
@Grab(group='javax.ws', module='rs', version='2.0.1')
@Grab(group='io.github.cdancy', module='jenkins-rest', version='1.0.2')
import jenkins.model.Jenkins
import hudson.Util
import hudson.model.Job
import org.jenkinsci.plugins.workflow.job.WorkflowJob
import com.cdancy.jenkins.rest.JenkinsClient
String jenkinsUrl = 'https://jenkins.sample.com'
String userName = 'admin'
String password = 'admin'
JenkinsClient client = JenkinsClient.builder()
.endPoint( jenkinsUrl )
.credentials( "${userName}:${password}" )
.build();
println client.getClass()
println client.api().systemApi().systemInfo().getClass()
println client.api().getClass()
// Groovy Version: 3.0.13 JVM: 11.0.15.1
// output
// class com.cdancy.jenkins.rest.JenkinsClient
// class com.cdancy.jenkins.rest.domain.system.AutoValue_SystemInfo
// class com.sun.proxy.$Proxy68