Ravi Srinivasan
2019-01-31 543f71c68ec4e219daaaf60b1cf66664e24a9025
commit | author | age
e36a5b 1 # An Enslaved Hope
43f2f2 2
1173e5 3 > In this exercise we'll break free from the chains of point'n'click Jenkins by introducing pipeline as code in the form of `Jenkinsfile`. Following this we will introduce some new Jenkins slaves that will be used in later exercises.
e36a5b 4
44d7bc 5 <!-- ![jenkins-fail-meme](../images/exercise4/jenkins-fail-meme.jpeg) -->
921415 6
e36a5b 7 There are a number of ways pipeline as code can be achieved in Jenkins.
44d7bc 8
1173e5 9  * The Job DSL Plugin - this is a slightly older but very functional DSL mechanism to create reusable pipelines. Create a `groovy` file to run Jenkins Domain Specific Language to create jobs, functions and other items. In Jenkins; you then can execute this file which will build all of the config.xml files needed for each Job.
44d7bc 10
8894bf 11  * The Scripted Pipeline - The scripted pipeline introduced the Jenkinsfile and the ability for developers to write their Jenkins setup as groovy code. A repo with a Jenkinsfile in its root can be pointed to by Jenkins and it will automatically build out each of the stages described within. The scripted pipeline is ultimately Groovy at its core.
44d7bc 12
dd12d4 13  * The Declarative Pipeline - This approach looks to simplify and opinionate what you can do and when you can do it in a pipeline. It does this by giving you top level `block` which define sections, directives and steps. The declarative syntax is not run as groovy but you can execute groovy inside script blocks. The advantage of it over scripted is validation of the config and lighter approach with requirement to understand all of the `groovy` syntax
e36a5b 14
43f2f2 15 _____
D 16
17 ## Learning Outcomes
18 As a learner you will be able to
1173e5 19 - Use a Jenkinsfile to create a declarative pipeline to build, bake and deploy the Todolist App
CM 20 - Identify the differences between scripted, declarative and DSL pipelines
b5d705 21 - Create Jenkins slave nodes for use in builds in future exercises
43f2f2 22
D 23 ## Tools and Frameworks
44d7bc 24 <!-- > Name of tool - short description and link to docs or website -->
43f2f2 25
44d7bc 26 1. [Jenkins Pipeline](https://jenkins.io/doc/book/pipeline/) - Overview of the Jenkinsfile approach
e36a5b 27 1. [Pipeline Syntax](https://jenkins.io/doc/book/pipeline/syntax/) - Documentation for the declarative pipeline
D 28 1. [Groovy](http://groovy-lang.org/) - Groovy is a powerful, optionally typed and dynamic language, with static-typing and static compilation capabilities, for the Java platform aimed at improving developer productivity thanks to a concise, familiar and easy to learn syntax. It integrates smoothly with any Java program, and immediately delivers to your application powerful features, including scripting capabilities, Domain-Specific Language authoring, runtime and compile-time meta-programming and functional programming.
b664dc 29 1. [Zed Attack Proxy](https://www.owasp.org/index.php/OWASP_Zed_Attack_Proxy_Project) - The OWASP Zed Attack Proxy (ZAP) is one of the world’s most popular free security tools and is actively maintained by hundreds of international volunteers*. It can help you automatically find security vulnerabilities in your web applications while you are developing and testing your applications. Its also a great tool for experienced pentesters to use for manual security testing.
D 30 1. [Arachni Crawler](http://www.arachni-scanner.com/) - Arachni is a feature-full, modular, high-performance Ruby framework aimed towards helping penetration testers and administrators evaluate the security of modern web applications. It is free, with its source code public and available for review. It is versatile enough to cover a great deal of use cases, ranging from a simple command line scanner utility, to a global high performance grid of scanners, to a Ruby library allowing for scripted audits, to a multi-user multi-scan web collaboration platform. In addition, its simple REST API makes integration a cinch.
43f2f2 31
D 32 ## Big Picture
664135 33 > From the previous exercise; we gated our pipeline. Now we will add a pipeline-as-code in the form of the Jenkinfile and re-use it on the Backend too.
D 34
14a966 35 ![big-picture](../images/big-picture/big-picture-4.jpg)
43f2f2 36
D 37 _____
38
44d7bc 39 <!-- ## 10,000 Ft View
b5d705 40 > The goal of this exercise is to move to using the Jenkinsfile in the todolist-api and todolist-fe projects. Additionally we will create new slaves for use in the next exercise.
43f2f2 41
e43fd2 42 2. On Jenkins; create a multibranch pipeline project to scan the GitLab endpoint for each app. Use the Jenkinsfile provided to run the stages. Replace `<YOUR_NAME>` with the appropriate variable.
43f2f2 43
44d7bc 44 2. Create two new Jenkins slaves for the `OWASP ZAP` scanner and the `Arachni` WebCrawler -->
43f2f2 45
D 46 ## Step by Step Instructions
44d7bc 47 <!-- > This is a fairly structured guide with references to exact filenames and sections of text to be added. -->
43f2f2 48
e36a5b 49 ### Part 1 - The Jenkinsfile
543f71 50 > _In this exercise we'll replace the Pipeline we created in the previous exercise with a Jenkinsfile approach_
43f2f2 51
543f71 52 1. On your terminal navigate to your `todolist-api` project and checkout the pipeline feature branch that's been already created for you.
RS 53 ```bash
54 cd todolist-api
55 ```
e36a5b 56 ```bash
fad576 57 git checkout feature/jenkinsfile
43f2f2 58 ```
D 59
1173e5 60 2. Open up your `todolist-api` application in your favourite editor and move to the `Jenkinsfile` in the root of the project. The high-level structure of the file is shown collapsed below.
e36a5b 61 ![pipeline-overview](../images/exercise4/pipeline-overview.png)
D 62 Some of the key things to note:
1173e5 63     * `pipeline {}` is how all declarative Jenkins pipelines begin.
db509f 64     * `environment {}` defines environment variables to be used across all build stages
A 65     * `options {}` contains specific Job specs you want to run globally across the jobs e.g. setting the terminal colour
66     * `stage {}` all jobs must have one stage. This is the logical part of the build that will be executed e.g. `bake-image`
e36a5b 67     * `steps {}` each `stage` has one or more steps involved. These could be execute shell or git checkout etc.
1173e5 68     * `agent {}` specifies the node the build should be run on e.g. `jenkins-slave-npm`
e43fd2 69     * `post {}` hook is used to specify the post-build-actions. Jenkins declarative pipeline syntax provides very useful callbacks for `success`, `failure` and `always` which are useful for controlling the job flow
W 70     * `when {}` is used for flow control. It can be used at the stage level and be used to stop pipeline entering that stage. e.g. when branch is master; deploy to `test` environment.
e36a5b 71
543f71 72 3. The Jenkinsfile is mostly complete to do all the testing etc that was done in previous exercises. Some minor changes will be needed to orchestrate namespaces. Find and replace all instances of `<YOUR_NAME>` in the Jenkinsfile. Update the `<GIT_USERNAME>` to the one you login to the cluster with; this variable is used in the namespace of your git projects when checking out code etc. Ensure the `GITLAB_DOMAIN` matches your git host.
e36a5b 73 ```groovy
D 74     environment {
75         // GLobal Vars
dd12d4 76         PIPELINES_NAMESPACE = "<YOUR_NAME>-ci-cd"
e36a5b 77         APP_NAME = "todolist-api"
D 78
79         JENKINS_TAG = "${JOB_NAME}.${BUILD_NUMBER}".replace("/", "-")
80         JOB_NAME = "${JOB_NAME}".replace("/", "-")
81
82         GIT_SSL_NO_VERIFY = true
83         GIT_CREDENTIALS = credentials('jenkins-git-creds')
530a25 84         GITLAB_DOMAIN = "gitlab.<APPS_URL>"
70ba2a 85         GITLAB_PROJECT = "<GIT_USERNAME>"
e36a5b 86     }
D 87 ```
88
543f71 89 4. With these changes in place, push your changes to the `feature/jenkinsfile` branch.
e36a5b 90 ```bash
fad576 91 git add Jenkinsfile
D 92 ```
93 ```bash
94 git commit -m "ADD - namespace and git repo to pipeline"
95 ```
96 ```bash
97 git push
e36a5b 98 ```
D 99
543f71 100 5. When the changes have been successfully pushed; Open Jenkins.
e36a5b 101
543f71 102 6. Create a `New Item` on Jenkins. Give it the name `todolist-api` and select `Multibranch Pipeline` from the bottom of the list as the job type.
e36a5b 103 ![multibranch-select](../images/exercise4/multibranch-select.png)
D 104
543f71 105 7. On the job's configure page; set the Branch Sources to `git`
e36a5b 106 ![multibranch-select-git](../images/exercise4/multibranch-select-git.png)
D 107
543f71 108 8. Fill in the Git settings with your `todolist-api` GitLab url and set the credentials as you've done before. `https://gitlab.<APPS_URL>/<YOUR_NAME>/todolist-api.git`
e36a5b 109 ![multibranch-git](../images/exercise4/multibranch-git.png)
D 110
543f71 111 9. Set the `Scan Multibranch Pipeline Triggers` to be periodic and the interval to 1 minute. This will poll the GitLab instance for new branches or change sets to build.
e36a5b 112 ![multibranch-scan-time](../images/exercise4/multibranch-scan-time.png)
D 113
543f71 114 10. Save the Job configuration to run the intial scan. The log will show scans for `master` and `develop` branches, which have no `Jenkinsfile` so are skipped. The resulting view will show the `feature/jenkinsfile` job corresponding the only branch that currently has one. The build should run automatically.
e36a5b 115 ![todolist-api-multi](../images/exercise4/todolist-api-multi.png)
D 116
543f71 117 11. The pipeline file is setup to only run `bake` & `deploy` stages when on `master` or `develop` branch. This is to provide us with very fast feedback for team members working on feature or bug fix branches. Each time someone commits or creates a new branch a basic build with testing occurs to give very rapid feedback to the team. Let's now update our  `master` and `develop` branches to include the Jenkinsfile and delete the feature branch.
e36a5b 118 ```bash
fad576 119 git checkout develop
D 120 ```
121 ```bash
122 git merge feature/jenkinsfile
ed472a 123 # you may get merge conflicts at this point
fad576 124 ```
543f71 125 > NOTE: You may see a number of merge conflict warnings at this point. You can safely ignore them and proceed to commit the changes.
RS 126
fad576 127 ```bash
D 128 git add .
129 ```
130 ```bash
131 git commit -m "Jenkinsfile updates"
132 ```
133 ```bash
134 git checkout master
135 ```
136 ```bash
137 git merge develop
138 ```
139 ```bash
140 git push -u origin --all
141 ```
142 ```bash
e36a5b 143 # this is to delete the branch from the remote
fad576 144 git push origin :feature/jenkinsfile
e36a5b 145 ```
D 146
543f71 147 12. Back on Jenkins we should see our `todolist-api` pipelines have changed with the `develop` and `master` now appearing. The `feature/jenkinsfile` branch was deleted so this job will go away after some time.
e36a5b 148 ![todolist-api-multi-dev-test](../images/exercise4/todolist-api-multi-dev-test.png)
D 149
543f71 150 13. With the builds running for  `develop` and `master` we can explore the Blue Ocean View for Jenkins. On the Job overview page, hit the `Open Blue Ocean` button on the side to see what modern Jenkins looks like.
e36a5b 151 ![blue-ocean-todolist-api](../images/exercise4/blue-ocean-todolist-api.png)
543f71 152 <!-- ![open-blue-ocean](../images/exercise4/open-blue-ocean.png) -->
e36a5b 153
543f71 154 14.  We can move on to the `todolist-fe` job. The process is the same as before, checkout the feature branch
e36a5b 155 ```bash
fad576 156 cd todolist-fe
D 157 ```
158 ```bash
159 git checkout feature/jenkinsfile
e36a5b 160 ```
D 161
543f71 162 15. Open up your `todolist-fe` application in your favourite editor and move to the `Jenkinsfile` in the root of the project. Update all `<YOUR_NAME>` and `<GIT_USERNAME>` as you did before, including in the prepare environment steps. Check the  `GITLAB_DOMAIN` is set too.
e36a5b 163
543f71 164 <!-- ![jenkinsfile-prep](../images/exercise4/jenkinsfile-prep.png) -->
RS 165
166 16. Commit your changes to your feature branch as you did previously.
e36a5b 167 ```bash
fad576 168 git add Jenkinsfile
D 169 ```
170 ```bash
171 git commit -m "ADD - namespace and git repo to pipeline"
172 ```
173 ```bash
174 git push
e36a5b 175 ```
D 176
543f71 177 17. This time update your `master` and `develop` branches before creating config in Jenkins
e36a5b 178 ```
fad576 179 git checkout develop
D 180 ```
181 ```bash
182 git merge feature/jenkinsfile
ed472a 183 # you may get merge conflicts at this point
fad576 184 ```
D 185 ```bash
186 git add .
187 ```
188 ```bash
189 git commit -m "Jenkinsfile updates"
190 ```
191 ```bash
192 git checkout master
193 ```
194 ```bash
195 git merge develop
196 ```
197 ```bash
ed472a 198 # this is to delete the branch from the remote
fad576 199 git push origin :feature/jenkinsfile
D 200 ```
201 ```bash
202 git push -u origin --all
e36a5b 203 ```
D 204
543f71 205 18. On Jenkins; create a new `Multibranch Pipeline` job called `todolist-fe`.
e36a5b 206
543f71 207 19. Add the `todolist-fe` git repository and set the credentials for git accordingly.
e36a5b 208
543f71 209 20. Set the trigger to scan every minute as done previously. Save the configuration and we should see the collection of Jobs as shown below.
e36a5b 210 ![todolist-fe-multi](../images/exercise4/todolist-fe-multi.png)
D 211
543f71 212 > NOTE: If the `feature/jenkinsfile` job is running, you can stop it to speed up the job execution for the `master` and `develop` branches.
RS 213
214 21. Run the jobs and validate the app is working as expected in the `test` environment!
ed472a 215 ![todolist-test](../images/exercise4/todolist-test.png)
34fb36 216
D 217 ### Part 2 - OCP Pipeline
218 > _This exercise adds a new BuildConfig to our cluster for the todolist-apps to run their pipelines in OpenShift using the OpenShift Jenkins Sync Plugin. We will use the OpenShift Applier to create the content in the cluster_
219
543f71 220 1. For the rest of the lab, ensure that you are working from the `master` branch
RS 221 ```bash
222 git checkout master
223 ```
224
b2ce13 225 2. Open the `todolist-fe` app in your favourite editor. Move to the `.openshift-applier` directory. Explore the `template/ocp-pipeline`. This template creates a BuildConfig for OpenShift with a Jenkinsfile from a given repo. In this case; it will be the `Jenkinsfile` at the root of our application.
34fb36 226
543f71 227 3. Open the `params/ocp-pipeline` file and update `PIPELINE_SOURCE_REPOSITORY_URL` with the git url of your project (Don't forget to add the `.git` at the end). For example:
34fb36 228 ```
530a25 229 PIPELINE_SOURCE_REPOSITORY_URL=https://gitlab.<APPS_URL>/<GIT_USERNAME>/todolist-fe.git
34fb36 230 PIPELINE_SOURCE_REPOSITORY_REF=develop
D 231 NAME=todolist-fe
232 ```
233
543f71 234 4. Create a new object in `inventory/group_vars/all.yml` to drive the `ocp-pipeline` template with the parameters file you've just created. It can be put under the existing `todolist-fe-build` object.
34fb36 235 ```yaml
D 236   - name: todolist-ocp-pipeline
237     template: "{{ playbook_dir }}/templates/ocp-pipeline.yml"
238     params: "{{ playbook_dir }}/params/ocp-pipeline"
239     namespace: "{{ ci_cd_namespace }}"
240     tags:
241     - pipeline
242 ```
243 ![ocp-pipeline-applier](../images/exercise4/ocp-pipeline-applier.png)
244
543f71 245 5. Log in to OpenShift using the `oc` client, and use the OpenShift Applier to create the cluster content
34fb36 246 ```bash
543f71 247 oc login https://<CLUSTER_URL>
RS 248 ```
249 ```bash
250 cd todolist-fe/.openshift-applier
fad576 251 ```
D 252 ```bash
253 ansible-playbook apply.yml -i inventory/ \
34fb36 254      -e "filter_tags=pipeline"
D 255 ```
543f71 256 > NOTE: Windows users should run the `oc` command and Ansible playbook from inside the `do500-toolbox` container.
34fb36 257
543f71 258 6. With these changes in place, commit your changes to GitLab
d4f1fa 259 ```bash
fad576 260 git add .
D 261 ```
262 ```bash
263 git commit -m "ADD - ocp pipeline in git repo"
264 ```
265 ```bash
266 git push
d4f1fa 267 ```
D 268
543f71 269 7. Login to your OpenShift Cluster and go to the `<YOUR_NAME>-ci-cd` namespace. On the side menu; hit `Builds > Pipeline` to see your newly created pipeline running in OCP Land.
34fb36 270 ![ocp-pipeline-view](../images/exercise4/ocp-pipeline-view.png)
D 271
543f71 272 8. Running the pipeline from here will run it in Jenkins. You can see the job sync between OpenShift and Jenkins if you login to Jenkins. You should see a folder with `<YOUR_NAME>-ci-cd` and your pipeline jobs inside of it.
34fb36 273 ![ocp-pipeline-jenkins](../images/exercise4/ocp-pipeline-jenkins.png)
D 274
543f71 275 > NOTE: If you see failures in the first pipeline run, re-run the pipeline again and it should succeed.
RS 276
277 9. With the configuration in place for the `todolist-fe`; repeat the process for the `todolist-api`. 
278 ```bash
279 cd todolist-api/.openshift-applier
280 ```
281 ```bash
282 git checkout master
283 ```
284
285 10. Update the `todolist-api/.openshift-applier/inventory/group_vars/all.yml` with a new object to drive the params and template
34fb36 286 ```yaml
d4f1fa 287   - name: todolist-ocp-pipeline
34fb36 288     template: "{{ playbook_dir }}/templates/ocp-pipeline.yml"
D 289     params: "{{ playbook_dir }}/params/ocp-pipeline"
290     namespace: "{{ ci_cd_namespace }}"
291     tags:
292     - pipeline
293 ```
294
543f71 295 11. Update the `todolist-api/.openshift-applier/params/ocp-pipeline`
34fb36 296 ```
530a25 297 PIPELINE_SOURCE_REPOSITORY_URL=https://gitlab.<APPS_URL>/<GIT_USERNAME>/todolist-api.git
34fb36 298 PIPELINE_SOURCE_REPOSITORY_REF=develop
D 299 NAME=todolist-api
300 ```
301
543f71 302 12. Use the OpenShift Applier to create the cluster content
34fb36 303 ```bash
fad576 304 cd todolist-api/.openshift-applier
543f71 305 ```
RS 306 ```bash
307 oc login https://<CLUSTER_URL>
fad576 308 ```
D 309 ```bash
310 ansible-playbook apply.yml -i inventory/ \
34fb36 311      -e "filter_tags=pipeline"
D 312 ```
313
543f71 314 > NOTE: Windows users should run the `oc` command and Ansible playbook from inside the `do500-toolbox` container.
RS 315
316 13. Login to your OpenShift Cluster and go to the `<YOUR_NAME>-ci-cd` namespace. On the side menu; hit `Builds > Pipeline` to see your newly created pipeline running in OCP Land.
34fb36 317 ![ocp-pipeline-view2](../images/exercise4/ocp-pipeline-view2.png)
D 318
543f71 319 14. Commit your changes to GitLab
d4f1fa 320 ```bash
fad576 321 git add .
D 322 ```
323 ```bash
324 git commit -m "ADD - ocp pipeline in git repo"
325 ```
326 ```bash
327 git push
d4f1fa 328 ```
34fb36 329
D 330 ### Part 3 - Security Scanning Slaves
44d7bc 331 > _This part of the exercise focuses on updating the `enablement-ci-cd` repo with some new jenkins-slave pods for use in future exercise_
43f2f2 332
44d7bc 333 <!-- #### 3a - OWASP ZAP
6769e3 334 > _OWASP ZAP (Zed Attack Proxy) is a free open source security tool used for finding security vulnerabilities in web applications._
A 335
40c0ca 336 3. On your  terminal; move to the `enablement-ci-cd` repo.  We need to checkout a template for OpenShift to build our Jenkins Slave images and some parameters for the `zap` slave.
6769e3 337 ```bash
40c0ca 338 git checkout exercise4/zap-and-arachni params/jenkins-slave-zap templates/jenkins-slave-generic-template.yml
6769e3 339 ```
A 340
5b1604 341 3. This should have created the following files which we will fill out. We will use a `ZAP` image hosted on the `rht-labs/ci-cd` repo so there will be no `Dockerfile` needed:
e32e5c 342     - `params/jenkins-slave-zap`
6769e3 343
da9923 344 3. Create an object in `inventory/host_vars/ci-cd-tooling.yml` called `jenkins-slave-zap` and add the following content:
054490 345 ```yaml
da9923 346     - name: "jenkins-slave-zap"
b664dc 347       namespace: "{{ ci_cd_namespace }}"
D 348       template: "{{ playbook_dir }}/templates/jenkins-slave-generic-template.yml"
da9923 349       params: "{{ playbook_dir }}/params/jenkins-slave-zap"
b664dc 350       tags:
D 351       - zap
6769e3 352 ```
2c15b7 353 ![zap-object](../images/exercise4/zap-object.png)
6769e3 354
A 355 3. Run the ansible playbook filtering with tag `zap` so only the zap build pods are run.
356 ```bash
fad576 357 ansible-playbook apply.yml -e target=tools \
b664dc 358      -i inventory/ \
D 359      -e "filter_tags=zap"
6769e3 360 ```
A 361
530a25 362 3. Head to <CLUSTER_URL> on OpenShift and move to your ci-cd project > builds. You should see `jenkins-slave-zap` has been built.
44d7bc 363 ![zap-build](../images/exercise4/zap-build.png) -->
6769e3 364
543f71 365 #### 3a - Arachni Scan
6769e3 366 > _Arachni is a feature-full, modular, high-performance Ruby framework aimed towards helping penetration testers and administrators evaluate the security of web applications._
e32e5c 367
543f71 368 1. To save time, a slave S2I image for Arachni scanner has already been built for you and pushed to the `openshift` namespace. Tag and label the image so that it is available for builds in the `<YOUR_NAME>-ci-cd` namespace.
e32e5c 369 ```bash
543f71 370 oc project <YOUR_NAME>-ci-cd
e32e5c 371 ```
543f71 372 ```bash
RS 373 oc tag openshift/jenkins-slave-arachni:latest jenkins-slave-arachni:latest
374 ```
375 ```bash
376 oc label is jenkins-slave-arachni role=jenkins-slave-arachni
377 ```
378 > NOTE: Windows users should run the `oc` commands in the `do500-toolbox` container.
6769e3 379
543f71 380 <!-- 3. Create an object in `inventory/host_vars/ci-cd-tooling.yml` called `jenkins-slave-arachni` with the following content:
054490 381 ```yaml
da9923 382     - name: "jenkins-slave-arachni"
b664dc 383       namespace: "{{ ci_cd_namespace }}"
D 384       template: "{{ playbook_dir }}/templates/jenkins-slave-generic-template.yml"
da9923 385       params: "{{ playbook_dir }}/params/jenkins-slave-arachni"
b664dc 386       tags:
D 387       - arachni
6769e3 388 ```
A 389
1173e5 390 3. Update the `jenkins-slave-arachni` files `SOURCE_REPOSITORY_URL` to point to your GitLab's hosted version of the `enablement-ci-cd` repo.
e32e5c 391 ```
530a25 392 SOURCE_REPOSITORY_URL=https://gitlab.<APPS_URL>/<GIT_USERNAME>/enablement-ci-cd.git
e32e5c 393 SOURCE_CONTEXT_DIR=docker/jenkins-slave-arachni
D 394 BUILDER_IMAGE_NAME=registry.access.redhat.com/openshift3/jenkins-slave-base-rhel7:latest
395 NAME=jenkins-slave-arachni
396 SOURCE_REPOSITORY_REF=master
397 ```
398
399 3. With these changes in place, push your changes to the `master` branch.
400 ```bash
fad576 401 git add .
D 402 ```
403 ```bash
404 git commit -m "ADD - Arachni scanning image"
405 ```
406 ```bash
407 git push
e32e5c 408 ```
D 409
1173e5 410 3. Run the Ansible playbook filtering with tag `arachni` so only the arachni build pods are run.
6769e3 411 ```bash
fad576 412 ansible-playbook apply.yml -e target=tools \
b664dc 413      -i inventory/ \
D 414      -e "filter_tags=arachni"
543f71 415 ``` -->
6769e3 416
543f71 417 2. Head to <CLUSTER_URL> on OpenShift and move to your ci-cd project `Builds > Images`. You should see the `jenkins-slave-arachni` image.
33c738 418 ![builds-zap-arachni](../images/exercise4/builds-zap-arachni.png)
43f2f2 419
D 420 _____
421
44d7bc 422 <!-- ## Extension Tasks
43f2f2 423 > _Ideas for go-getters. Advanced topic for doers to get on with if they finish early. These will usually not have a solution and are provided for additional scope._
e36a5b 424
D 425 Jenkins S2I
426  - Add the multi-branch configuration to the S2I to have Jenkins come alive with the `todolist-api` and `-fe` configuration cooked into it for future uses.
427
d608d6 428 Jenkins Pipeline Extension
e43fd2 429  - Add an extension to the pipeline that promotes code to the UAT environment once the master job has been successful.
1173e5 430  - Use a WAIT to allow for manual input to approve the promotion
d608d6 431
D 432 Jenkins e2e extension (blue/green)
db509f 433  - Add a step in the pipeline to only deploy to the `test` environment if the e2e tests have run successfully against which ever environment (blue or green) is not deployed.
43f2f2 434
D 435 ## Additional Reading
436 > List of links or other reading that might be of use / reference for the exercise
437
01c4da 438 ## Slide Links
RH 439
440 - [Intro](https://docs.google.com/presentation/d/1B3Fv4g66zZ8ZkqBq9TYmImJhUDvMecXCt4q3DXGWhjc/)
441 - [Wrap-up](https://docs.google.com/presentation/d/1EOk6y798Xh1hsaQlxRuqyr23FIIf7sNY4any_yXIL7A/)
44d7bc 442 - [All Material](https://drive.google.com/drive/folders/1oCjpl33Db7aPocmpu3NNF0B9czRvFq3m) -->