Ryan DeBeasi
2018-08-08 4a882638de03f149e0960482db37706f82de3da4
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
9eed0b 4 ![automation-xkcd](https://imgs.xkcd.com/comics/automation.png)
D 5
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)
b62fab 37
74d1f1 38 _____
0f4d08 39
D 40 ## 10,000 Ft View
5e7a31 41 > 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 42
5e7a31 43 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 44
949ccb 45 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 46
74d1f1 47 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 48
949ccb 49 3. Use the templates provided to create build of the jenkins-s2i. The templates are in `exercise1/jenkins-s2i`
92099a 50
949ccb 51 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 52     * Nexus
D 53     * GitLab
5e7a31 54     * Jenkins (using an s2i to pre-configure Jenkins)
92099a 55
949ccb 56 5. Commit your `enablement-ci-cd` repository to the GitLab Instance you've created
92099a 57
949ccb 58 6. Burn it all down and re-apply your inventory proving config-as-code works.
0f4d08 59
D 60 ## Step by Step Instructions
bd7806 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
45eb81 66 3. 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).
bd7806 67 ```bash
45eb81 68 mkdir -p ~/innovation-labs && cd ~/innovation-labs
2a3d5b 69 ```
784073 70 <p class="tip">
D 71 NOTE - If you do not want to have this folder at the root of your home dir that's fine, just ensure any parent directories of this `innovation-labs` folder do NOT have any spaces in them as it breaks Ansible in later labs...
72 </p>
73
74 3. Clone the scaffold project to your local machine's `innovation-labs` folder and pull all remote branches for use in later exercises. Note - this may error saying `fatal: A branch named 'develop' already exists.` but it can be ignored
75 ```bash
76 git clone https://github.com/rht-labs/enablement-ci-cd && cd enablement-ci-cd
2a3d5b 77 ```
784073 78 ```bash
D 79 ./git-pull-all.sh
0f4d08 80 ```
D 81
4a8826 82 3. Open the `enablement-ci-cd` folder in VSCode (or your favourite editor). The project is laid out as follows
bd7806 83 ```
D 84 .
85 ├── README.md
fd78e6 86 ├── apply.yml
bd7806 87 ├── docker
D 88 ├── inventory
fd78e6 89 │   ├── host_vars
D 90 │   │   ├── ci-cd-tooling.yml
91 │   │   └── projects-and-policies.yml
92 │   └── hosts
bd7806 93 ├── jenkins-s2i
D 94 ├── params
fd78e6 95 │   └── project-requests-ci-cd
bd7806 96 ├── requirements.yml
D 97 └── templates
fd78e6 98     └── project-requests.yml
bd7806 99 ```
D 100  * `docker` folder contains our jenkins-slave images that will be used by the builds.
101  * `jenkins-s2i` contains the configuration and plugins we want to bring jenkins to life with
102  * `params` houses the variables we will load the templates with
103  * `templates` is a collection of OpenShift templates
fd78e6 104  * `inventory/host_vars/*.yml` is the collection of objects we want to insert into the cluster.
bd7806 105  * `requirements.yml` is a manifest which contains the ansible modules needed to run the playbook
fd78e6 106  * `apply.yml` is a playbook that sets up some variables and runs the OpenShift Applier role.
bd7806 107
5e7a31 108 3. 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 109 ```yaml
f49b0d 110   hosts: "{{ target }}"
fd78e6 111   vars:
D 112     ci_cd_namespace: donal-ci-cd
113     dev_namespace: donal-dev
114     test_namespace: donal-test
f49b0d 115   tasks:
fd78e6 116 ```
f49b0d 117 <p class="tip">
D 118 NOTE - yaml is indentation sensitive so keep things lined up properly!
119 </p>
fd78e6 120
D 121 3. 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
122
5e7a31 123 3. Open the `params/project-requests-ci-cd` and replace the `<YOUR_NAME>` with your name to create the corresponding projects in the cluster.
1c9328 124 ![new-item](../images/exercise1/ci-cd-project-namespace.png)
bd7806 125
5e7a31 126 3. Let's add two more params files to pass to our template to be able to create a `dev` and `test` project.
CM 127   * Create another two params files `params/project-requests-dev` & `params/project-requests-test`. On the terminal run
e23af1 128 ```bash
784073 129 touch params/project-requests-dev params/project-requests-test
e23af1 130 ```
784073 131   * In your editor; Open `params/project-requests-dev` and add the following by substituting `<YOUR_NAME>` accordingly
fd78e6 132 ```
D 133 NAMESPACE=<YOUR_NAME>-dev
134 NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Dev
135 ```
784073 136   * In your editor; Open `params/project-requests-test` and add the following by substituting `<YOUR_NAME>` accordingly
fd78e6 137 ```
D 138 NAMESPACE=<YOUR_NAME>-test
139 NAMESPACE_DISPLAY_NAME=<YOUR-NAME> Test
140 ```
bd7806 141
fd78e6 142 3. 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 143 ```yaml
fd78e6 144     - name: "{{ dev_namespace }}"
D 145       template: "{{ playbook_dir }}/templates/project-requests.yml"
1c9328 146       template_action: create
fd78e6 147       params: "{{ playbook_dir }}/params/project-requests-dev"
1c9328 148       tags:
D 149       - projects
fd78e6 150     - name: "{{ test_namespace }}"
D 151       template: "{{ playbook_dir }}/templates/project-requests.yml"
1c9328 152       template_action: create
fd78e6 153       params: "{{ playbook_dir }}/params/project-requests-test"
1c9328 154       tags:
D 155       - projects
bd7806 156 ```
1c9328 157 ![project-request-yaml](../images/exercise1/project-request-yml.png)
bd7806 158
D 159 3. With the configuration in place; install the OpenShift Applier dependency
160 ```bash
784073 161 ansible-galaxy install -r requirements.yml --roles-path=roles
bd7806 162 ```
D 163
5e7a31 164 3. 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 sent as shown below). Accept any insecure connection warning 👍:
bd7806 165 ```bash
a9627c 166 oc login https://console.lader.rht-labs.com
784073 167 ```
D 168 ```bash
169 ansible-playbook apply.yml -i inventory/ -e target=bootstrap
fd78e6 170 ```
D 171 where the `-e target=bootstrap` is passing an additional variable specifying that we run the `bootstrap` inventory
bd7806 172
853f0c 173 3. Once successful you should see an output similar to this (Cows not included): ![playbook-success](../images/exercise1/play-book-success.png)
bd7806 174
5e7a31 175 3. You can check to see the projects have been created successfully by running
f49b0d 176 ```bash
784073 177 oc projects
f49b0d 178 ```
D 179 ![project-success](../images/exercise1/project-success.png)
180
784073 181 ### Part 2 - Nexus
da55a5 182 > _Now that we have our Projects setup; we can start to populate them with Apps to be used in our dev lifecycle_
bd7806 183
92099a 184 4. In the `enablement-ci-cd` repo, checkout the templates for Nexus by running
da55a5 185 ```bash
784073 186 git checkout exercise1/git-nexus templates/nexus.yml
92099a 187 ```
11198f 188 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 189
5e7a31 190 4. Add some parameters for running the template by creating a new file in the `params` directory.
92099a 191 ```bash
784073 192 touch params/nexus
da55a5 193 ```
D 194
8fc7f6 195 4. The essential params to include in this file are:
92099a 196 ```bash
D 197 VOLUME_CAPACITY=5Gi
4dac3c 198 MEMORY_LIMIT=1Gi
92099a 199 ```
D 200
a9efee 201 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 202
92099a 203 ```yaml
fd78e6 204 ---
D 205 ansible_connection: local
206 openshift_cluster_content:
207 - object: ci-cd-tooling
208   content:
4c20f0 209   - name: "nexus"
D 210     namespace: "{{ ci_cd_namespace }}"
211     template: "{{ playbook_dir }}/templates/nexus.yml"
212     params: "{{ playbook_dir }}/params/nexus"
213     tags:
214     - nexus
92099a 215 ```
1c9328 216 ![ci-cd-deployments-yml](../images/exercise1/ci-cd-deployments-yml.png)
92099a 217
a9efee 218 4. Run the OpenShift applier, specifying the tag `nexus` to speed up its execution (`-e target=tools` is to run the other inventory).
92099a 219 ```bash
784073 220 ansible-playbook apply.yml -e target=tools \
92099a 221      -i inventory/ \
1c9328 222      -e "filter_tags=nexus"
92099a 223 ```
D 224
3acbf0 225 4. 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 226
784073 227 ### Part 3 - GitLab
D 228
5e7a31 229 #### 3a - GitLab install
fdaee0 230 <p class="tip">
784073 231 NOTE - This section may already have been completed for you, please check with your tutor. If this is the case, skip to section 3b "Commit CI/CD" below to add your code to GitLab.
fdaee0 232 </p>
D 233
11198f 234 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 235 ```bash
784073 236 git checkout exercise1/git-nexus templates/gitlab.yml params/gitlab
5e7a31 237 ```
92099a 238 Explore the template; it contains the PVC, buildConfig and services. The DeploymentConfig is made up of these apps
D 239  - Redis (3.2.3)
240  - PostgreSQL (9.4)
241  - GitLab CE (v10.2.3)
242
3acbf0 243 4. Open the `params/gitlab` file and complete the following params
RH 244 <p class="tip">
245 Note - The values here for the LDAP and BIND credentials will be provided by your tutor.
246 </p>
92099a 247 ```
D 248 LDAP_BIND_DN=uid=<BIND_USER>,ou=People,dc=<YOUR_DOMAIN>,dc=com
249 LDAP_USER_FILTER=(memberof=CN=YourGroup,OU=Users,DC=<YOUR_DOMAIN>,DC=com)
250 LDAP_PASSWORD=<BIND_USER_PASSWORD>
251 LDAP_HOST=<LDAP_HOST>
252 LDAP_BASE=ou=People,dc=<YOUR_DOMAIN>,dc=com
253 LDAP_LABEL="<LDAP_DESCRIPTION>"
254 GITLAB_ROOT_PASSWORD=<GITLAB_ROOT_USER_PASSWORD>
255 GITLAB_DATA_VOL_SIZE=2Gi
256 POSTGRESQL_VOL_SIZE=1Gi
257 APPLICATION_HOSTNAME=<GITLAB_URL>
4feb7f 258 NAMESPACE=<YOUR_NAME>-ci-cd
92099a 259 ```
D 260 where the following need to be replaced by actual values:
261     * `<BIND_USER>` is the user used to query the LDAP
262     * `<BIND_USER_PASSWORD>` is the password used when querying the LDAP
263     * `<YOUR_DOMAIN>` is the domain the LDAP is hosted on
264     * `<LDAP_HOST>` is fqdn of the LDAP server
5e7a31 265     * `<LDAP_DESCRIPTION>` is the description to be used on the sign-in header for GitLab e.g. "Name LDAP Login"
CM 266     * `<GITLAB_ROOT_USER_PASSWORD>` is the root user for GOD access on the GitLab instance e.g. password123
92099a 267     * `<GITLAB_URL>` is the endpoint for gitlab. It will take the form `gitlab-<YOUR_NAME>-ci-cd.apps.<ENV_ID>.<YOUR_DOMAIN>.com`
D 268
fd78e6 269 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 270 ```yaml
1c9328 271     - name: "gitlab"
fd78e6 272       namespace: "{{ ci_cd_namespace }}"
D 273       template: "{{ playbook_dir }}/templates/gitlab.yml"
274       params: "{{ playbook_dir }}/params/gitlab"
1c9328 275       tags:
D 276       - gitlab
92099a 277 ```
D 278
a9efee 279 4. Run the OpenShift applier, specifying the tag `gitlab` to speed up its execution.
92099a 280 ```bash
784073 281 ansible-playbook apply.yml -e target=tools \
92099a 282      -i inventory/ \
1c9328 283      -e "filter_tags=gitlab"
92099a 284 ```
D 285
1c9328 286 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 287
D 288 #### 3b - Commit CI/CD
4feb7f 289
5e7a31 290 4. Navigate to GitLab (if you have just skipped straight to this step; ask your tutor for the URL). You can login using your cluster credentials using the LDAP tab
1c9328 291 ![gitlab-ui](../images/exercise1/gitlab-ui.png)
4feb7f 292
4c20f0 293 4. 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 294 ![gitlab-new-project](../images/exercise1/gitlab-new-project.png)
D 295 <p class="tip">
853f0c 296 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
1c9328 297 </p>
D 298
853f0c 299 4. 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.
1c9328 300 ```bash
784073 301 git config --global user.email "yourname@mail.com"
1c9328 302 ```
784073 303 ```bash
D 304 git config --global user.name "Your Name"
305 ```
306
5e7a31 307 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 308 ```bash
D 309 git remote set-url origin <GIT_URL>
310 ```
311 ```bash
312 git add .
313 ```
314 ```bash
315 git commit -m "Adding git and nexus config"
316 ```
317 ```bash
318 git push -u origin --all
319 ```
320
e41c20 321 ### Part 4 MongoDB for CI tests
a9627c 322 > In order to run our API tests in CI in later labs; we need there to be a MongoDB available for executing our tests. As this is part of our CI/CD Lifecycle; we will add it now.
D 323
324 4. In our `enablement-ci-cd` repo; checkout the mongo templates as shown below to bring in the template and params. The mongodb template we're using is the same as the one for our `todolist-fe` created in previous exercise.
325 ```bash
55ba17 326 git checkout exercise1/mongodb params/mongodb templates/mongodb.yml
a9627c 327 ```
D 328
5e7a31 329 4. 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 330 ```yaml
D 331   - name: "jenkins-mongodb"
332     namespace: "{{ ci_cd_namespace }}"
333     template: "{{ playbook_dir }}/templates/mongodb.yml"
334     params: "{{ playbook_dir }}/params/mongodb"
335     tags:
336     - mongodb
337 ```
55ba17 338 ![jenkins-mongo](../images/exercise1/jenkins-mongo.png)
a9627c 339
D 340 4. Git commit your updates to the inventory to git for traceability.
341 ```bash
342 git add .
343 ```
344 ```bash
345 git commit -m "ADD - mongodb for use in the pipeline"
346 ```
347 ```bash
348 git push
349 ```
350
5e7a31 351 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 352 ```bash
D 353 ansible-playbook apply.yml -e target=tools \
354   -i inventory/ \
355   -e "filter_tags=mongodb"
356 ```
357 ![ocp-mongo](../images/exercise3/ocp-mongo.png)
358
5cf97a 359 **Note - When making changes to enablement-ci-cd you should frequently commit the changes to git.**
bd7806 360
e41c20 361 ### Part 5 - Jenkins & s2i
d28811 362 > _Create a build and deployment config for Jenkins. Add new configuration and plugins to the OCP Stock Jenkins using s2i_
bd7806 363
1c9328 364 5. Add the Jenkins Build & Deployment configs to the `enablement-ci-cd` repo by merging the contents `exercise1/jenkins` in
D 365 ```bash
784073 366 git checkout exercise1/jenkins templates/jenkins.yml
1c9328 367 ```
5e7a31 368 The Jenkins template is essentially the standard persistent Jenkins one with OpenShift.
1c9328 369
a7a123 370 5. 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.
D 371 ```
4dac3c 372 MEMORY_LIMIT=3Gi
1adb94 373 VOLUME_CAPACITY=10Gi
1c9328 374 JVM_ARCH=x86_64
D 375 NAMESPACE=<YOUR_NAME>-ci-cd
376 JENKINS_OPTS=--sessionTimeout=720
377 ```
fd78e6 378
5e7a31 379 5. 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 380 ```yaml
D 381     - name: "jenkins"
fd78e6 382       namespace: "{{ ci_cd_namespace }}"
D 383       template: "{{ playbook_dir }}/templates/jenkins.yml"
384       params: "{{ playbook_dir }}/params/jenkins"
1c9328 385       tags:
D 386       - jenkins
387 ```
11198f 388 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 389
5e7a31 390 5. 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 391 ```bash
784073 392 git checkout exercise1/jenkins-s2i jenkins-s2i
1c9328 393 ```
5e7a31 394 The structure of the Jenkins s2i config is
1c9328 395 ```
D 396 jenkins-s2i
397 ├── README.md
398 ├── configuration
399 │   ├── build-failure-analyzer.xml
400 │   ├── init.groovy
401 │   ├── jenkins.plugins.slack.SlackNotifier.xml
a7a123 402 │   ├── scriptApproval.xml
1c9328 403 │   └── jobs
D 404 │       └── seed-multibranch-job
405 │           └── config.xml
406 └── plugins.txt
407 ```
408  * `plugins.txt` is a list of `pluginId:version` for Jenkins to pre-install when starting
409  * `./configuration` contains content that is placed in `${JENKINS_HOME}`. A `config.xml` could be placed in here to control the bulk of Jenkins configuration.
410  * `./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 411  * `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 412  * `init.groovy` contains a collection of settings jenkins configures itself with when launching
D 413
5e7a31 414 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 415 ```txt
D 416 greenballs:1.15
5e7a31 417 ```
1c9328 418 ![green-balls.png](../images/exercise1/green-balls.png)
D 419 Why does Jenkins have Blue Balls? 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/)
420
5e7a31 421 5. Before building and deploying the Jenkins s2i; add 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. 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.
CM 422 But for 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 423 ```groovy
D 424 gitUsername = System.getenv("GIT_USERNAME") ?: "<USERNAME>"
425 gitPassword = System.getenv("GIT_PASSWORD") ?: "<PASSWORD>"
426 ```
a7a123 427 <p class="tip">
5e7a31 428 Note in a residency we would not use your GitCredentials for pushing and pulling from Git, a service user would be created for this.
a7a123 429 </p>
1c9328 430
afef19 431 5. Checkout the params and the templates for the `jenkins-s2i`
a7a123 432 ```bash
784073 433 git checkout exercise1/jenkins-s2i params/jenkins-s2i templates/jenkins-s2i.yml
a7a123 434 ```
D 435
5e7a31 436 5. Open `params/jenkins-s2i` and add the following content; replacing variables as appropriate.
1c9328 437 ```
e23af1 438 SOURCE_REPOSITORY_URL=<GIT_URL>
1c9328 439 NAME=jenkins
D 440 SOURCE_REPOSITORY_CONTEXT_DIR=jenkins-s2i
441 IMAGE_STREAM_NAMESPACE=<YOUR_NAME>-ci-cd
e23af1 442 SOURCE_REPOSITORY_USERNAME=<YOUR_LDAP_USERNAME>
D 443 SOURCE_REPOSITORY_PASSWORD=<YOUR_LDAP_PASSWORD>
1c9328 444 ```
5e7a31 445 where
853f0c 446     * `<GIT_URL>` is the full clone path of the repo where this project is stored (including the https && .git)
d28811 447     * `<YOUR_NAME>` is the prefix for your `-ci-cd` project.
D 448     * Explore some of the other parameters in `templates/jenkins-s2i.yml`
e23af1 449     * `<YOUR_LDAP_USERNAME>` is the username builder pod will use to login and clone the repo with
D 450     * `<YOUR_LDAP_PASSWORD>` is the password the builder pod will use to authenticate and clone the repo using
d28811 451 <p class="tip">
e23af1 452 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.
d28811 453 </p>
1c9328 454
5e7a31 455 5. Create a new object `ci-cd-builds` in the Ansible `inventory/host_vars/ci-cd-tooling.yml` to drive the s2i build configuration.
1c9328 456 ```yaml
D 457   - object: ci-cd-builds
458     content:
459     - name: "jenkins-s2i"
fd78e6 460       namespace: "{{ ci_cd_namespace }}"
D 461       template: "{{ playbook_dir }}/templates/jenkins-s2i.yml"
462       params: "{{ playbook_dir }}/params/jenkins-s2i"
1c9328 463       tags:
D 464       - jenkins
465 ```
466
467 5. Commit your code to your GitLab instance
468 ```bash
784073 469 git add .
D 470 ```
471 ```bash
472 git commit -m "Adding Jenkins and Jenkins s2i"
473 ```
474 ```bash
475 git push
1c9328 476 ```
D 477
5e7a31 478 5.  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 479 ```bash
D 480 oc project <YOUR_NAME>-ci-cd
481 ```
3437ff 482 ```bash
T 483 oc tag openshift/jenkins-slave-npm:latest jenkins-slave-npm:latest
484 ```
485 ```bash
486 oc label is jenkins-slave-npm role=jenkins-slave
487 ```
350001 488 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 489
T 490 5. 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 491 ```bash
784073 492 ansible-playbook apply.yml -e target=tools \
1c9328 493      -i inventory/ \
D 494      -e "filter_tags=jenkins"
495 ```
496
d28811 497 5. 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
D 498 ![jenkins-s2i-log](../images/exercise1/jenkins-s2i-log.png)
bd7806 499
5e7a31 500 5. 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 501
5e7a31 502 ### Part 6 - Jenkins Hello World
d28811 503 > _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 balls are green._
D 504
505 6. Log in to Jenkins and hit `New Item` ![new-item](../images/exercise1/new-item.png).
506
176e08 507 6. Create a freestyle job called `hello-world` ![jenkins-new-hello-world](../images/exercise1/jenkins-new-hello-world.png).
d28811 508
11198f 509 6. 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 510
D 511 6. 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).
512
5e7a31 513 6. Run the build and we should see if pass successfully and with Green Balls! ![jenkins-green-balls](../images/exercise1/jenkins-green-balls.png)
d28811 514
e41c20 515 ### Part 7 - Live, Die, Repeat
5e7a31 516 > _In this section you will prove the infra as code is working by deleting your Cluster Content and recreating it all_
d28811 517
D 518 7. Commit your code to the new repo in GitLab
9eed0b 519 ```bash
784073 520 git add .
D 521 ```
522 ```bash
523 git commit -m "ADD - all ci/cd contents"
524 ```
525 ```bash
526 git push
9eed0b 527 ```
d28811 528
D 529 7. Burn your OCP content to the ground
9eed0b 530 ```bash
784073 531 oc delete project <YOUR_NAME>-ci-cd
D 532 ```
533 ```bash
534 oc delete project <YOUR_NAME>-dev
535 ```
536 ```bash
537 oc delete project <YOUR_NAME>-test
9eed0b 538 ```
d28811 539
e23af1 540 7. Check to see the projects that were marked for deletion are removed.
D 541 ```bash
784073 542 oc get projects | egrep '<YOUR_NAME>-ci-cd|<YOUR_NAME>-dev|<YOUR_NAME>-test'
e23af1 543 ```
D 544
9eed0b 545 7. Re-apply the inventory to re-create it all!
D 546 ```bash
a9627c 547 oc login https://console.lader.rht-labs.com
784073 548 ```
D 549 ```bash
550 ansible-playbook apply.yml -i inventory/ -e target=bootstrap
551 ```
552 ```bash
553 ansible-playbook apply.yml -i inventory/ -e target=tools
9eed0b 554 ```
0f4d08 555
74d1f1 556 _____
D 557
0f4d08 558 ## Extension Tasks
d28811 559 > _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 560
a9627c 561  - Install Cowsay for 100% more Ansible Fun!
92099a 562  - Add more secure access for Nexus (ie not admin / admin123) using the automation to drive secret creation
1c9328 563  - Add a SonarQube persistent deployment to the `ci-cd-deployments` section.
D 564  - Add `jenkins.plugins.slack.SlackNotifier.xml` to `jenkins-s2i/configuration` to include URL of Slack for team build notifications and rebuild Jenkins S2I
0f4d08 565
74d1f1 566 _____
D 567
0f4d08 568 ## Additional Reading
9eed0b 569 > List of links or other reading that might be of use / reference for the exercise
4f0295 570
RH 571 ## Slide links
572
573 - [Intro](https://docs.google.com/presentation/d/1LsfAkH8GfIhulEoy_yd-usWBfDHnZEyQdNvYeTmAg4A/)
574 - [Wrap-up](https://docs.google.com/presentation/d/1cfyJ6SHddZNbM61oz67r870rLYVKY335zGclXN2uLMY/)
3207b9 575 - [All Material](https://drive.google.com/drive/folders/13Bt4BXf9P2OB8VI4YQNcNONF1786dqOx)