Ravi Srinivasan
2019-01-24 38f5f2bae7b05fadbe0819664e46b57332dc13d7
commit | author | age
74d1f1 1 # The Manual Menace
5e7a31 2 > In this exercise learners will use Ansible to drive automated provisioning of Projects in OpenShift, Git, Jenkins and Nexus.
0f4d08 3
69951c 4 <!-- ![automation-xkcd](https://imgs.xkcd.com/comics/automation.png) -->
9eed0b 5
D 6 ## Exercise Intro
853f0c 7 In this exercise we will use automation tooling to create Project namespaces for our `CI/CD` tooling along with the `dev` and `test` namespaces for our deployments to live. We do this manually using the OpenShift CLI; but as we go from cluster to cluster or project to project Dev and Ops teams often find themselves having to redo these tasks again and again. Configuring our cluster using code; we can easily store this in Git and repeat the process again and again. By minimising the time taken to do these repetitive tasks we can accelerate our ability to deliver value to our customers; working on the hard problems they face.
9eed0b 8
853f0c 9 This exercise uses Ansible to drive the creation of the cluster content. In particular; we'll use a play book called the `OpenShift Applier`. Once the project namespace have been created; we will add some tools to support CI/CD such as Jenkins, Git and Nexus. These tools will be needed by later lessons to automate the build and deploy of our apps. Again; we will use OpenShift Templates and drive their creation in the cluster using Ansible. To prove things are working, finally we'll delete all our content and re-apply the inventory to re-create our cluster's content.
74d1f1 10
5e7a31 11 #### Why is config-as-code important?
78b569 12 * Assurance - Prevents unwanted config changes from people making arbitrary changes to environments. No more Snowflake servers!
5e7a31 13 * Traceability - Committing config as code means a user has approved and changes can be tracked.
78b569 14 * Phoenix Server -  Burn it all to the ground and bring it back; exactly the way it was!
D 15
74d1f1 16 _____
0f4d08 17
D 18 ## Learning Outcomes
19 As a learner you will be able to
74d1f1 20
D 21 1. Run the OpenShift Applier to automate creating cluster content
22 1. Create and admin project namespaces in OpenShift
23 1. Deploy commonly used applications to support the development process
0f4d08 24
D 25 ## Tools and Frameworks
26
74d1f1 27 * [GitLab](https://about.gitlab.com/) - Community driven Git server now with integrated DevOps Toolchain.
D 28 * [Nexus](https://www.sonatype.com/nexus-repository-sonatype) - Repository manager for storing lots of application types. Can also host `npm` and `Docker` registries.
29 * [Jenkins](https://jenkins.io/) - OpenSource Build automation server. Highly customisable with plugins.
30 * [Ansible](https://www.ansible.com/) - IT Automation tool used to provision and manage state of cloud and physical infrastructure.
b4d469 31 * [OpenShift Applier](https://github.com/redhat-cop/openshift-applier) - used to apply OpenShift objects to an OpenShift Cluster.
A 32
74d1f1 33 ## Big Picture
5e7a31 34 > The Big Picture is our emerging architecture; starting with an empty cluster we populate it with projects and some ci/cd tooling.
74d1f1 35
1a8071 36 ![big-picture](../images/big-picture/big-picture-1.jpg)
74d1f1 37 _____
0f4d08 38
69951c 39 <!-- ## 10,000 Ft View
5e7a31 40 > This exercise is aimed at the creation of the tooling that will be used to support the rest of the Exercises. The high-level goal is to create a collection of project namespaces and populate them with Git, Jenkins & Nexus.
74d1f1 41
5e7a31 42 If you're feeling confident and don't want to follow the step-by-step guide these high-level instructions should provide a challenge for you:
74d1f1 43
949ccb 44 1. Clone the repo `https://github.com/rht-labs/enablement-ci-cd` which contains the scaffold of the project. Ensure you get all remote branches.
92099a 45
74d1f1 46 2. Create `<your-name>-ci-cd`, `<your-name>-dev` and `<your-name>-test` project namespaces using the inventory and run them with the OpenShift Applier to populate the cluster
e23af1 47
949ccb 48 3. Use the templates provided to create build of the jenkins-s2i. The templates are in `exercise1/jenkins-s2i`
92099a 49
949ccb 50 4. Use the templates provided to create build and deployment configs in `<your-name>-ci-cd` for. Templates are on a branch called `exercise1/git-nexus` && `exercise1/jenkins`:
74d1f1 51     * Nexus
D 52     * GitLab
5e7a31 53     * Jenkins (using an s2i to pre-configure Jenkins)
92099a 54
949ccb 55 5. Commit your `enablement-ci-cd` repository to the GitLab Instance you've created
92099a 56
949ccb 57 6. Burn it all down and re-apply your inventory proving config-as-code works.
69951c 58 -->
0f4d08 59
D 60 ## Step by Step Instructions
69951c 61 <!-- > This is a structured guide with references to exact filenames and explanations.  -->
0f4d08 62
bd7806 63 ### Part 1 - Create OpenShift Projects
d28811 64 > _Using the OpenShift Applier, we will add new project namespaces to the cluster which will be used throughout the exercise._
D 65
69951c 66 1. In this course three different git projects will be created. To setup your local machine for each of these, create a new folder on the terminal in the root of your HOME directory for convenience. To do this, open a new Terminal session and create the new folder using the following command (new terminal sessions will start in your HOME dir).
RS 67
68 For Linux and MacOS systems
bd7806 69 ```bash
69951c 70 mkdir -p ~/do500-workspace && cd ~/do500-workspace
RS 71 ```
72
73 For Microsoft Windows systems, navigate to the `C:\do500-workspace` directory
74 ```bash
75 cd C:\do500-workspace
2a3d5b 76 ```
784073 77 <p class="tip">
69951c 78 <b>NOTE</b> - If you do not want to have this folder at the root of your home directory, that's fine, just ensure any parent directories of this `do500-workspace` folder do <b>NOT</b> have any spaces in them as it breaks Ansible in later labs...
784073 79 </p>
D 80
69951c 81 2. Clone the scaffold project to your local machine's `do500-workspace` folder and pull all remote branches for use in later exercises. You may see an error saying `fatal: A branch named 'develop' already exists.` This error can be safely ignored.
RS 82
784073 83 ```bash
D 84 git clone https://github.com/rht-labs/enablement-ci-cd && cd enablement-ci-cd
2a3d5b 85 ```
784073 86 ```bash
D 87 ./git-pull-all.sh
69951c 88 ```
RS 89
90 If you are using a Microsoft Windows system, run the above shell script using the `Git Bash` terminal instead of the default Windows command line. You need to navigate to the `C:\do500-workspace\enablement-ci-cd` directory by running
91 ```bash
92 cd /c/do500-workspace/enablement-ci-cd
93 ```
94 ```bash
95 ./git-pull-all.sh
96 ```
97 ```bash
98 exit
0f4d08 99 ```
D 100
4a8826 101 3. Open the `enablement-ci-cd` folder in VSCode (or your favourite editor). The project is laid out as follows
bd7806 102 ```
D 103 .
104 ├── README.md
fd78e6 105 ├── apply.yml
bd7806 106 ├── docker
D 107 ├── inventory
fd78e6 108 │   ├── host_vars
D 109 │   │   ├── ci-cd-tooling.yml
110 │   │   └── projects-and-policies.yml
111 │   └── hosts
bd7806 112 ├── jenkins-s2i
D 113 ├── params
fd78e6 114 │   └── project-requests-ci-cd
bd7806 115 ├── requirements.yml
D 116 └── templates
fd78e6 117     └── project-requests.yml
bd7806 118 ```
69951c 119  * `docker` folder contains sample Dockerfiles for our jenkins-slave images that will be used by the builds.
bd7806 120  * `jenkins-s2i` contains the configuration and plugins we want to bring jenkins to life with
D 121  * `params` houses the variables we will load the templates with
122  * `templates` is a collection of OpenShift templates
fd78e6 123  * `inventory/host_vars/*.yml` is the collection of objects we want to insert into the cluster.
bd7806 124  * `requirements.yml` is a manifest which contains the ansible modules needed to run the playbook
fd78e6 125  * `apply.yml` is a playbook that sets up some variables and runs the OpenShift Applier role.
bd7806 126
69951c 127 4. Open the `apply.yml` file in the root of the project. Update the namespace variables by replacing the `<YOUR_NAME>` with your name or initials. Don't use uppercase or special characters. For example; my name is Dónal so I've created:
fd78e6 128 ```yaml
f49b0d 129   hosts: "{{ target }}"
fd78e6 130   vars:
D 131     ci_cd_namespace: donal-ci-cd
132     dev_namespace: donal-dev
133     test_namespace: donal-test
f49b0d 134   tasks:
fd78e6 135 ```
f49b0d 136 <p class="tip">
69951c 137 NOTE - YAML is indentation sensitive so keep things lined up properly!
f49b0d 138 </p>
fd78e6 139
69951c 140 5. Open the `inventory/host_vars/projects-and-policies.yml` file; you should see some variables setup already to create the `<YOUR_NAME>-ci-cd` namespace. This object is passed to the OpenShift Applier to call the `templates/project-requests.yml` template with the `params/project-requests-ci-cd` parameters. We will add some additional content here but first let's explore the parameters and the template
fd78e6 141
69951c 142 6. Open the `params/project-requests-ci-cd` and replace the `<YOUR_NAME>` with your name to create the corresponding projects in the cluster.
1c9328 143 ![new-item](../images/exercise1/ci-cd-project-namespace.png)
bd7806 144
69951c 145 7. Let's add two more params files to pass to our template to be able to create a `dev` and `test` project.
5e7a31 146   * Create another two params files `params/project-requests-dev` & `params/project-requests-test`. On the terminal run
e23af1 147 ```bash
784073 148 touch params/project-requests-dev params/project-requests-test
e23af1 149 ```
784073 150   * In your editor; Open `params/project-requests-dev` and add the following by substituting `<YOUR_NAME>` accordingly
fd78e6 151 ```
D 152 NAMESPACE=<YOUR_NAME>-dev
153 NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Dev
154 ```
784073 155   * In your editor; Open `params/project-requests-test` and add the following by substituting `<YOUR_NAME>` accordingly
fd78e6 156 ```
D 157 NAMESPACE=<YOUR_NAME>-test
158 NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Test
159 ```
bd7806 160
69951c 161 8. In the `inventory/host_vars/projects-and-policies.yml` file; add the new objects for the projects you want to create (dev & test) by adding another object to the content array for each. You can copy and paste them from the `ci-cd` example and update them accordingly. If you do this; remember to change the params file! e.g.
bd7806 162 ```yaml
fd78e6 163     - name: "{{ dev_namespace }}"
D 164       template: "{{ playbook_dir }}/templates/project-requests.yml"
1c9328 165       template_action: create
fd78e6 166       params: "{{ playbook_dir }}/params/project-requests-dev"
1c9328 167       tags:
D 168       - projects
fd78e6 169     - name: "{{ test_namespace }}"
D 170       template: "{{ playbook_dir }}/templates/project-requests.yml"
1c9328 171       template_action: create
fd78e6 172       params: "{{ playbook_dir }}/params/project-requests-test"
1c9328 173       tags:
D 174       - projects
bd7806 175 ```
1c9328 176 ![project-request-yaml](../images/exercise1/project-request-yml.png)
bd7806 177
69951c 178 For Microsoft Windows systems, you need to run Ansible and OpenShift client commands from inside the `do500-toolbox` container.
RS 179
180 <p class="tip">
181 NOTE - On Microsoft Windows systems, we recommend you keep the container running for the duration of the lab. Run all Ansible and OpenShift client ("oc") CLI commands from inside the container. Do NOT launch the container on Linux and MacOS systems, since you should already have Ansible and the OpenShift client natively installed on your system by following the pre-requisites setup guide.
182 </p>
183
184 9. Launch the toolbox container using the Windows command line terminal, and navigate to the `enablement-ci-cd` directory inside the container
185 ```bash
186 docker run -it -v C:/do500-workspace:/home/tool-box/workarea:Z quay.io/jrigsbee/do500-toolbox /bin/bash
187 bash-4.4$ cd workarea/enablement-ci-cd
188 ```
189
190 10. With the configuration in place; install the OpenShift Applier dependency
bd7806 191 ```bash
784073 192 ansible-galaxy install -r requirements.yml --roles-path=roles
bd7806 193 ```
D 194
69951c 195 11. Apply the inventory by logging into OpenShift on the terminal and running the playbook as follows (<CLUSTER_URL> should be replaced with the one you've been provided by the instructor). Accept any insecure connection warning 👍:
bd7806 196 ```bash
6c5da4 197 oc login <CLUSTER_URL>
784073 198 ```
D 199 ```bash
200 ansible-playbook apply.yml -i inventory/ -e target=bootstrap
fd78e6 201 ```
D 202 where the `-e target=bootstrap` is passing an additional variable specifying that we run the `bootstrap` inventory
bd7806 203
69951c 204 12. Once successful you should see an output similar to this (Cows not included): ![playbook-success](../images/exercise1/play-book-success.png)
bd7806 205
69951c 206 13. You can check to see the projects have been created successfully by running
f49b0d 207 ```bash
784073 208 oc projects
f49b0d 209 ```
D 210 ![project-success](../images/exercise1/project-success.png)
211
784073 212 ### Part 2 - Nexus
da55a5 213 > _Now that we have our Projects setup; we can start to populate them with Apps to be used in our dev lifecycle_
bd7806 214
69951c 215 1. In the `enablement-ci-cd` repo, checkout the templates for Nexus by running
da55a5 216 ```bash
784073 217 git checkout exercise1/git-nexus templates/nexus.yml
92099a 218 ```
11198f 219 The template contains all the things needed to setup a persistent nexus server, exposing a service and route while also creating the persistent volume needed. Have a read through the template; at the bottom you'll see a collection of parameters we will pass to the template.
92099a 220
69951c 221 2. Add some parameters for running the template by creating a new file in the `params` directory.
92099a 222 ```bash
784073 223 touch params/nexus
da55a5 224 ```
D 225
69951c 226 3. The essential params to include in this file are:
92099a 227 ```bash
D 228 VOLUME_CAPACITY=5Gi
4dac3c 229 MEMORY_LIMIT=1Gi
92099a 230 ```
D 231
a9efee 232 4. Create a new object in the inventory variables `inventory/host_vars/ci-cd-tooling.yml` called `ci-cd-tooling` and populate its `content` is as follows
fd78e6 233
92099a 234 ```yaml
fd78e6 235 ---
D 236 ansible_connection: local
237 openshift_cluster_content:
238 - object: ci-cd-tooling
239   content:
4c20f0 240   - name: "nexus"
D 241     namespace: "{{ ci_cd_namespace }}"
242     template: "{{ playbook_dir }}/templates/nexus.yml"
243     params: "{{ playbook_dir }}/params/nexus"
244     tags:
245     - nexus
92099a 246 ```
1c9328 247 ![ci-cd-deployments-yml](../images/exercise1/ci-cd-deployments-yml.png)
92099a 248
69951c 249 5. Run the OpenShift applier, specifying the tag `nexus` to speed up its execution (`-e target=tools` is to run the other inventory).
92099a 250 ```bash
784073 251 ansible-playbook apply.yml -e target=tools \
92099a 252      -i inventory/ \
1c9328 253      -e "filter_tags=nexus"
92099a 254 ```
D 255
69951c 256 6. Once successful; login to the cluster through the browser (using cluster URL) and navigate to the `<YOUR_NAME>-ci-cd`. You should see Nexus up and running. You can login with default credentials (admin / admin123) ![nexus-up-and-running](../images/exercise1/nexus-up-and-running.png)
92099a 257
784073 258 ### Part 3 - GitLab
D 259
69951c 260 <!-- #### 3a - GitLab install -->
fdaee0 261 <p class="tip">
69951c 262 NOTE - A Gitlab instance in the cloud has already been set up for you, please check with your instructor for the Gitlab instance URL.
fdaee0 263 </p>
D 264
69951c 265 <!-- 4. Now let's do the same thing for GitLab to get it up and running. Checkout the template and params provided by running
92099a 266 ```bash
784073 267 git checkout exercise1/git-nexus templates/gitlab.yml params/gitlab
5e7a31 268 ```
92099a 269 Explore the template; it contains the PVC, buildConfig and services. The DeploymentConfig is made up of these apps
D 270  - Redis (3.2.3)
271  - PostgreSQL (9.4)
272  - GitLab CE (v10.2.3)
273
3acbf0 274 4. Open the `params/gitlab` file and complete the following params
RH 275 <p class="tip">
276 Note - The values here for the LDAP and BIND credentials will be provided by your tutor.
277 </p>
92099a 278 ```
D 279 LDAP_BIND_DN=uid=<BIND_USER>,ou=People,dc=<YOUR_DOMAIN>,dc=com
280 LDAP_USER_FILTER=(memberof=CN=YourGroup,OU=Users,DC=<YOUR_DOMAIN>,DC=com)
281 LDAP_PASSWORD=<BIND_USER_PASSWORD>
282 LDAP_HOST=<LDAP_HOST>
283 LDAP_BASE=ou=People,dc=<YOUR_DOMAIN>,dc=com
284 LDAP_LABEL="<LDAP_DESCRIPTION>"
285 GITLAB_ROOT_PASSWORD=<GITLAB_ROOT_USER_PASSWORD>
286 GITLAB_DATA_VOL_SIZE=2Gi
287 POSTGRESQL_VOL_SIZE=1Gi
288 APPLICATION_HOSTNAME=<GITLAB_URL>
4feb7f 289 NAMESPACE=<YOUR_NAME>-ci-cd
92099a 290 ```
D 291 where the following need to be replaced by actual values:
292     * `<BIND_USER>` is the user used to query the LDAP
293     * `<BIND_USER_PASSWORD>` is the password used when querying the LDAP
294     * `<YOUR_DOMAIN>` is the domain the LDAP is hosted on
295     * `<LDAP_HOST>` is fqdn of the LDAP server
5e7a31 296     * `<LDAP_DESCRIPTION>` is the description to be used on the sign-in header for GitLab e.g. "Name LDAP Login"
CM 297     * `<GITLAB_ROOT_USER_PASSWORD>` is the root user for GOD access on the GitLab instance e.g. password123
92099a 298     * `<GITLAB_URL>` is the endpoint for gitlab. It will take the form `gitlab-<YOUR_NAME>-ci-cd.apps.<ENV_ID>.<YOUR_DOMAIN>.com`
D 299
fd78e6 300 4. Create another object in the inventory `inventory/host_vars/ci-cd-tooling.yml` file to run the build & deploy of this template. Add the following and update the `namespace:` accordingly
92099a 301 ```yaml
1c9328 302     - name: "gitlab"
fd78e6 303       namespace: "{{ ci_cd_namespace }}"
D 304       template: "{{ playbook_dir }}/templates/gitlab.yml"
305       params: "{{ playbook_dir }}/params/gitlab"
1c9328 306       tags:
D 307       - gitlab
92099a 308 ```
D 309
a9efee 310 4. Run the OpenShift applier, specifying the tag `gitlab` to speed up its execution.
92099a 311 ```bash
784073 312 ansible-playbook apply.yml -e target=tools \
92099a 313      -i inventory/ \
1c9328 314      -e "filter_tags=gitlab"
92099a 315 ```
D 316
69951c 317 4. Once successful; login to the cluster and navigate to the `<YOUR_NAME>-ci-cd`. You should see GitLab up and running. ![gitlab-up-and-running](../images/exercise1/gitlab-up-and-running.png) -->
784073 318
69951c 319 <!-- #### 3b - Commit CI/CD -->
4feb7f 320
69951c 321 1. Navigate to GitLab login page. You can login using your cluster credentials using the LDAP tab
1c9328 322 ![gitlab-ui](../images/exercise1/gitlab-ui.png)
4feb7f 323
69951c 324 2. Once logged in create a new project called `enablement-ci-cd` and mark it as internal. Once created; copy out the `git url` for use on the next step.
1c9328 325 ![gitlab-new-project](../images/exercise1/gitlab-new-project.png)
69951c 326 <!-- <p class="tip">
853f0c 327 Note - we would not normally make the project under your name but create a group and add the project there on residency but for simplicity of the exercise we'll do that here
69951c 328 </p> -->
1c9328 329
69951c 330 3. If you have not used Git before; you may need to tell Git who you are and what your email is before we commit. Run the following commands, substituting your email and "Your Name". If you've done this before move on to the next step. The last git config command is used to bypass SSL key verification for the GitLab server instance since we are using self-signed certificates on the sever.
RS 331
1c9328 332 ```bash
784073 333 git config --global user.email "yourname@mail.com"
1c9328 334 ```
784073 335 ```bash
D 336 git config --global user.name "Your Name"
69951c 337 ```
RS 338
339 ```bash
340 git config --global http.sslVerify false
784073 341 ```
D 342
5e7a31 343 4. Commit your local project to this new remote by first removing the existing origin (github) where the Ansible project was cloned from in the first steps. Remember to substitute `<GIT_URL>` accordingly with the one created for your `enablement-ci-cd` repository a moment ago.
784073 344 ```bash
D 345 git remote set-url origin <GIT_URL>
346 ```
347 ```bash
348 git add .
349 ```
350 ```bash
351 git commit -m "Adding git and nexus config"
352 ```
353 ```bash
354 git push -u origin --all
355 ```
356
69951c 357 ### Part 4 - MongoDB for CI tests
RS 358 > In order to run our API tests in CI in later labs; we need a MongoDB server instance available for executing our tests. As this is part of our CI/CD Lifecycle; we will add it now.
a9627c 359
69951c 360 1. In our `enablement-ci-cd` repo; checkout the mongo templates as shown below to bring in the template and params. 
RS 361 <!-- The mongodb template we're using is the same as the one for our `todolist-fe` created in previous exercise. -->
a9627c 362 ```bash
55ba17 363 git checkout exercise1/mongodb params/mongodb templates/mongodb.yml
a9627c 364 ```
D 365
69951c 366 2. Open `enablement-ci-cd` in your favourite editor. Edit the `inventory/host_vars/ci-cd-tooling.yml` to include a new object for our mongodb as shown below. This item can be added below the Jenkins slave in the `ci-cd-tooling` section.
a9627c 367 ```yaml
D 368   - name: "jenkins-mongodb"
369     namespace: "{{ ci_cd_namespace }}"
370     template: "{{ playbook_dir }}/templates/mongodb.yml"
371     params: "{{ playbook_dir }}/params/mongodb"
372     tags:
373     - mongodb
374 ```
55ba17 375 ![jenkins-mongo](../images/exercise1/jenkins-mongo.png)
a9627c 376
69951c 377 3. Git commit your updates to the inventory to git for traceability.
a9627c 378 ```bash
D 379 git add .
380 ```
381 ```bash
382 git commit -m "ADD - mongodb for use in the pipeline"
383 ```
384 ```bash
385 git push
386 ```
387
5e7a31 388 4. Apply this change as done previously using Ansible. The deployment can be validated by going to your `<YOUR_NAME>-ci-cd` namespace and checking if it is there!
a9627c 389 ```bash
D 390 ansible-playbook apply.yml -e target=tools \
391   -i inventory/ \
392   -e "filter_tags=mongodb"
393 ```
394 ![ocp-mongo](../images/exercise3/ocp-mongo.png)
395
69951c 396 <p class="tip">
RS 397 Note - When making changes to the "enablement-ci-cd" repo, you should frequently commit the changes to git.
398 </p>
bd7806 399
69951c 400 ### Part 5 - Jenkins & S2I
RS 401 > _Create a build and deployment config for Jenkins. Add new configuration and plugins to the OpenShift default Jenkins image using s2i
bd7806 402
69951c 403 1. Add the Jenkins Build & Deployment configs to the `enablement-ci-cd` repo by merging the contents from the `exercise1/jenkins` branch
1c9328 404 ```bash
784073 405 git checkout exercise1/jenkins templates/jenkins.yml
1c9328 406 ```
69951c 407 <!-- The Jenkins template is essentially the standard persistent Jenkins one with OpenShift. -->
1c9328 408
69951c 409 2. As before; create a new set of params by creating a `params/jenkins` file and adding some overrides to the template and updating the `<YOUR_NAME>` value accordingly.
a7a123 410 ```
4dac3c 411 MEMORY_LIMIT=3Gi
1adb94 412 VOLUME_CAPACITY=10Gi
1c9328 413 JVM_ARCH=x86_64
D 414 NAMESPACE=<YOUR_NAME>-ci-cd
415 JENKINS_OPTS=--sessionTimeout=720
416 ```
fd78e6 417
69951c 418 3. Add a `jenkins` variable to the Ansible inventory underneath the jenkins-mongo (and git if you have it) in  `inventory/host_vars/ci-cd-tooling.yml`.
1c9328 419 ```yaml
D 420     - name: "jenkins"
fd78e6 421       namespace: "{{ ci_cd_namespace }}"
D 422       template: "{{ playbook_dir }}/templates/jenkins.yml"
423       params: "{{ playbook_dir }}/params/jenkins"
1c9328 424       tags:
D 425       - jenkins
426 ```
11198f 427 This configuration, if applied now, will create the deployment configuration needed for Jenkins but the `${NAMESPACE}:${JENKINS_IMAGE_STREAM_TAG}` in the template won't exist yet.
1c9328 428
69951c 429 4. To create this image we will take the supported OpenShift Jenkins Image and bake into it some extra configuration using an [s2i](https://github.com/openshift/source-to-image) builder image. More information on Jenkins s2i is found on the [openshift/jenkins](https://github.com/openshift/jenkins#installing-using-s2i-build) GitHub page. To create an s2i configuration for Jenkins, check out the pre-canned configuration source in the `enablement-ci-cd` repo
1c9328 430 ```bash
784073 431 git checkout exercise1/jenkins-s2i jenkins-s2i
1c9328 432 ```
5e7a31 433 The structure of the Jenkins s2i config is
1c9328 434 ```
D 435 jenkins-s2i
436 ├── README.md
437 ├── configuration
38f5f2 438 │   ├── build-failure-analyzer.xml
RS 439 │   ├── init.groovy
440 │   ├── jenkins.plugins.slack.SlackNotifier.xml
441 │   ├── scriptApproval.xml
442 │   └── jobs
443 │       └── seed-multibranch-job
444 │           └── config.xml
1c9328 445 └── plugins.txt
D 446 ```
447  * `plugins.txt` is a list of `pluginId:version` for Jenkins to pre-install when starting
448  * `./configuration` contains content that is placed in `${JENKINS_HOME}`. A `config.xml` could be placed in here to control the bulk of Jenkins configuration.
449  * `./configuration/jobs/*` contains job names and xml config that jenkins loads when starting. The seed job in there we will return to in later lessons.
d28811 450  * `build-failure-analyzer.xml` is config for the plugin to read the logs and look for key items based on a Regex. More on this in later lessons.
1c9328 451  * `init.groovy` contains a collection of settings jenkins configures itself with when launching
D 452
5e7a31 453 5. Let's add a plugin for Jenkins to be started with, [green-balls](https://plugins.jenkins.io/greenballs). This simply changes the default `SUCCESS` status of Jenkins from Blue to Green. Append the `jenkins-s2i/plugins.txt` file with
1c9328 454 ```txt
D 455 greenballs:1.15
5e7a31 456 ```
1c9328 457 ![green-balls.png](../images/exercise1/green-balls.png)
D 458
69951c 459 <!-- Why does Jenkins use blue to represent success? More can be found [on reddit](https://www.reddit.com/r/programming/comments/4lu6q8/why_does_jenkins_have_blue_balls/) or the [Jenkins blog](https://jenkins.io/blog/2012/03/13/why-does-jenkins-have-blue-balls/). -->
RS 460
461 6. Before building and deploying the Jenkins s2i; add your git credentials to it. These will be used by Jenkins to access the Git Repositories where our apps will be stored. We want Jenkins to be able to push tags to it, so write access is required. 
462
463 There are a few ways we can do this; either adding them to the `template/jenkins.yml` as environment variables and then including them in the `params/jenkins` file.  We could also create a token in GitLab and use it as the source secret in the Jenkins template.
464
465 For the sake of simplicity, just replace the `<USERNAME>` && `<PASSWORD>` in the `jenkins-s2i/configuration/init.groovy` with your LDAP credentials as seen below. This init file gets run when Jenkins launches, and will setup the credentials for use in our Jobs in the next exercises
1c9328 466 ```groovy
D 467 gitUsername = System.getenv("GIT_USERNAME") ?: "<USERNAME>"
468 gitPassword = System.getenv("GIT_PASSWORD") ?: "<PASSWORD>"
469 ```
69951c 470 <!-- <p class="tip">
5e7a31 471 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, a service user would be created for this.
69951c 472 </p> -->
1c9328 473
69951c 474 7. Checkout the params and the templates for the `jenkins-s2i`
a7a123 475 ```bash
784073 476 git checkout exercise1/jenkins-s2i params/jenkins-s2i templates/jenkins-s2i.yml
a7a123 477 ```
D 478
69951c 479 8. Open `params/jenkins-s2i` and add the following content; replacing variables as appropriate.
1c9328 480 ```
e23af1 481 SOURCE_REPOSITORY_URL=<GIT_URL>
1c9328 482 NAME=jenkins
D 483 SOURCE_REPOSITORY_CONTEXT_DIR=jenkins-s2i
484 IMAGE_STREAM_NAMESPACE=<YOUR_NAME>-ci-cd
e23af1 485 SOURCE_REPOSITORY_USERNAME=<YOUR_LDAP_USERNAME>
D 486 SOURCE_REPOSITORY_PASSWORD=<YOUR_LDAP_PASSWORD>
1c9328 487 ```
5e7a31 488 where
853f0c 489     * `<GIT_URL>` is the full clone path of the repo where this project is stored (including the https && .git)
d28811 490     * `<YOUR_NAME>` is the prefix for your `-ci-cd` project.
D 491     * Explore some of the other parameters in `templates/jenkins-s2i.yml`
e23af1 492     * `<YOUR_LDAP_USERNAME>` is the username builder pod will use to login and clone the repo with
D 493     * `<YOUR_LDAP_PASSWORD>` is the password the builder pod will use to authenticate and clone the repo using
69951c 494 <!-- <p class="tip">
e23af1 495 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, A service user would be created or a token generated.
69951c 496 </p> -->
1c9328 497
69951c 498 9. Create a new object `ci-cd-builds` in the Ansible `inventory/host_vars/ci-cd-tooling.yml` to drive the s2i build configuration.
1c9328 499 ```yaml
D 500   - object: ci-cd-builds
501     content:
502     - name: "jenkins-s2i"
fd78e6 503       namespace: "{{ ci_cd_namespace }}"
D 504       template: "{{ playbook_dir }}/templates/jenkins-s2i.yml"
505       params: "{{ playbook_dir }}/params/jenkins-s2i"
1c9328 506       tags:
D 507       - jenkins
508 ```
509
69951c 510 10. Commit your code to your GitLab instance
1c9328 511 ```bash
784073 512 git add .
D 513 ```
514 ```bash
515 git commit -m "Adding Jenkins and Jenkins s2i"
516 ```
517 ```bash
518 git push
1c9328 519 ```
D 520
69951c 521 11.  In order for Jenkins to be able to run `npm` builds and installs we must configure a `jenkins-build-slave` for Jenkins to use. This slave will be dynamically provisioned when we run a build. It needs to have NodeJS and npm installed in it. These slaves can take a time to build themselves so to speed up we have placed the slave within OpenShift and you can use the following commands to be able to use them in your project.
350001 522 ```bash
D 523 oc project <YOUR_NAME>-ci-cd
524 ```
3437ff 525 ```bash
T 526 oc tag openshift/jenkins-slave-npm:latest jenkins-slave-npm:latest
527 ```
528 ```bash
529 oc label is jenkins-slave-npm role=jenkins-slave
530 ```
350001 531 This is pulling the container image into your namespace and then adding a label which will allow Jenkins to take notice of it. Don't worry if the label is already there and this last command fails!
3437ff 532
69951c 533 12. Now your code is commited, and you have bought in the Jenkins slave; run the OpenShift Applier to add the config to the cluster
1c9328 534 ```bash
784073 535 ansible-playbook apply.yml -e target=tools \
1c9328 536      -i inventory/ \
D 537      -e "filter_tags=jenkins"
538 ```
539
69951c 540 13. This will trigger a build of the s2i and when it's complete it will add an imagestream of `<YOUR_NAME>-ci-cd/jenkins:latest` to the project. The Deployment config should kick in and deploy the image once it arrives. You can follow the build of the s2i by going to the OpenShift console's project
d28811 541 ![jenkins-s2i-log](../images/exercise1/jenkins-s2i-log.png)
bd7806 542
69951c 543 14. When the Jenkins deployment has completed; login (using your OpenShift credentials) and accept the role permissions. You should now see a fairly empty Jenkins with just the seed job
92099a 544
5e7a31 545 ### Part 6 - Jenkins Hello World
69951c 546 > _To test things are working end-to-end; create a hello world job that doesn't do much but proves we can pull code from git and that our builds are green._
d28811 547
69951c 548 1. Log in to Jenkins and hit `New Item` ![new-item](../images/exercise1/new-item.png).
d28811 549
69951c 550 2. Create a freestyle job called `hello-world` ![jenkins-new-hello-world](../images/exercise1/jenkins-new-hello-world.png).
d28811 551
69951c 552 3. On the Source Code Management tab; add your `enablement-ci-cd` git repo and hit the dropdown to add your credentials we baked into the s2i on previous steps ![jenkins-scm-git](../images/exercise1/jenkins-scm-git.png)
d28811 553
69951c 554 4. On the build tab add an Execute Shell step and fill it with `echo "Hello World"` ![jenkins-hello-world](../images/exercise1/jenkins-hello-world.png).
d28811 555
69951c 556 5. Run the build and we should see it pass successfully and with a Green ball! ![jenkins-green-balls](../images/exercise1/jenkins-green-balls.png)
d28811 557
e41c20 558 ### Part 7 - Live, Die, Repeat
5e7a31 559 > _In this section you will prove the infra as code is working by deleting your Cluster Content and recreating it all_
d28811 560
69951c 561 1. Commit your code to the new repo in GitLab
9eed0b 562 ```bash
784073 563 git add .
D 564 ```
565 ```bash
566 git commit -m "ADD - all ci/cd contents"
567 ```
568 ```bash
569 git push
9eed0b 570 ```
d28811 571
69951c 572 2. Burn your OpenShift project resources to the ground
9eed0b 573 ```bash
784073 574 oc delete project <YOUR_NAME>-ci-cd
D 575 ```
576 ```bash
577 oc delete project <YOUR_NAME>-dev
578 ```
579 ```bash
580 oc delete project <YOUR_NAME>-test
9eed0b 581 ```
d28811 582
69951c 583 3. Check to see the projects that were marked for deletion are removed.
e23af1 584 ```bash
784073 585 oc get projects | egrep '<YOUR_NAME>-ci-cd|<YOUR_NAME>-dev|<YOUR_NAME>-test'
e23af1 586 ```
D 587
69951c 588 4. Re-apply the inventory to re-create it all!
9eed0b 589 ```bash
6c5da4 590 oc login <CLUSTER_URL>
784073 591 ```
D 592 ```bash
593 ansible-playbook apply.yml -i inventory/ -e target=bootstrap
594 ```
595 ```bash
596 ansible-playbook apply.yml -i inventory/ -e target=tools
9eed0b 597 ```
0f4d08 598
74d1f1 599 _____
D 600
69951c 601 <!-- ## Extension Tasks
d28811 602 > _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._
0f4d08 603
a9627c 604  - Install Cowsay for 100% more Ansible Fun!
92099a 605  - Add more secure access for Nexus (ie not admin / admin123) using the automation to drive secret creation
1c9328 606  - Add a SonarQube persistent deployment to the `ci-cd-deployments` section.
69951c 607  - Add `jenkins.plugins.slack.SlackNotifier.xml` to `jenkins-s2i/configuration` to include URL of Slack for team build notifications and rebuild Jenkins s2i
0f4d08 608
69951c 609 _____ -->
74d1f1 610
26420c 611 <!-- ## Additional Reading
69951c 612 > List of links and other reading material that might be of use for the exercise
4f0295 613
RH 614 ## Slide links
615
69951c 616 - TBD
RS 617 - TBD
26420c 618 - TBD -->
69951c 619
RS 620 <!-- - [Intro](https://docs.google.com/presentation/d/1LsfAkH8GfIhulEoy_yd-usWBfDHnZEyQdNvYeTmAg4A/)
4f0295 621 - [Wrap-up](https://docs.google.com/presentation/d/1cfyJ6SHddZNbM61oz67r870rLYVKY335zGclXN2uLMY/)
38f5f2 622 - [All Material](https://drive.google.com/drive/folders/13Bt4BXf9P2OB8VI4YQNcNONF1786dqOx) -->