├── .github └── issue_template.md ├── .travis.yml ├── .yamllint ├── LICENSE ├── README.md ├── defaults └── main.yml ├── files ├── apt │ └── debian-package-pins └── jenkins.model.JenkinsLocationConfiguration.xml.j2 ├── meta └── main.yml ├── molecule ├── api-token │ ├── Dockerfile.j2 │ ├── jenkins-configs │ │ ├── config.xml │ │ ├── jobs │ │ │ └── test_job │ │ │ │ └── config.xml │ │ └── users │ │ │ └── molecule │ │ │ └── config.xml │ ├── molecule.yml │ ├── playbook.yml │ └── tests │ │ ├── .gitignore │ │ └── test_default.py ├── bionic │ ├── Dockerfile.j2 │ ├── jenkins-configs │ │ └── config.xml │ ├── molecule.yml │ ├── playbook.yml │ └── tests │ │ ├── .gitignore │ │ └── test_default.py ├── default │ ├── Dockerfile.j2 │ ├── jenkins-configs │ │ ├── config.xml │ │ ├── jobs │ │ │ └── test_job │ │ │ │ └── config.xml │ │ ├── secrets │ │ │ └── com.example.secret.xml │ │ └── userContent │ │ │ └── index.html │ ├── molecule.yml │ ├── playbook.yml │ └── tests │ │ ├── .gitignore │ │ └── test_default.py └── https │ ├── Dockerfile.j2 │ ├── jenkins-configs │ └── config.xml │ ├── molecule.yml │ ├── playbook.yml │ ├── ssl │ └── test-cert.jks │ └── tests │ ├── .gitignore │ └── test_default.py ├── requirements.txt └── tasks ├── apt ├── install.yml ├── start.yml └── stop.yml ├── cancel-quiet-mode.yml ├── configure-files.yml ├── configure-jenkins.yml ├── configure-jobs.yml ├── configure-plugins.yml ├── docker ├── install.yml ├── start.yml └── stop.yml ├── get-crumb.yml ├── main.yml ├── sanity-checks.yml ├── set-quiet-mode.yml ├── start.yml └── yum ├── install.yml ├── start.yml └── stop.yml /.github/issue_template.md: -------------------------------------------------------------------------------- 1 | ## Expected Behavior 2 | 3 | 4 | ## Actual Behavior 5 | 6 | 7 | ## Steps to Reproduce the Problem 8 | 9 | 1. 10 | 2. 11 | 3. 12 | 13 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | python: 4 | - "3.6" 5 | services: 6 | - docker 7 | install: 8 | - pip install -r requirements.txt 9 | script: 10 | - molecule test --all 11 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | extends: default 2 | 3 | rules: 4 | line-length: 5 | max: 90 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Emmet O'Grady 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Ansible Role for Jenkins 2 | ======================== 3 | 4 | Installs and completely configures Jenkins using Ansible. 5 | 6 | This role is used when you want all your Jenkins configuration in version 7 | control so you can deploy Jenkins repeatably and reliably and you can treat your 8 | Jenkins as a [Cow instead of a 9 | Pet](https://blog.engineyard.com/2014/pets-vs-cattle). 10 | 11 | If you are looking for a role to install Jenkins and you want to configure 12 | everything through the web interface and you don't care about being able to 13 | repeatably deploy this same fully-configured Jenkins, then you don't need this 14 | role. Instead, have a look at the 15 | [geerlingguy/ansible-role-jenkins](https://github.com/geerlingguy/ansible-role-jenkins) 16 | role instead. 17 | 18 | Requirements 19 | ------------ 20 | 21 | If deploying using Docker, then you need Docker installed on the server. Docker, 22 | apt-get, and yum are the only supported ways at the moment although more ways 23 | can easily be added, PRs welcome. 24 | 25 | Installation 26 | ------------ 27 | 28 | Install using Ansible Galaxy: 29 | 30 | ``` 31 | $ ansible-galaxy install emmetog.jenkins 32 | ``` 33 | 34 | Role Variables 35 | -------------- 36 | 37 | The following variables influence how Jenkins is installed: 38 | 39 | - `jenkins_install_via`: Controls how Jenkins is installed. **Important**: This 40 | variable must be defined to one of the following values: 41 | - `docker`: Install in a Docker container 42 | - `apt`: Install Jenkins directly on Ubuntu/Debian Linux systems 43 | - `yum`: Install Jenkins directly on RedHat/CentOS Linux systems 44 | - `jenkins_version`: The exact version of Jenkins to install 45 | 46 | The following variables influence how Jenkins is configured: 47 | 48 | - `jenkins_url`: The URL that Jenkins will be accessible on 49 | - `jenkins_port`: The port that Jenkins will listen on 50 | - `jenkins_home`: The directory on the server where the Jenkins configs will 51 | live 52 | - `jenkins_admin`: The administrator's email address for the Jenkins server 53 | - `jenkins_java_opts`: Options passed to the Java executable 54 | - `jenkins_config_owner`: Owner of Jenkins configuration files 55 | - `jenkins_config_group`: Group of Jenkins configuration files 56 | - `jenkins_auth`: How Ansible should authenticate itself with Jenkins, (see the 57 | "Authentication and Security" section below) 58 | - `jenkins_url_health_check`: which url to use for the health check after jenkins is started (defaults to `jenkins_url`) 59 | - `jenkins_health_check_user`: if defined, uses basic auth (see API token section) for health check with this username (useful if you set up e.g. Google OAuth) 60 | - `jenkins_health_check_password`: if defined, uses basic auth (see API token section) for health check with this password (useful if you set up e.g. Google OAuth) 61 | 62 | The following list variables influence the jobs/plugins that will be installed 63 | in Jenkins: 64 | 65 | - `jenkins_jobs`: List of names of the jobs to copy to Jenkins. The `config.xml` 66 | file must exist under `jenkins_source_dir_jobs/` 67 | - `jenkins_plugins`: List of plugin IDs to install on Jenkins. 68 | - `jenkins_custom_plugins`: List of custom plugins to install on Jenkins. 69 | 70 | For a complete list of variables, see [`defaults/main.yml`](defaults/main.yml). 71 | 72 | Example Playbook 73 | ---------------- 74 | 75 | ```yml 76 | - hosts: jenkins 77 | 78 | vars: 79 | jenkins_version: "2.73.1" 80 | jenkins_hostname: "jenkins.example.com" 81 | jenkins_port: 8080 82 | jenkins_install_via: "docker" 83 | jenkins_jobs: 84 | - "my-first-job" 85 | - "another-awesome-job" 86 | jenkins_include_secrets: true 87 | jenkins_include_custom_files: true 88 | jenkins_custom_files: 89 | - src: "jenkins.plugins.openstack.compute.UserDataConfig.xml" 90 | dest: "jenkins.plugins.openstack.compute.UserDataConfig.xml" 91 | jenkins_plugins: 92 | - git 93 | - blueocean 94 | jenkins_custom_plugins: 95 | - "openstack-cloud-plugin/openstack-cloud.jpi" 96 | 97 | roles: 98 | - emmetog.jenkins 99 | ``` 100 | 101 | Managing Configuration Files 102 | ---------------------------- 103 | 104 | The example above will look for job configuration files in 105 | `{{ playbook_dir }}/jenkins-configs/jobs/my-first-job/config.xml` and 106 | `{{ playbook_dir }}/jenkins-configs/jobs/another-awesome-job/config.xml`. 107 | 108 | **NOTE**: These directories are customizable, see the 109 | `jenkins_source_dir_configs` and `jenkins_source_dir_jobs` role variables. 110 | 111 | The role will also look for `{{ playbook_dir }}/jenkins-configs/config.xml` 112 | This `config.xml` file will be copied to the server and used as the job 113 | configuration template. 114 | 115 | The above example will also upload the entire secrets directory under 116 | `{{ playbook_dir }}/jenkins-configs/secrets`, and also copy custom files 117 | defined in the `{{ jenkins_custom_files }}` variable. Note that 118 | `{{ jenkins_include_secrets }}` and `{{ jenkins_include_custom_files }}` 119 | variables should be set to `true` for features these to work. Additionally, 120 | the role can install custom plugins by providing the .jpi or .hpi files in the 121 | `{{ jenkins_custom_plugins }}` list variable. 122 | 123 | The `config.xml` and the custom files are treated as templates so you can put 124 | variables in them, including sensitive data from the Ansible vault. 125 | 126 | When you want to make a change in a configuration file, or you want to add a 127 | new item (such as a job, plugin, etc) the normal workflow is: 128 | 129 | 1. Make the change in the Jenkins UI 130 | 2. Copy the resulting XML files back into your VCS 131 | 3. For newly-created files, don't forget to add them to the respective list: 132 | - For new jobs, these must be added to `jenkins_jobs` 133 | - For custom files, these must be added to `jenkins_include_custom_files` 134 | - For custom plugins, these must be added to `jenkins_custom_plugins` 135 | 136 | Example Jenkins Configuration File 137 | ---------------------------------- 138 | 139 | In `{{ jenkins_source_dir_configs }}/config.xml` you put your global Jenkins 140 | configuration, for example: 141 | 142 | ```xml 143 | 144 | 145 | 146 | 2.176.1 147 | RESTART 148 | 1 149 | EXCLUSIVE 150 | true 151 | 152 | 153 | false 154 | false 155 | 156 | false 157 | 158 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} 159 | ${ITEM_ROOTDIR}/builds 160 | 161 | 162 | 163 | 164 | 165 | 0 166 | 0 167 | 168 | 169 | 170 | all 171 | false 172 | false 173 | 174 | 175 | 176 | all 177 | 0 178 | 179 | JNLP-connect 180 | JNLP2-connect 181 | 182 | 183 | 184 | false 185 | 186 | 187 | 188 | 189 | ``` 190 | 191 | Example Job Configuration File 192 | ------------------------------ 193 | 194 | Here's an example of what you could put in 195 | `{{ playbook_dir }}/jenkins-configs/jobs/my-first-job/config.xml`: 196 | 197 | ```xml 198 | 199 | 200 | 201 | My first job, it says "hello world" 202 | false 203 | 204 | 205 | true 206 | false 207 | false 208 | false 209 | 210 | false 211 | 212 | 213 | echo "Hello World!" 214 | 215 | 216 | 217 | 218 | 219 | ``` 220 | 221 | Authentication and Security 222 | --------------------------- 223 | 224 | This role supports the following authentication mechanisms for Jenkins: 225 | 226 | 1. API token-based authentication (recommended, requires at least Jenkins 2.96) 227 | 2. Crumb-based authentication with the [Strict Crumb Issuer 228 | plugin](https://plugins.jenkins.io/strict-crumb-issuer) (required if _not_ 229 | using API tokens and Jenkins 2.176.2 or newer) 230 | 3. No security (not recommended) 231 | 232 | *API token-based authentication* 233 | 234 | API token-based authentication is recommended, but requires a bit of extra 235 | effort to configure. The advantage of API tokens is that they can be easily 236 | revoked in Jenkins, and their usage is also tracked. API tokens also do not 237 | require getting a crumb token, which has become more difficult since Jenkins 238 | version 2.172.2 (see [this security 239 | bulletin](https://jenkins.io/security/advisory/2019-07-17/#SECURITY-626). 240 | 241 | To create an API token, you'll need to do the following: 242 | 243 | 1. All API tokens must belong to a specific user. So either create a special 244 | user for deployments, or log in as the administrator or another account. 245 | 2. In the user's configuration page, click the "Add new Token" button. 246 | 3. Save the token value, preferably in an Ansible vault. 247 | 4. Define the following variables in your playbook: 248 | - `jenkins_auth: "api"` 249 | - `jenkins_api_token: "(defined in the Anible vault)"` 250 | - `jenkins_api_username: "(defined in the Ansible vault)"` 251 | 5. Create a backup of the file `$JENKINS_HOME/users/the_username/config.xml`, 252 | where `the_username` corresponds to the user which owns the API token you 253 | just created. 254 | 6. Add this file to your control host, and make sure that is deployed to Jenkins 255 | in the `jenkins_custom_files` list, like so: 256 | 257 | ``` 258 | jenkins_custom_files: 259 | - src: "users/the_username/config.xml" 260 | dest: "users/the_username/config.xml" 261 | ``` 262 | 263 | Note that you may need to change the `src` value, depending on where you save 264 | the file on the control machine relative to the playbook. 265 | 266 | *Crumb-based authentication* 267 | 268 | Crumb-based authentication can be used to prevent cross-site request forgery 269 | attacks and is recommended if API tokens are impractical. **Note**: crumb-based 270 | authentication only works with the "Anyone can do anything" access control 271 | setting. If your Jenkins configuration requires a stricter security setup, you 272 | should use API tokens (documented above). 273 | 274 | Crumb-based authentication can also be a bit tricky to configure due to recent 275 | security fixes in Jenkins. To configure CSRF, you'll need to do the following: 276 | 277 | 1. If you are using Jenkins >= 2.176.2, you'll need to install the 278 | Strict Crumb Issuer plugin. This can be done by this role by adding the 279 | `strict-crumb-issuer` ID to the `jenkins_plugins` list. 280 | 2. In Jenkins, click on "Manage Jenkins" -> "Configure Global Security" 281 | 3. In the "CSRF Protection" section, enable "Prevent Cross Site Request Forgery 282 | exploits", and then select "Strict Crumb Issuer" if using Jenkins >= 2.176.2, 283 | or otherwise "Default Crumb Issuer". Note that to see this option, you'll 284 | need to have the Strict Crumb Issuer plugin installed. Afterwards, you'll 285 | also need to backup the main Jenkins `config.xml` file to the control host. 286 | 287 | Likewise, for the above to work, you'll need at least Ansible 2.9.0pre5 or 2.10 288 | (which are, at the time of this writing, both in development. See [this Ansible 289 | issue](https://github.com/ansible/ansible/issues/61672) for more details). 290 | 291 | HTTPS 292 | ----- 293 | 294 | If you want to enable HTTPS on Jenkins, this can be done as follows: 295 | 296 | - Define `jenkins_port_https` to the port that Jenkins should listen on 297 | - Define variables *either* for the JKS keystore or the CA signed certificate: 298 | * For JKS keystore, you'll need to define: 299 | - `jenkins_https_keystore`: Path to the keystore file on the control host, 300 | which will be copied to the Jenkins server by this role. 301 | - `jenkins_https_keystore_password`: Password for said JKS keystore. Use of 302 | the Ansible vault is recommended for this. **IMPORTANT**: This string 303 | will be written in plaintext to the Jenkins configuration file on the 304 | server. It will also be visible in the server's process list. Consider 305 | migrating your certificate to a signed certificate file (see below). 306 | * For a CA signed certificate file, you'll need to define: 307 | - `jenkins_https_certificate`: Path to the certificate file, which will be 308 | copied to the Jenkins server by this role. Use of the Ansible vault is 309 | recommended for this file. 310 | - `jenkins_https_private_key`: Private key for said CA signed certificate. 311 | Use of the Ansible vault is recommended for this file. 312 | - Optionally, `jenkins_https_validate_certs` should be defined to `false` if 313 | you are using a self-signed certificate. 314 | 315 | If you are deploying Jenkins with Docker, then using a reverse proxy such as 316 | [jwilder/nginx-proxy](https://github.com/jwilder/nginx-proxy) or 317 | [traefik](https://github.com/containous/traefik) is recommended instead of 318 | configuring Jenkins itself. This gives a bit more flexibility and allows for 319 | separation of responsibilities. See the documentation in those projects for 320 | more details on how to deploy the proxies and configure HTTPS. 321 | 322 | If using a reverse proxy in front of the Jenkins instance and deploying using 323 | Docker you probably want to set the `jenkins_docker_expose_port` variable to 324 | false so that the port is not exposed on the host, only to the reverse proxy. 325 | 326 | License 327 | ------- 328 | 329 | MIT 330 | 331 | Author Information 332 | ------------------ 333 | 334 | Made with love by Emmet O'Grady. 335 | 336 | I am the founder of [NimbleCI](https://nimbleci.com) which builds Docker 337 | containers for feature branch workflow projects in Github. 338 | 339 | I blog on my [personal blog](http://blog.emmetogrady.com) and about Docker 340 | related things on the [NimbleCI blog](https://blog.nimbleci.com). 341 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | jenkins_version: "2.73.1" # The exact version of jenkins to deploy 3 | 4 | jenkins_hostname: "127.0.0.1" # The hostname that Jenkins will be accessible on 5 | # The port that Jenkins will listen on for unsecured (HTTP) requests. Define to -1 to 6 | # disable HTTP. 7 | jenkins_port: "8080" 8 | # The port that Jenkins will listen on for secured (HTTPS) requests. Define to -1 to 9 | # disable HTTPS. Enabling this option requires a SSL certificate (see below). 10 | jenkins_port_https: "-1" 11 | jenkins_home: /data/jenkins # The directory on the server where the Jenkins configs live 12 | jenkins_admin: "admin@example.com" # The administrator email address for the server 13 | 14 | # If you need to override any java options then do that here. 15 | jenkins_java_opts: "-Djenkins.install.runSetupWizard=false" 16 | 17 | # Configuration files owner and group 18 | jenkins_config_owner: "ubuntu" 19 | jenkins_config_group: "ubuntu" 20 | 21 | # The locations of the configuration files for jenkins 22 | jenkins_source_dir_configs: "{{ playbook_dir }}/jenkins-configs" 23 | jenkins_source_dir_jobs: "{{ jenkins_source_dir_configs }}/jobs" 24 | 25 | # When defined, include this task file after configuring jobs. This happens 26 | # at the very end of the role, but before Jenkins is taken out of quiet mode. 27 | jenkins_after_config_jobs_file: "" 28 | 29 | # config.xml template source 30 | jenkins_source_config_xml: "{{ jenkins_source_dir_configs }}/config.xml" 31 | 32 | # Include custom files for jenkins installation 33 | jenkins_include_custom_files: false 34 | jenkins_custom_files: {} # src and dest names 35 | 36 | # Include secrets directory during installation 37 | jenkins_include_secrets: false 38 | jenkins_source_secrets: "{{ jenkins_source_dir_configs }}/secrets/" 39 | 40 | # The names of the jobs (config.xml must exist under jenkins_source_dir_jobs/job_name/) 41 | jenkins_jobs: [] 42 | 43 | # List of plugins to install in the Jenkins instance 44 | jenkins_plugins: [] 45 | 46 | # How long to wait for installing plugins, in seconds. If you are seeing failures in the 47 | # "Wait for plugins to finish installing" task with an error message like "Timeout when 48 | # waiting for file ", you may want to increase this value. 49 | jenkins_plugin_timeout: 300 50 | 51 | # List of sources of custom jenkins plugins to install 52 | jenkins_custom_plugins: [] 53 | 54 | ####################### 55 | # Authentication vars # 56 | ####################### 57 | 58 | # Mechanism to use when authenticating to Jenkins. Must be one of the following values: 59 | # - api: Use an API token which belongs to a specific user 60 | # - crumb: Use anonymous crumb-based authentication 61 | # - none: No security (not recommended) 62 | # For more information, please refer to the "Authentication and Security" section of the 63 | # README. 64 | jenkins_auth: "crumb" 65 | 66 | # When defined, use this API token instead of getting a crumb from the system. Requires 67 | # jenkins_api_username. 68 | jenkins_api_token: "" 69 | # Username which owns the above API token. 70 | jenkins_api_username: "" 71 | 72 | ######################################### 73 | # SSL vars: apply to Jenkins HTTPS only # 74 | ######################################### 75 | 76 | # See https://wiki.jenkins.io/display/JENKINS/Starting+and+Accessing+Jenkins for more info 77 | 78 | # Jenkins JKS keystore file. Mutually exclusive with the certificate/private key options. 79 | jenkins_https_keystore: "" 80 | # Jenkins JKS keystore password. 81 | jenkins_https_keystore_password: "" 82 | 83 | # Jenkins CA signed certificate file. Mutually exclusive with the keystore options. 84 | jenkins_https_certificate: "" 85 | # Jenkins CA signed certificate private key. 86 | jenkins_https_private_key: "" 87 | 88 | # Set to false if you are using a self-signed certificate and wish to ignore any 89 | # certificate verification errors from Ansible. 90 | jenkins_https_validate_certs: true 91 | 92 | ################################################### 93 | # Docker vars: apply to deploying via docker only # 94 | ################################################### 95 | 96 | # The docker hub image name 97 | jenkins_docker_image: "jenkins/jenkins" 98 | 99 | # Configs specific to the "docker" method of running jenkins 100 | # The name of the jenkins container 101 | jenkins_docker_container_name: jenkins 102 | 103 | # Default, if true, the port will be exposed on the host (using "port") 104 | # If set to false, the port will only be exposed to other containers (using "expose") 105 | jenkins_docker_expose_port: true 106 | 107 | 108 | ############################################# 109 | # Apt vars: apply to deploying via apt only # 110 | ############################################# 111 | 112 | # Packages which are to be installed on the jenkins instance 113 | jenkins_apt_packages: 114 | - openjdk-8-jdk 115 | 116 | # Java version to use. Note that JDK 8 is required for Jenkins 117 | # 2.54 or greater. 118 | jenkins_java_version: "java-1.8.0-openjdk-amd64" 119 | -------------------------------------------------------------------------------- /files/apt/debian-package-pins: -------------------------------------------------------------------------------- 1 | Package: * 2 | Pin: release o=Debian,n=experimental 3 | Pin-Priority: -1 4 | 5 | Package: * 6 | Pin: release o=Debian,n=sid 7 | Pin-Priority: -1 8 | 9 | Package: openjdk-7-jdk 10 | Pin: release o=Debian,n=experimental 11 | Pin-Priority: 500 12 | 13 | Package: openjdk-7-jre 14 | Pin: release o=Debian,n=experimental 15 | Pin-Priority: 500 16 | 17 | Package: openjdk-7-jre-headless 18 | Pin: release o=Debian,n=experimental 19 | Pin-Priority: 500 20 | 21 | Package: libjpeg62-turbo 22 | Pin: release o=Debian,n=sid 23 | Pin-Priority: 500 -------------------------------------------------------------------------------- /files/jenkins.model.JenkinsLocationConfiguration.xml.j2: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ jenkins_admin }} 4 | {{ jenkins_url }} 5 | 6 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Emmet O'Grady 4 | description: Installs and completely configures Jenkins using Ansible 5 | issue_tracker_url: https://github.com/emmetog/ansible-jenkins/issues 6 | 7 | license: MIT 8 | 9 | min_ansible_version: 2.1 10 | 11 | # Below are all platforms currently available. Just uncomment 12 | # the ones that apply to your role. If you don't see your 13 | # platform on this list, let us know and we'll get it added! 14 | platforms: 15 | - name: Ubuntu 16 | versions: 17 | - all 18 | - name: Debian 19 | versions: 20 | - all 21 | - name: EL 22 | versions: 23 | - all 24 | 25 | # Below are all categories currently available. Just as with 26 | # the platforms above, uncomment those that apply to your role. 27 | galaxy_tags: 28 | - development 29 | - packaging 30 | - docker 31 | - jenkins 32 | - ci 33 | - deploy 34 | 35 | dependencies: [] 36 | # List your role dependencies here, one per line. 37 | # Be sure to remove the '[]' above if you add dependencies 38 | # to this list. 39 | -------------------------------------------------------------------------------- /molecule/api-token/Dockerfile.j2: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | {% if item.registry is defined %} 4 | FROM {{ item.registry.url }}/{{ item.image }} 5 | {% else %} 6 | FROM {{ item.image }} 7 | {% endif %} 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y apt-transport-https aptitude bash ca-certificates sudo python \ 11 | python-apt && \ 12 | apt-get clean 13 | 14 | RUN useradd -G sudo molecule 15 | -------------------------------------------------------------------------------- /molecule/api-token/jenkins-configs/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.190.1 5 | RESTART 6 | 1 7 | EXCLUSIVE 8 | true 9 | 10 | 11 | false 12 | false 13 | 14 | false 15 | 16 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} 17 | ${ITEM_ROOTDIR}/builds 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 0 25 | 26 | 27 | 28 | all 29 | false 30 | false 31 | 32 | 33 | 34 | all 35 | 0 36 | 37 | JNLP-connect 38 | JNLP2-connect 39 | 40 | 41 | 42 | false 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /molecule/api-token/jenkins-configs/jobs/test_job/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 5 | 6 | true 7 | false 8 | false 9 | false 10 | 11 | false 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /molecule/api-token/jenkins-configs/users/molecule/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10 4 | molecule 5 | Molecule Test User 6 | 7 | 8 | 9 | 10 | 11 | 12 | bdf647eb-10f3-46e3-8a2d-13d10962247f 13 | Deployment Token 14 | 2019-10-23 15:27:12.108 UTC 15 | 16 | 11 17 | bf8962734f66b3a0e122d6c96cae2e85dfceb6d8b9b4cdc0333de5d73c956313 18 | 19 | 20 | 21 | 22 | 23 | 24 | true 25 | 26 | 27 | 28 | 29 | 30 | test@example.com 31 | 32 | 33 | 34 | 35 | 36 | 37 | authenticated 38 | 39 | 1571844399911 40 | 41 | 42 | 43 | 44 | 45 | 46 | all 47 | false 48 | false 49 | 50 | 51 | 52 | 53 | 54 | default 55 | 56 | 57 | 58 | 59 | 60 | #jbcrypt:$2a$10$AwJxJ.RV0mv7nzROLZN1O.XarAZfFdxaYXM.MRbdnr/pgSp5m608i 61 | 62 | 63 | 64 | 65 | 66 | ae4a45c415ddc43f 67 | 68 | 69 | true 70 | 71 | 72 | 73 | false 74 | 75 | 76 | -------------------------------------------------------------------------------- /molecule/api-token/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: 7 | name: yamllint 8 | platforms: 9 | - name: instance 10 | image: ubuntu:16.04 11 | privileged: true 12 | exposed_ports: 13 | - 8080/tcp 14 | published_ports: 15 | - 0.0.0.0:8080:8080/tcp 16 | env: 17 | JENKINS_HOME: /jenkins 18 | provisioner: 19 | name: ansible 20 | log: true 21 | lint: 22 | name: ansible-lint 23 | options: 24 | # E602: Don't compare to empty string 25 | # All workarounds for this are uglier than just comparing to empty strings. See: 26 | # https://github.com/ansible/ansible-lint/issues/457 27 | x: ['602'] 28 | scenario: 29 | test_sequence: 30 | - destroy 31 | - create 32 | - converge 33 | # The idempotence check must be disabled for this scenario, because we are copying 34 | # custom files for user accounts. These files (or rather, their parent directories) 35 | # are renamed by Jenkins when it starts up in order to avoid naming conflicts. So 36 | # "users/molecule/config.xml" becomes "users/molecule_7942252632599620805/config.xml", 37 | # with a randomly-generated number. 38 | # - idempotence 39 | - lint 40 | - verify 41 | verifier: 42 | name: testinfra 43 | lint: 44 | name: flake8 45 | -------------------------------------------------------------------------------- /molecule/api-token/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | vars: 5 | jenkins_auth: "api" 6 | jenkins_api_username: "molecule" 7 | # NOTE: Do not store actual API tokens in plain-text in your playbooks. Always use an 8 | # Ansible vault for such data. 9 | jenkins_api_token: "110cd5010cc081551972181446639ba99f" 10 | jenkins_config_owner: "jenkins" 11 | jenkins_config_group: "jenkins" 12 | jenkins_home: "/jenkins" 13 | jenkins_install_via: "apt" 14 | jenkins_custom_files: 15 | - src: "users/molecule/config.xml" 16 | dest: "users/molecule/config.xml" 17 | jenkins_include_custom_files: true 18 | jenkins_jobs: 19 | - test_job 20 | jenkins_plugins: 21 | - git 22 | jenkins_version: "2.190.1" 23 | roles: 24 | - ansible-jenkins 25 | -------------------------------------------------------------------------------- /molecule/api-token/tests/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /molecule/api-token/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import testinfra.utils.ansible_runner 4 | 5 | from jenkins import Jenkins 6 | 7 | 8 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 9 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') 10 | 11 | 12 | def test_jenkins_installed(host): 13 | package = host.package('jenkins') 14 | 15 | assert package.is_installed 16 | 17 | 18 | def test_jenkins_version(): 19 | master = Jenkins('http://127.0.0.1:8080') 20 | version = master.get_version() 21 | 22 | assert version == '2.190.1' 23 | 24 | 25 | def test_jenkins_plugins(): 26 | master = Jenkins('http://127.0.0.1:8080') 27 | plugins = master.get_plugins() 28 | 29 | assert plugins['git']['active'] 30 | assert plugins['git']['enabled'] 31 | 32 | 33 | def test_jenkins_jobs(): 34 | master = Jenkins('http://127.0.0.1:8080') 35 | test_job = master.get_job_info('test_job') 36 | 37 | assert test_job['name'] == 'test_job' 38 | assert test_job['buildable'] 39 | -------------------------------------------------------------------------------- /molecule/bionic/Dockerfile.j2: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | {% if item.registry is defined %} 4 | FROM {{ item.registry.url }}/{{ item.image }} 5 | {% else %} 6 | FROM {{ item.image }} 7 | {% endif %} 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y gpg apt-transport-https aptitude bash ca-certificates sudo \ 11 | python python-apt && \ 12 | apt-get clean 13 | 14 | RUN useradd -G sudo molecule 15 | -------------------------------------------------------------------------------- /molecule/bionic/jenkins-configs/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.176.1 5 | RESTART 6 | 1 7 | EXCLUSIVE 8 | true 9 | 10 | 11 | false 12 | false 13 | 14 | false 15 | 16 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} 17 | ${ITEM_ROOTDIR}/builds 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 0 25 | 26 | 27 | 28 | all 29 | false 30 | false 31 | 32 | 33 | 34 | all 35 | 0 36 | 37 | JNLP-connect 38 | JNLP2-connect 39 | 40 | 41 | 42 | false 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /molecule/bionic/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: 7 | name: yamllint 8 | platforms: 9 | - name: instance 10 | image: ubuntu:18.04 11 | privileged: true 12 | exposed_ports: 13 | - 8080/tcp 14 | published_ports: 15 | - 0.0.0.0:8080:8080/tcp 16 | env: 17 | JENKINS_HOME: /jenkins 18 | provisioner: 19 | name: ansible 20 | log: true 21 | lint: 22 | name: ansible-lint 23 | options: 24 | # E602: Don't compare to empty string 25 | # All workarounds for this are uglier than just comparing to empty strings. See: 26 | # https://github.com/ansible/ansible-lint/issues/457 27 | x: ['602'] 28 | verifier: 29 | name: testinfra 30 | lint: 31 | name: flake8 32 | -------------------------------------------------------------------------------- /molecule/bionic/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | vars: 5 | jenkins_config_owner: "jenkins" 6 | jenkins_config_group: "jenkins" 7 | jenkins_home: "/jenkins" 8 | jenkins_install_via: "apt" 9 | jenkins_version: "2.176.1" 10 | roles: 11 | - ansible-jenkins 12 | -------------------------------------------------------------------------------- /molecule/bionic/tests/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /molecule/bionic/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import testinfra.utils.ansible_runner 4 | 5 | from jenkins import Jenkins 6 | 7 | 8 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 9 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') 10 | 11 | 12 | def test_jenkins_installed(host): 13 | package = host.package('jenkins') 14 | 15 | assert package.is_installed 16 | 17 | 18 | def test_jenkins_version(): 19 | master = Jenkins('http://127.0.0.1:8080') 20 | version = master.get_version() 21 | 22 | assert version == '2.176.1' 23 | -------------------------------------------------------------------------------- /molecule/default/Dockerfile.j2: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | {% if item.registry is defined %} 4 | FROM {{ item.registry.url }}/{{ item.image }} 5 | {% else %} 6 | FROM {{ item.image }} 7 | {% endif %} 8 | 9 | RUN \ 10 | if [ $(command -v apt-get) ]; then \ 11 | apt-get update && \ 12 | apt-get install -y apt-transport-https aptitude bash ca-certificates sudo \ 13 | python python-apt && \ 14 | apt-get clean; \ 15 | elif [ $(command -v yum) ]; then \ 16 | yum makecache fast && \ 17 | yum install -y python sudo yum-plugin-ovl bash && \ 18 | sed -i 's/plugins=0/plugins=1/g' /etc/yum.conf && \ 19 | yum clean all; \ 20 | fi 21 | 22 | RUN useradd -G sudo molecule 23 | -------------------------------------------------------------------------------- /molecule/default/jenkins-configs/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.176.1 5 | RESTART 6 | 1 7 | EXCLUSIVE 8 | true 9 | 10 | 11 | false 12 | false 13 | 14 | false 15 | 16 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} 17 | ${ITEM_ROOTDIR}/builds 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 0 25 | 26 | 27 | 28 | all 29 | false 30 | false 31 | 32 | 33 | 34 | all 35 | 0 36 | 37 | JNLP-connect 38 | JNLP2-connect 39 | 40 | 41 | 42 | false 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /molecule/default/jenkins-configs/jobs/test_job/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | false 4 | 5 | 6 | true 7 | false 8 | false 9 | false 10 | 11 | false 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /molecule/default/jenkins-configs/secrets/com.example.secret.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /molecule/default/jenkins-configs/userContent/index.html: -------------------------------------------------------------------------------- 1 | Hello, world! 2 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: 7 | name: yamllint 8 | platforms: 9 | - name: instance 10 | image: ubuntu:16.04 11 | privileged: true 12 | exposed_ports: 13 | - 8080/tcp 14 | published_ports: 15 | - 0.0.0.0:8080:8080/tcp 16 | env: 17 | JENKINS_HOME: /jenkins 18 | provisioner: 19 | name: ansible 20 | log: true 21 | lint: 22 | name: ansible-lint 23 | options: 24 | # E602: Don't compare to empty string 25 | # All workarounds for this are uglier than just comparing to empty strings. See: 26 | # https://github.com/ansible/ansible-lint/issues/457 27 | x: ['602'] 28 | verifier: 29 | name: testinfra 30 | lint: 31 | name: flake8 32 | -------------------------------------------------------------------------------- /molecule/default/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | vars: 5 | jenkins_config_owner: "jenkins" 6 | jenkins_config_group: "jenkins" 7 | jenkins_custom_files: 8 | - src: "userContent/index.html" 9 | dest: "userContent/index.html" 10 | jenkins_home: "/jenkins" 11 | jenkins_include_custom_files: true 12 | jenkins_include_secrets: true 13 | jenkins_install_via: "apt" 14 | jenkins_jobs: 15 | - test_job 16 | jenkins_plugins: 17 | - git 18 | jenkins_version: "2.176.1" 19 | roles: 20 | - ansible-jenkins 21 | -------------------------------------------------------------------------------- /molecule/default/tests/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /molecule/default/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import testinfra.utils.ansible_runner 4 | 5 | from jenkins import Jenkins 6 | 7 | 8 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 9 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') 10 | 11 | 12 | def test_jenkins_installed(host): 13 | package = host.package('jenkins') 14 | 15 | assert package.is_installed 16 | 17 | 18 | def test_jenkins_user(host): 19 | assert host.user('jenkins').group == 'jenkins' 20 | assert host.user('jenkins').home == '/jenkins' 21 | 22 | 23 | def test_jenkins_dir(host): 24 | assert host.file('/jenkins').is_directory 25 | assert host.file('/jenkins').mode == 0o0755 26 | assert host.file('/jenkins').user == 'jenkins' 27 | assert host.file('/jenkins').group == 'jenkins' 28 | assert host.file('/jenkins/config.xml').is_file 29 | assert host.file('/jenkins/config.xml').user == 'jenkins' 30 | assert host.file('/jenkins/config.xml').group == 'jenkins' 31 | 32 | 33 | def test_jenkins_secrets_files(host): 34 | assert host.file('/jenkins/secrets').is_directory 35 | assert host.file('/jenkins/secrets').mode == 0o0700 36 | assert host.file('/jenkins/secrets').user == 'jenkins' 37 | assert host.file('/jenkins/secrets').group == 'jenkins' 38 | test_secret_file = host.file('/jenkins/secrets/com.example.secret.xml') 39 | assert test_secret_file.is_file 40 | assert test_secret_file.user == 'jenkins' 41 | assert test_secret_file.group == 'jenkins' 42 | 43 | 44 | def test_jenkins_job_files(host): 45 | assert host.file('/jenkins/jobs').is_directory 46 | assert host.file('/jenkins/jobs').user == 'jenkins' 47 | assert host.file('/jenkins/jobs').group == 'jenkins' 48 | assert host.file('/jenkins/jobs/test_job').is_directory 49 | assert host.file('/jenkins/jobs/test_job').user == 'jenkins' 50 | assert host.file('/jenkins/jobs/test_job').group == 'jenkins' 51 | test_job_config_file = host.file('/jenkins/jobs/test_job/config.xml') 52 | assert test_job_config_file.is_file 53 | assert test_job_config_file.user == 'jenkins' 54 | assert test_job_config_file.group == 'jenkins' 55 | 56 | 57 | def test_jenkins_custom_files(host): 58 | assert host.file('/jenkins/userContent').is_directory 59 | assert host.file('/jenkins/userContent').user == 'jenkins' 60 | assert host.file('/jenkins/userContent').group == 'jenkins' 61 | assert host.file('/jenkins/userContent/index.html').is_file 62 | assert host.file('/jenkins/userContent/index.html').user == 'jenkins' 63 | assert host.file('/jenkins/userContent/index.html').group == 'jenkins' 64 | 65 | 66 | def test_jenkins_java_process(host): 67 | process = host.process.get(command='/usr/bin/java') 68 | 69 | assert '-Djenkins.install.runSetupWizard=false' in process.args 70 | 71 | 72 | def test_jenkins_version(): 73 | master = Jenkins('http://127.0.0.1:8080') 74 | version = master.get_version() 75 | 76 | assert version == '2.176.1' 77 | 78 | 79 | def test_jenkins_plugins(): 80 | master = Jenkins('http://127.0.0.1:8080') 81 | plugins = master.get_plugins() 82 | 83 | assert plugins['git']['active'] 84 | assert plugins['git']['enabled'] 85 | 86 | 87 | def test_jenkins_jobs(): 88 | master = Jenkins('http://127.0.0.1:8080') 89 | test_job = master.get_job_info('test_job') 90 | 91 | assert test_job['name'] == 'test_job' 92 | assert test_job['buildable'] 93 | -------------------------------------------------------------------------------- /molecule/https/Dockerfile.j2: -------------------------------------------------------------------------------- 1 | # Molecule managed 2 | 3 | {% if item.registry is defined %} 4 | FROM {{ item.registry.url }}/{{ item.image }} 5 | {% else %} 6 | FROM {{ item.image }} 7 | {% endif %} 8 | 9 | RUN apt-get update && \ 10 | apt-get install -y apt-transport-https aptitude bash ca-certificates sudo python \ 11 | python-apt && \ 12 | apt-get clean 13 | 14 | RUN useradd -G sudo molecule 15 | -------------------------------------------------------------------------------- /molecule/https/jenkins-configs/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2.190.2 5 | RESTART 6 | 1 7 | EXCLUSIVE 8 | true 9 | 10 | 11 | false 12 | false 13 | 14 | false 15 | 16 | ${JENKINS_HOME}/workspace/${ITEM_FULLNAME} 17 | ${ITEM_ROOTDIR}/builds 18 | 19 | 20 | 21 | 22 | 23 | 0 24 | 0 25 | 26 | 27 | 28 | all 29 | false 30 | false 31 | 32 | 33 | 34 | all 35 | 0 36 | 37 | JNLP-connect 38 | JNLP2-connect 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /molecule/https/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: 7 | name: yamllint 8 | platforms: 9 | - name: instance 10 | image: ubuntu:16.04 11 | privileged: true 12 | exposed_ports: 13 | - 8080/tcp 14 | published_ports: 15 | - 0.0.0.0:8080:8080/tcp 16 | env: 17 | JENKINS_HOME: /jenkins 18 | provisioner: 19 | name: ansible 20 | log: true 21 | lint: 22 | name: ansible-lint 23 | options: 24 | # E602: Don't compare to empty string 25 | # All workarounds for this are uglier than just comparing to empty strings. See: 26 | # https://github.com/ansible/ansible-lint/issues/457 27 | x: ['602'] 28 | verifier: 29 | name: testinfra 30 | env: 31 | # Instruct the python-jenkins library to ignore SSL verification errors, which are 32 | # caused by the self-signed certificate. 33 | PYTHONHTTPSVERIFY: "0" 34 | lint: 35 | name: flake8 36 | -------------------------------------------------------------------------------- /molecule/https/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | vars: 5 | jenkins_auth: "none" 6 | jenkins_config_owner: "jenkins" 7 | jenkins_config_group: "jenkins" 8 | jenkins_home: "/jenkins" 9 | jenkins_https_keystore: "{{ playbook_dir }}/ssl/test-cert.jks" 10 | # NOTE: For testing purposes, we are using a self-signed certificate with the password 11 | # of "password". You are of course advised to store such data in an Ansible vault. 12 | jenkins_https_keystore_password: "password" 13 | jenkins_https_validate_certs: false 14 | jenkins_install_via: "apt" 15 | jenkins_port: "-1" 16 | jenkins_port_https: "8080" 17 | jenkins_version: "2.190.2" 18 | roles: 19 | - ansible-jenkins 20 | -------------------------------------------------------------------------------- /molecule/https/ssl/test-cert.jks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/emmetog/ansible-jenkins/d58fa96e1bcf37adf1fc34e191286043d1b4c9a4/molecule/https/ssl/test-cert.jks -------------------------------------------------------------------------------- /molecule/https/tests/.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/ 2 | -------------------------------------------------------------------------------- /molecule/https/tests/test_default.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import testinfra.utils.ansible_runner 4 | 5 | from jenkins import Jenkins 6 | 7 | 8 | testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner( 9 | os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all') 10 | 11 | 12 | def test_jenkins_installed(host): 13 | package = host.package('jenkins') 14 | 15 | assert package.is_installed 16 | 17 | 18 | def test_jenkins_version(): 19 | master = Jenkins('https://127.0.0.1:8080') 20 | version = master.get_version() 21 | 22 | assert version == '2.190.2' 23 | 24 | 25 | def test_jenkins_java_process(host): 26 | process = host.process.get(command='/usr/bin/java') 27 | 28 | assert '-Djenkins.install.runSetupWizard=false' in process.args 29 | assert '--httpsKeyStore=/jenkins/secrets/test-cert.jks' in process.args 30 | assert '--httpsKeyStorePassword=password' in process.args 31 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ansible==2.9.20 2 | docker-py==1.10.6 3 | molecule==2.22 4 | python-jenkins==1.5.0 5 | testinfra==3.2.0 6 | -------------------------------------------------------------------------------- /tasks/apt/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create Jenkins group 3 | group: 4 | name: "{{ jenkins_config_group }}" 5 | state: present 6 | 7 | - name: Create Jenkins user 8 | user: 9 | name: "{{ jenkins_config_owner }}" 10 | group: "{{ jenkins_config_group }}" 11 | home: "{{ jenkins_home }}" 12 | shell: "/bin/false" 13 | state: present 14 | 15 | # This package is only available for Xenial (16.04), see: 16 | # https://packages.ubuntu.com/search?keywords=python-software-properties 17 | - name: Install apt PPA dependencies 18 | apt: 19 | name: python-software-properties 20 | when: ansible_distribution_release == "xenial" 21 | 22 | - name: Install the Debian keyring 23 | apt: 24 | name: debian-archive-keyring 25 | 26 | - name: Add apt keys for debian repositories 27 | apt_key: 28 | keyserver: keyserver.ubuntu.com 29 | id: "{{ key_item }}" 30 | with_items: 31 | - "04EE7237B7D453EC" 32 | - "648ACFD622F3D138" 33 | loop_control: 34 | loop_var: key_item 35 | 36 | - name: Add Debian experimental repository for OpenJDK 37 | apt_repository: 38 | repo: deb http://httpredir.debian.org/debian experimental main 39 | state: present 40 | 41 | - name: Add Debian sid repository for OpenJDK 42 | apt_repository: 43 | repo: deb http://httpredir.debian.org/debian sid main 44 | state: present 45 | 46 | - name: Create pinning file for apt 47 | copy: 48 | src: files/apt/debian-package-pins 49 | dest: /etc/apt/preferences.d/debian 50 | owner: root 51 | group: root 52 | mode: 0644 53 | 54 | - name: Install apt packages 55 | apt: 56 | name: "{{ jenkins_apt_packages }}" 57 | state: present 58 | 59 | - name: Set default Java version 60 | shell: /usr/sbin/update-java-alternatives -s "{{ jenkins_java_version }}" # noqa 305 61 | ignore_errors: true 62 | changed_when: false 63 | 64 | - name: Add Jenkins key 65 | apt_key: 66 | url: "https://pkg.jenkins.io/debian-stable/jenkins.io.key" 67 | state: present 68 | 69 | - name: Add Jenkins repository 70 | apt_repository: 71 | repo: 'deb https://pkg.jenkins.io/debian-stable binary/' 72 | state: present 73 | 74 | - name: Install Jenkins binary package 75 | apt: 76 | name: "jenkins={{ jenkins_version }}" 77 | update_cache: true 78 | -------------------------------------------------------------------------------- /tasks/apt/start.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Jenkins is started 3 | service: 4 | name: jenkins 5 | state: started 6 | changed_when: false 7 | -------------------------------------------------------------------------------- /tasks/apt/stop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Jenkins is stopped 3 | service: 4 | name: jenkins 5 | state: stopped 6 | changed_when: false 7 | 8 | - name: Wait for Jenkins to stop 9 | wait_for: 10 | timeout: 5 11 | -------------------------------------------------------------------------------- /tasks/cancel-quiet-mode.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Cancel quiet mode with API token 3 | uri: 4 | url: "{{ jenkins_url }}/cancelQuietDown" 5 | method: POST 6 | headers: 7 | Content-Type: "text/xml" 8 | status_code: 200,302 9 | url_username: "{{ jenkins_api_username }}" 10 | url_password: "{{ jenkins_api_token }}" 11 | force_basic_auth: true 12 | validate_certs: "{{ jenkins_https_validate_certs }}" 13 | when: jenkins_auth == "api" 14 | 15 | - include_tasks: "get-crumb.yml" 16 | when: jenkins_auth == "crumb" 17 | 18 | - name: Cancel quiet mode with crumb 19 | uri: 20 | url: "{{ jenkins_url }}/cancelQuietDown" 21 | method: POST 22 | headers: 23 | Content-Type: "text/xml" 24 | Cookie: "{{ jenkins_crumb_cookie }}" 25 | Jenkins-Crumb: "{{ jenkins_crumb_token }}" 26 | status_code: 200,302 27 | validate_certs: "{{ jenkins_https_validate_certs }}" 28 | when: jenkins_auth == "crumb" 29 | 30 | - name: Cancel quiet mode with no security 31 | uri: 32 | url: "{{ jenkins_url }}/cancelQuietDown" 33 | method: POST 34 | headers: 35 | Content-Type: "text/xml" 36 | status_code: 200,302 37 | validate_certs: "{{ jenkins_https_validate_certs }}" 38 | when: jenkins_auth == "none" 39 | -------------------------------------------------------------------------------- /tasks/configure-files.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: "{{ jenkins_install_via }}/stop.yml" 3 | 4 | - name: Create intermediate dirs for custom files 5 | file: 6 | path: "{{ jenkins_home }}/{{ item.dest | dirname }}" 7 | owner: "{{ jenkins_config_owner }}" 8 | group: "{{ jenkins_config_group }}" 9 | mode: 0755 10 | state: directory 11 | with_items: "{{ jenkins_custom_files }}" 12 | 13 | - name: Configure custom files 14 | template: 15 | src: "{{ jenkins_source_dir_configs }}/{{ item.src }}" 16 | dest: "{{ jenkins_home }}/{{ item.dest }}" 17 | mode: 0644 18 | owner: "{{ jenkins_config_owner }}" 19 | group: "{{ jenkins_config_group }}" 20 | with_items: "{{ jenkins_custom_files }}" 21 | -------------------------------------------------------------------------------- /tasks/configure-jenkins.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Jenkins should not be running while we write configuration files, otherwise 3 | # otherwise some data might be overwritten when it restarts. 4 | - include_tasks: "{{ jenkins_install_via }}/stop.yml" 5 | 6 | - name: Set JENKINS_HOME 7 | lineinfile: 8 | create: true 9 | dest: "/etc/default/jenkins" 10 | line: "JENKINS_HOME={{ jenkins_home }}" 11 | regexp: '^JENKINS_HOME=' 12 | state: present 13 | when: jenkins_install_via != "docker" 14 | 15 | - name: Set Jenkins port for HTTP 16 | lineinfile: 17 | dest: /etc/default/jenkins 18 | regexp: '^HTTP_PORT=' 19 | line: "HTTP_PORT={{ jenkins_port }}" 20 | when: jenkins_install_via != "docker" 21 | 22 | - name: Set Jenkins port for HTTPS 23 | lineinfile: 24 | dest: /etc/default/jenkins 25 | regexp: '^HTTPS_PORT=' 26 | insertafter: '^HTTP_PORT=' 27 | line: "HTTPS_PORT={{ jenkins_port_https }}" 28 | when: jenkins_install_via != "docker" 29 | 30 | - name: Set Jenkins Java command line options 31 | lineinfile: 32 | dest: /etc/default/jenkins 33 | regexp: '^JAVA_ARGS=' 34 | line: "JAVA_ARGS=\"{{ jenkins_java_opts }}\"" 35 | when: jenkins_install_via != "docker" 36 | 37 | - name: Ensure correct ownership of JENKINS_HOME directory 38 | file: 39 | path: "{{ jenkins_home }}" 40 | owner: "{{ jenkins_config_owner }}" 41 | group: "{{ jenkins_config_group }}" 42 | mode: 0755 43 | state: directory 44 | 45 | - name: Ensure main configuration file is up to date 46 | template: 47 | src: "{{ jenkins_source_config_xml }}" 48 | dest: "{{ jenkins_home }}/config.xml" 49 | owner: "{{ jenkins_config_owner }}" 50 | group: "{{ jenkins_config_group }}" 51 | mode: 0644 52 | 53 | - name: Configure Jenkins location 54 | template: 55 | src: files/jenkins.model.JenkinsLocationConfiguration.xml.j2 56 | dest: "{{ jenkins_home }}/jenkins.model.JenkinsLocationConfiguration.xml" 57 | owner: "{{ jenkins_config_owner }}" 58 | group: "{{ jenkins_config_group }}" 59 | mode: 0644 60 | 61 | - name: Initialize Jenkins secrets dir fact 62 | set_fact: 63 | jenkins_secrets: "{{ jenkins_home }}/secrets" 64 | 65 | - name: Copy secrets 66 | copy: 67 | src: "{{ jenkins_source_secrets }}" 68 | dest: "{{ jenkins_secrets }}" 69 | owner: "{{ jenkins_config_owner }}" 70 | group: "{{ jenkins_config_group }}" 71 | when: jenkins_include_secrets 72 | 73 | - name: Ensure correct ownership of secrets directory 74 | file: 75 | path: "{{ jenkins_secrets }}" 76 | owner: "{{ jenkins_config_owner }}" 77 | group: "{{ jenkins_config_group }}" 78 | mode: 0700 79 | state: directory 80 | 81 | - name: Copy JKS keystore credentials 82 | copy: 83 | src: "{{ jenkins_https_keystore }}" 84 | dest: "{{ jenkins_secrets }}/" 85 | when: jenkins_https_keystore and jenkins_https_keystore_password 86 | 87 | - name: Copy CA signed certificate 88 | copy: 89 | src: "{{ jenkins_https_certificate }}" 90 | dest: "{{ jenkins_secrets }}/" 91 | when: jenkins_https_certificate and jenkins_https_private_key 92 | 93 | - name: Copy CA certificate private key 94 | copy: 95 | src: "{{ jenkins_https_private_key }}" 96 | dest: "{{ jenkins_secrets }}/" 97 | when: jenkins_https_certificate and jenkins_https_private_key 98 | 99 | - name: Initialize HTTPS credentials fact 100 | set_fact: 101 | jenkins_https_creds: "" 102 | 103 | - name: Set JKS keystore credentials 104 | set_fact: 105 | jenkins_https_creds: >- 106 | --httpsKeyStore='{{ jenkins_secrets }}/{{ jenkins_https_keystore | basename }}' 107 | --httpsKeyStorePassword='{{ jenkins_https_keystore_password }}' 108 | when: jenkins_https_keystore and jenkins_https_keystore_password 109 | 110 | # This fact prevents the next task from going over >90 chars 111 | - name: Set fact for HTTPS certificate file 112 | set_fact: 113 | jenkins_https_certificate_file: >- 114 | {{ jenkins_secrets }}/{{ jenkins_https_certificate | basename }} 115 | when: jenkins_https_certificate and jenkins_https_private_key 116 | 117 | - name: Set CA signed certificate credentials 118 | set_fact: 119 | jenkins_https_creds: >- 120 | --httpsCertificate='{{ jenkins_https_certificate_file }}' 121 | --httpsPrivateKey='{{ jenkins_secrets }}/{{ jenkins_https_private_key | basename }}' 122 | when: jenkins_https_certificate and jenkins_https_private_key 123 | 124 | - name: Set Jenkins command line options 125 | lineinfile: 126 | dest: /etc/default/jenkins 127 | regexp: '^JENKINS_ARGS=' 128 | line: "JENKINS_ARGS=\"--webroot=/var/cache/$NAME/war --httpPort=$HTTP_PORT \ 129 | --httpsPort=$HTTPS_PORT {{ jenkins_https_creds }}\"" 130 | -------------------------------------------------------------------------------- /tasks/configure-jobs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # First, make sure that Jenkins is stopped before attempting to copy any job 3 | # configuration files. 4 | - include_tasks: "{{ jenkins_install_via }}/stop.yml" 5 | 6 | - name: Job directories are present 7 | file: 8 | path: "{{ jenkins_home }}/jobs/{{ item }}" 9 | state: directory 10 | mode: 0777 11 | owner: "{{ jenkins_config_owner }}" 12 | group: "{{ jenkins_config_group }}" 13 | with_items: "{{ jenkins_jobs }}" 14 | 15 | - name: Jobs are present 16 | copy: 17 | src: "{{ jenkins_source_dir_jobs }}/{{ item }}/config.xml" 18 | dest: "{{ jenkins_home }}/jobs/{{ item }}/config.xml" 19 | mode: 0777 20 | owner: "{{ jenkins_config_owner }}" 21 | group: "{{ jenkins_config_group }}" 22 | with_items: "{{ jenkins_jobs }}" 23 | -------------------------------------------------------------------------------- /tasks/configure-plugins.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Custom plugins are installed 3 | copy: 4 | src: "{{ item }}" 5 | dest: "{{ jenkins_home }}/plugins/" 6 | owner: "{{ jenkins_config_owner }}" 7 | group: "{{ jenkins_config_group }}" 8 | mode: 0644 9 | with_items: "{{ jenkins_custom_plugins }}" 10 | when: jenkins_custom_plugins is defined 11 | 12 | # Jenkins must be running in order to install plugins from the internet, but 13 | # we should put it into quiet mode immediately to avoid any jobs being 14 | # scheduled. 15 | - include_tasks: "start.yml" 16 | - include_tasks: "set-quiet-mode.yml" 17 | 18 | - name: Install plugins with API token 19 | jenkins_plugin: 20 | name: "{{ item }}" 21 | jenkins_home: "{{ jenkins_home }}" 22 | owner: "{{ jenkins_config_owner }}" 23 | group: "{{ jenkins_config_group }}" 24 | url: "{{ jenkins_url }}" 25 | timeout: "{{ jenkins_plugin_timeout }}" 26 | url_username: "{{ jenkins_api_username }}" 27 | url_password: "{{ jenkins_api_token }}" 28 | force_basic_auth: true 29 | validate_certs: "{{ jenkins_https_validate_certs }}" 30 | with_items: "{{ jenkins_plugins }}" 31 | when: jenkins_auth == "api" 32 | 33 | # As of Jenkins 2.176.2, installing plugins requires a crumb. The jenkins_plugin module 34 | # will get its own crumb for this, but only in Ansible 2.9 and newer. So if you are 35 | # seeing crumb-related errors during deployments while installing plugins, either 36 | # update your Ansible or switch to API-based authentication. 37 | - name: Install plugins without an API token 38 | jenkins_plugin: 39 | name: "{{ item }}" 40 | jenkins_home: "{{ jenkins_home }}" 41 | owner: "{{ jenkins_config_owner }}" 42 | group: "{{ jenkins_config_group }}" 43 | url: "{{ jenkins_url }}" 44 | timeout: "{{ jenkins_plugin_timeout }}" 45 | validate_certs: "{{ jenkins_https_validate_certs }}" 46 | with_items: "{{ jenkins_plugins }}" 47 | when: jenkins_auth == "crumb" or jenkins_auth == "none" 48 | 49 | - name: Wait for plugins to finish installing 50 | wait_for: 51 | path: "{{ jenkins_home }}/plugins/{{ item }}.jpi" 52 | with_items: "{{ jenkins_plugins }}" 53 | -------------------------------------------------------------------------------- /tasks/docker/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure jenkins home dir is created 3 | file: 4 | path: "{{ jenkins_home }}" 5 | mode: 0777 6 | owner: "{{ jenkins_config_owner }}" 7 | group: "{{ jenkins_config_group }}" 8 | state: directory 9 | 10 | - name: Container is running (with ingress port) 11 | docker_container: 12 | name: "{{ jenkins_docker_container_name }}" 13 | image: "{{ jenkins_docker_image }}:{{ jenkins_version }}" 14 | published_ports: 15 | - "{{ jenkins_port }}:8080" 16 | volumes: 17 | - "{{ jenkins_home }}:/var/jenkins_home" 18 | env: 19 | JAVA_OPTS: "{{ jenkins_java_opts }}" 20 | register: container_result 21 | when: jenkins_docker_expose_port 22 | 23 | - name: Container is running (without ingress port) 24 | docker_container: 25 | name: "{{ jenkins_docker_container_name }}" 26 | image: "{{ jenkins_docker_image }}:{{ jenkins_version }}" 27 | expose: "8080" 28 | volumes: 29 | - "{{ jenkins_home }}:/var/jenkins_home" 30 | env: 31 | JAVA_OPTS: "{{ jenkins_java_opts }}" 32 | register: container_result 33 | when: not jenkins_docker_expose_port 34 | 35 | - name: Pause container # noqa 503 36 | pause: 37 | seconds: 45 38 | when: container_result|changed 39 | -------------------------------------------------------------------------------- /tasks/docker/start.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Container is running (with ingress port) 3 | docker_container: 4 | name: "{{ jenkins_docker_container_name }}" 5 | image: "{{ jenkins_docker_image }}:{{ jenkins_version }}" 6 | published_ports: 7 | - "{{ jenkins_port }}:8080" 8 | volumes: 9 | - "{{ jenkins_home }}:/var/jenkins_home" 10 | env: 11 | JAVA_OPTS: "{{ jenkins_java_opts }}" 12 | register: container_result 13 | when: jenkins_docker_expose_port 14 | 15 | - name: Container is running (without ingress port) 16 | docker_container: 17 | name: "{{ jenkins_docker_container_name }}" 18 | image: "{{ jenkins_docker_image }}:{{ jenkins_version }}" 19 | expose: "8080" 20 | volumes: 21 | - "{{ jenkins_home }}:/var/jenkins_home" 22 | env: 23 | JAVA_OPTS: "{{ jenkins_java_opts }}" 24 | register: container_result 25 | when: not jenkins_docker_expose_port 26 | -------------------------------------------------------------------------------- /tasks/docker/stop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Container is stopped 3 | docker_container: 4 | name: "{{ jenkins_docker_container_name }}" 5 | image: "{{ jenkins_docker_image }}:{{ jenkins_version }}" 6 | published_ports: "{{ jenkins_port }}:8080" 7 | volumes: 8 | - "{{ jenkins_home }}:/var/jenkins_home" 9 | env: 10 | JAVA_OPTS: "{{ jenkins_java_opts }}" 11 | state: stopped 12 | 13 | - name: Wait for container to stop 14 | wait_for: 15 | timeout: 5 16 | -------------------------------------------------------------------------------- /tasks/get-crumb.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Get crumb for Jenkins API 3 | uri: 4 | url: '{{ jenkins_url }} 5 | /crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)' 6 | return_content: true 7 | status_code: 200,404 8 | validate_certs: "{{ jenkins_https_validate_certs }}" 9 | register: jenkins_crumb 10 | until: jenkins_crumb.status == 200 or jenkins_crumb.status == 404 11 | retries: 5 12 | delay: 1 13 | 14 | - name: Set Jenkins token from crumb 15 | set_fact: 16 | jenkins_crumb_token: "{{ jenkins_crumb.content.split(':')[1] | default('noCrumb') }}" 17 | when: jenkins_crumb.status == 200 18 | 19 | - name: Initialize Jenkins crumb cookie fact 20 | set_fact: 21 | jenkins_crumb_cookie: "" 22 | 23 | - name: Save Jenkins crumb cookie for Jenkins >= 2.176.2 24 | set_fact: 25 | jenkins_crumb_cookie: "{{ jenkins_crumb.set_cookie }}" 26 | when: > 27 | jenkins_crumb.status == 200 and jenkins_version is version_compare("2.176.2", ">=") 28 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include: "sanity-checks.yml" 3 | 4 | # Previous versions of this role defined jenkins_url as a default variable, but this URL 5 | # did not include the port, and required the user to hard-code the protocol. 6 | - name: Set jenkins_url fact for backwards-compatibility installations 7 | set_fact: 8 | jenkins_url: "{{ jenkins_url }}:{{ jenkins_port }}" 9 | when: jenkins_url is defined 10 | 11 | - name: Set jenkins_url fact for HTTP 12 | set_fact: 13 | jenkins_url: "http://{{ jenkins_hostname }}:{{ jenkins_port }}" 14 | when: jenkins_port != "-1" and jenkins_url is not defined 15 | 16 | # Note that this task will overwrite jenkins_url if both HTTP and HTTPS ports are defined. 17 | # This is by intention. 18 | - name: Set jenkins_url fact for HTTPS 19 | set_fact: 20 | jenkins_url: "https://{{ jenkins_hostname }}:{{ jenkins_port_https }}" 21 | when: jenkins_port_https != "-1" and jenkins_url is not defined 22 | 23 | - name: Set jenkins_url_health_check fact 24 | set_fact: 25 | jenkins_url_health_check: "{{ jenkins_url }}" 26 | when: jenkins_url_health_check is not defined 27 | 28 | - include: "{{ jenkins_install_via }}/install.yml" 29 | 30 | - include: "configure-jenkins.yml" 31 | 32 | - include: "configure-files.yml" 33 | when: jenkins_include_custom_files 34 | 35 | - include: "configure-plugins.yml" 36 | 37 | - include: "configure-jobs.yml" 38 | 39 | - include: "{{ jenkins_after_config_jobs_file }}" 40 | when: jenkins_after_config_jobs_file | length > 0 41 | 42 | - include: "start.yml" 43 | 44 | - include: "cancel-quiet-mode.yml" 45 | -------------------------------------------------------------------------------- /tasks/sanity-checks.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Warn if jenkins_url is defined 3 | debug: 4 | msg: "Please define jenkins_hostname instead of jenkins_url" 5 | when: jenkins_url is defined 6 | 7 | - name: Sanity check Jenkins authentication mechanism variable 8 | fail: 9 | msg: "Invalid value for jenkins_auth variable" 10 | when: jenkins_auth not in ["api", "crumb", "none"] 11 | 12 | - name: Sanity check API token 13 | fail: 14 | msg: "jenkins_api_token is required when using API-based authentication" 15 | when: jenkins_auth == "api" and jenkins_api_token == "" 16 | 17 | - name: Sanity check API username 18 | fail: 19 | msg: "jenkins_api_username is required when using API-based authentication" 20 | when: jenkins_auth == "api" and jenkins_api_username == "" 21 | -------------------------------------------------------------------------------- /tasks/set-quiet-mode.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: "get-crumb.yml" 3 | when: jenkins_auth == "crumb" 4 | 5 | - name: Set quiet mode with API token 6 | uri: 7 | url: "{{ jenkins_url }}/quietDown" 8 | method: POST 9 | headers: 10 | Content-Type: "text/xml" 11 | status_code: 200,302 12 | url_username: "{{ jenkins_api_username }}" 13 | url_password: "{{ jenkins_api_token }}" 14 | force_basic_auth: true 15 | validate_certs: "{{ jenkins_https_validate_certs }}" 16 | when: jenkins_auth == "api" 17 | 18 | - name: Set quiet mode with crumb 19 | uri: 20 | url: "{{ jenkins_url }}/quietDown" 21 | method: POST 22 | headers: 23 | Content-Type: "text/xml" 24 | Cookie: "{{ jenkins_crumb_cookie }}" 25 | Jenkins-Crumb: "{{ jenkins_crumb_token }}" 26 | status_code: 200,302 27 | validate_certs: "{{ jenkins_https_validate_certs }}" 28 | when: jenkins_auth == "crumb" 29 | 30 | - name: Set quiet mode with no security 31 | uri: 32 | url: "{{ jenkins_url }}/quietDown" 33 | method: POST 34 | headers: 35 | Content-Type: "text/xml" 36 | status_code: 200,302 37 | validate_certs: "{{ jenkins_https_validate_certs }}" 38 | when: jenkins_auth == "none" 39 | -------------------------------------------------------------------------------- /tasks/start.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: "{{ jenkins_install_via }}/start.yml" 3 | 4 | - name: Initialize jenkins_force_basic_auth parameter 5 | set_fact: 6 | jenkins_force_basic_auth: false 7 | 8 | - name: Set jenkins_force_basic_auth parameter 9 | set_fact: 10 | jenkins_force_basic_auth: true 11 | when: jenkins_health_check_user is defined 12 | 13 | - name: Wait for Jenkins to start 14 | uri: 15 | url: "{{ jenkins_url_health_check }}" 16 | url_username: "{{ jenkins_health_check_user | default(omit) }}" 17 | url_password: "{{ jenkins_health_check_password | default(omit) }}" 18 | force_basic_auth: "{{ jenkins_force_basic_auth }}" 19 | validate_certs: "{{ jenkins_https_validate_certs }}" 20 | become: false 21 | register: jenkins_home_content 22 | # Jenkins will return 503 (service unavailable) on the home page while 23 | # starting (the "Please wait while Jenkins is getting ready to work" page) 24 | until: jenkins_home_content is success and jenkins_home_content.status == 200 25 | retries: 30 26 | delay: 5 27 | -------------------------------------------------------------------------------- /tasks/yum/install.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Make sure Jenkins is stopped" 3 | service: 4 | name: "jenkins" 5 | state: "stopped" 6 | ignore_errors: true 7 | changed_when: false 8 | 9 | - name: "Create Jenkins group" 10 | group: 11 | name: "{{ jenkins_config_group }}" 12 | state: present 13 | 14 | - name: "Create Jenkins user" 15 | user: 16 | name: "{{ jenkins_config_owner }}" 17 | groups: "{{ jenkins_config_group }}" 18 | state: present 19 | 20 | - name: "Install Java and GIT" 21 | yum: 22 | name: "java" 23 | state: "present" 24 | with_items: 25 | - java 26 | - git 27 | 28 | - name: "Add Jenkins repository" 29 | get_url: 30 | url: "https://pkg.jenkins.io/redhat-stable/jenkins.repo" 31 | dest: "/etc/yum.repos.d/jenkins.repo" 32 | 33 | - name: "Import Jenkins key" 34 | command: "rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io.key" 35 | changed_when: false 36 | 37 | - name: "Install Jenkins" 38 | yum: 39 | name: jenkins-{{ jenkins_version }} 40 | state: present 41 | -------------------------------------------------------------------------------- /tasks/yum/start.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Start Jenkins" 3 | service: name="jenkins" state="started" 4 | -------------------------------------------------------------------------------- /tasks/yum/stop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Stop Jenkins" 3 | service: name="jenkins" state="stopped" 4 | --------------------------------------------------------------------------------