├── .ansible-lint ├── .github ├── FUNDING.yml └── stale.yml ├── .gitignore ├── .travis.yml ├── .yamllint ├── LICENSE ├── README.md ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── molecule └── default │ ├── converge.yml │ ├── molecule.yml │ ├── playbook-latest.yml │ ├── playbook-web-context.yml │ └── requirements.yml ├── tasks ├── configure.yml └── main.yml └── templates └── sonar.unit.j2 /.ansible-lint: -------------------------------------------------------------------------------- 1 | skip_list: 2 | - '204' 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | --- 3 | github: geerlingguy 4 | patreon: geerlingguy 5 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 90 5 | 6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 8 | daysUntilClose: 30 9 | 10 | # Only issues or pull requests with all of these labels are check if stale. Defaults to `[]` (disabled) 11 | onlyLabels: [] 12 | 13 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 14 | exemptLabels: 15 | - pinned 16 | - security 17 | - planned 18 | 19 | # Set to true to ignore issues in a project (defaults to false) 20 | exemptProjects: false 21 | 22 | # Set to true to ignore issues in a milestone (defaults to false) 23 | exemptMilestones: false 24 | 25 | # Set to true to ignore issues with an assignee (defaults to false) 26 | exemptAssignees: false 27 | 28 | # Label to use when marking as stale 29 | staleLabel: stale 30 | 31 | # Limit the number of actions per hour, from 1-30. Default is 30 32 | limitPerRun: 30 33 | 34 | pulls: 35 | markComment: |- 36 | This pull request has been marked 'stale' due to lack of recent activity. If there is no further activity, the PR will be closed in another 30 days. Thank you for your contribution! 37 | 38 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark pull requests as stale. 39 | 40 | unmarkComment: >- 41 | This pull request is no longer marked for closure. 42 | 43 | closeComment: >- 44 | This pull request has been closed due to inactivity. If you feel this is in error, please reopen the pull request or file a new PR with the relevant details. 45 | 46 | issues: 47 | markComment: |- 48 | This issue has been marked 'stale' due to lack of recent activity. If there is no further activity, the issue will be closed in another 30 days. Thank you for your contribution! 49 | 50 | Please read [this blog post](https://www.jeffgeerling.com/blog/2020/enabling-stale-issue-bot-on-my-github-repositories) to see the reasons why I mark issues as stale. 51 | 52 | unmarkComment: >- 53 | This issue is no longer marked for closure. 54 | 55 | closeComment: >- 56 | This issue has been closed due to inactivity. If you feel this is in error, please reopen the issue or file a new issue with the relevant details. 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.retry 2 | */__pycache__ 3 | *.pyc 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: python 3 | services: docker 4 | 5 | env: 6 | global: 7 | - ROLE_NAME: sonar 8 | matrix: 9 | # LTS. 10 | - MOLECULE_DISTRO: centos7 11 | - MOLECULE_DISTRO: ubuntu1804 12 | 13 | # Latest. 14 | - MOLECULE_DISTRO: centos7 15 | MOLECULE_PLAYBOOK: playbook-latest.yml 16 | - MOLECULE_DISTRO: ubuntu1804 17 | MOLECULE_PLAYBOOK: playbook-latest.yml 18 | 19 | # Web Context. 20 | - MOLECULE_DISTRO: ubuntu1804 21 | MOLECULE_PLAYBOOK: playbook-web-context.yml 22 | 23 | install: 24 | # Install test dependencies. 25 | - pip install molecule yamllint ansible-lint docker 26 | 27 | before_script: 28 | # Use actual Ansible Galaxy role name for the project directory. 29 | - cd ../ 30 | - mv ansible-role-$ROLE_NAME geerlingguy.$ROLE_NAME 31 | - cd geerlingguy.$ROLE_NAME 32 | 33 | script: 34 | # Run tests. 35 | - molecule test 36 | 37 | notifications: 38 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ 39 | -------------------------------------------------------------------------------- /.yamllint: -------------------------------------------------------------------------------- 1 | --- 2 | extends: default 3 | rules: 4 | line-length: 5 | max: 210 6 | level: warning 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Jeff Geerling 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | 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, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible Role: SonarQube 2 | 3 | [![Build Status](https://travis-ci.org/geerlingguy/ansible-role-sonar.svg?branch=master)](https://travis-ci.org/geerlingguy/ansible-role-sonar) 4 | 5 | > **DEPRECATED**: This role is no longer actively maintained. It may still work, but I have marked it as 'deprecated' on Ansible Galaxy, and recommend you find a new role to replace it, or fork it and use your fork. 6 | 7 | An Ansible Role that installs [SonarQube](http://www.sonarqube.org/) on RedHat/CentOS and Debian/Ubuntu Linux servers. 8 | 9 | ## Requirements 10 | 11 | Requires the `unzip` utility to be installed on the server. Also, different SonarQube versions require different minimum versions of Java: 12 | 13 | - SonarQube 5.0-5.5 requires Java 1.7+ 14 | - SonarQube 5.6+ requires Java 1.8+ 15 | 16 | Finally, recent versions of SonarQube also require MySQL 5.6 or later. 17 | 18 | ## Role Variables 19 | 20 | Available variables are listed below, along with default values: 21 | 22 | workspace: /root 23 | 24 | Directory where downloaded files will be temporarily stored. 25 | 26 | sonar_download_validate_certs: true 27 | 28 | Controls whether to validate certificates when downloading SonarQube. 29 | 30 | sonar_download_url: http://dist.sonar.codehaus.org/sonarqube-4.5.4.zip 31 | sonar_version_directory: sonarqube-4.5.4 32 | 33 | The URL from which SonarQube will be downloaded, and the resulting directory name (should match the download archive, without the archive extension). 34 | 35 | sonar_web_context: '' 36 | 37 | The value of `sonar.web.context`. Setting this to something like `/sonar` allows you to set the context where Sonar can be accessed (e.g. `hostname/sonar` instead of `hostname`). 38 | 39 | sonar_mysql_username: sonar 40 | sonar_mysql_password: sonar 41 | 42 | sonar_mysql_host: localhost 43 | sonar_mysql_port: "3306" 44 | sonar_mysql_database: sonar 45 | 46 | sonar_mysql_allowed_hosts: 47 | - 127.0.0.1 48 | - ::1 49 | - localhost 50 | 51 | JDBC settings for a connection to a MySQL database. Defaults presume the database resides on localhost and is only accessible on the SonarQube server itself. 52 | 53 | ## Dependencies 54 | 55 | - geerlingguy.java 56 | - geerlingguy.mysql 57 | 58 | ## Example Playbook 59 | 60 | - hosts: all 61 | roles: 62 | - geerlingguy.sonar 63 | 64 | Using the defaults, you can view the SonarQube home at `http://localhost:9000/` (default System administrator credentials are `admin`/`admin`). 65 | 66 | ## License 67 | 68 | MIT / BSD 69 | 70 | ## Author Information 71 | 72 | This role was created in 2014 by [Jeff Geerling](https://www.jeffgeerling.com/), author of [Ansible for DevOps](https://www.ansiblefordevops.com/). 73 | -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | workspace: /root 3 | sonar_download_validate_certs: true 4 | 5 | # Default to the latest LTS release. 6 | sonar_version: 4.5.6 7 | sonar_download_url: "https://binaries.sonarsource.com/Distribution/sonarqube/sonarqube-{{ sonar_version }}.zip" 8 | sonar_version_directory: "sonarqube-{{ sonar_version }}" 9 | 10 | sonar_web_context: '' 11 | 12 | # MySQL database connection details. 13 | sonar_mysql_username: sonar 14 | sonar_mysql_password: sonar 15 | 16 | sonar_mysql_host: localhost 17 | sonar_mysql_port: "3306" 18 | sonar_mysql_database: sonar 19 | 20 | sonar_mysql_allowed_hosts: 21 | - "127.0.0.1" 22 | - "::1" 23 | - "localhost" 24 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: restart sonar 3 | service: name=sonar state=restarted 4 | notify: wait for sonar 5 | 6 | - name: wait for sonar 7 | wait_for: port=9000 delay=3 timeout=300 8 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependencies: 3 | - geerlingguy.java 4 | - geerlingguy.mysql 5 | 6 | galaxy_info: 7 | author: geerlingguy 8 | description: SonarQube for Linux 9 | company: "Midwestern Mac, LLC" 10 | license: "license (BSD, MIT)" 11 | min_ansible_version: 2.0 12 | platforms: 13 | - name: EL 14 | versions: 15 | - all 16 | - name: Debian 17 | versions: 18 | - all 19 | - name: Ubuntu 20 | versions: 21 | - all 22 | galaxy_tags: 23 | - development 24 | - monitoring 25 | - sonar 26 | - sonarqube 27 | - codequality 28 | - scanner 29 | -------------------------------------------------------------------------------- /molecule/default/converge.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | become: true 5 | 6 | vars: 7 | mysql_python_package_debian: python3-mysqldb 8 | 9 | pre_tasks: 10 | - name: Update apt cache. 11 | apt: update_cache=true cache_valid_time=600 12 | when: ansible_os_family == 'Debian' 13 | 14 | - name: Install dependencies. 15 | package: 16 | name: 17 | - curl 18 | - unzip 19 | state: present 20 | 21 | roles: 22 | - role: geerlingguy.java 23 | - role: geerlingguy.mysql 24 | - role: geerlingguy.sonar 25 | 26 | post_tasks: 27 | - name: Ensure SonarQube is running. 28 | uri: 29 | url: "http://127.0.0.1:9000/" 30 | status_code: 200 31 | register: result 32 | until: result.status == 200 33 | retries: 60 34 | delay: 1 35 | -------------------------------------------------------------------------------- /molecule/default/molecule.yml: -------------------------------------------------------------------------------- 1 | --- 2 | dependency: 3 | name: galaxy 4 | driver: 5 | name: docker 6 | lint: | 7 | set -e 8 | yamllint . 9 | ansible-lint 10 | platforms: 11 | - name: instance 12 | image: "geerlingguy/docker-${MOLECULE_DISTRO:-centos7}-ansible:latest" 13 | command: ${MOLECULE_DOCKER_COMMAND:-""} 14 | volumes: 15 | - /sys/fs/cgroup:/sys/fs/cgroup:ro 16 | privileged: true 17 | pre_build_image: true 18 | provisioner: 19 | name: ansible 20 | playbooks: 21 | converge: ${MOLECULE_PLAYBOOK:-converge.yml} 22 | -------------------------------------------------------------------------------- /molecule/default/playbook-latest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Converge 3 | hosts: all 4 | become: true 5 | 6 | vars: 7 | # Latest version of SonarQube, from http://www.sonarqube.org/downloads/ 8 | sonar_version: 5.6.1 9 | mysql_python_package_debian: python3-mysqldb 10 | 11 | pre_tasks: 12 | - name: Update apt cache. 13 | apt: update_cache=true cache_valid_time=600 14 | when: ansible_os_family == 'Debian' 15 | changed_when: false 16 | 17 | - name: Install dependencies. 18 | package: 19 | name: 20 | - curl 21 | - unzip 22 | state: present 23 | 24 | - name: Add repository for OpenJDK 8 (Ubuntu 14). 25 | apt_repository: repo='ppa:openjdk-r/ppa' 26 | when: 27 | - ansible_os_family == "Debian" 28 | - ansible_distribution_version == "14.04" 29 | 30 | - name: Install the MySQL repo (RedHat). 31 | yum: 32 | name: http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 33 | state: present 34 | when: ansible_os_family == "RedHat" 35 | 36 | - name: Override variables for MySQL (RedHat). 37 | set_fact: 38 | mysql_daemon: mysqld 39 | mysql_packages: ['mysql-server'] 40 | mysql_log_error: /var/log/mysqld.err 41 | mysql_syslog_tag: mysqld 42 | mysql_pid_file: /var/run/mysqld/mysqld.pid 43 | mysql_socket: /var/lib/mysql/mysql.sock 44 | when: ansible_os_family == "RedHat" 45 | 46 | roles: 47 | - role: geerlingguy.java 48 | when: "ansible_os_family == 'RedHat'" 49 | java_packages: 50 | - java-1.8.0-openjdk 51 | 52 | - role: geerlingguy.java 53 | when: "ansible_os_family == 'Debian'" 54 | java_packages: 55 | - openjdk-8-jdk 56 | 57 | - role: geerlingguy.mysql 58 | - role: geerlingguy.sonar 59 | 60 | post_tasks: 61 | - name: Ensure SonarQube is running. 62 | uri: 63 | url: "http://127.0.0.1:9000/" 64 | status_code: 200 65 | register: result 66 | until: result.status == 200 67 | retries: 60 68 | delay: 1 69 | -------------------------------------------------------------------------------- /molecule/default/playbook-web-context.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: all 3 | 4 | vars: 5 | sonar_web_context: "/sonar" 6 | mysql_python_package_debian: python3-mysqldb 7 | 8 | pre_tasks: 9 | - name: Update apt cache. 10 | apt: update_cache=true cache_valid_time=600 11 | when: ansible_os_family == 'Debian' 12 | 13 | - name: Install dependencies. 14 | package: 15 | name: 16 | - curl 17 | - unzip 18 | state: present 19 | 20 | roles: 21 | - role: geerlingguy.java 22 | - role: geerlingguy.mysql 23 | - role: geerlingguy.sonar 24 | 25 | post_tasks: 26 | - name: Ensure SonarQube is running. 27 | uri: 28 | url: "http://127.0.0.1:9000{{ sonar_web_context }}" 29 | status_code: 200 30 | register: result 31 | until: result.status == 200 32 | retries: 60 33 | delay: 1 34 | -------------------------------------------------------------------------------- /molecule/default/requirements.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - src: geerlingguy.repo-remi 3 | - src: geerlingguy.java 4 | - src: geerlingguy.mysql 5 | -------------------------------------------------------------------------------- /tasks/configure.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure SonarQube JDBC settings for MySQL. 3 | lineinfile: 4 | dest: /usr/local/sonar/conf/sonar.properties 5 | regexp: "{{ item.regexp }}" 6 | line: "{{ item.line }}" 7 | notify: restart sonar 8 | with_items: 9 | - regexp: "^sonar.jdbc.username" 10 | line: "sonar.jdbc.username={{ sonar_mysql_username }}" 11 | - regexp: "^sonar.jdbc.password" 12 | line: "sonar.jdbc.password={{ sonar_mysql_password }}" 13 | - regexp: "^sonar.jdbc.url" 14 | line: "sonar.jdbc.url=jdbc:mysql://{{ sonar_mysql_host }}:{{ sonar_mysql_port }}/{{ sonar_mysql_database }}?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true&useConfigs=maxPerformance" 15 | - regexp: "^sonar.web.context" 16 | line: "sonar.web.context={{ sonar_web_context }}" 17 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Create a database for Sonar. 3 | mysql_db: 4 | name: "{{ sonar_mysql_database }}" 5 | state: present 6 | 7 | - name: Create a sonar user. 8 | mysql_user: 9 | name: "{{ sonar_mysql_username }}" 10 | host: "{{ item }}" 11 | priv: "{{ sonar_mysql_database }}.*:ALL" 12 | password: "{{ sonar_mysql_password }}" 13 | with_items: "{{ sonar_mysql_allowed_hosts }}" 14 | 15 | - name: Download Sonar. 16 | get_url: 17 | url: "{{ sonar_download_url }}" 18 | dest: "{{ workspace }}/{{ sonar_version_directory }}.zip" 19 | validate_certs: "{{ sonar_download_validate_certs }}" 20 | 21 | - name: Unzip Sonar. 22 | unarchive: 23 | src: "{{ workspace }}/{{ sonar_version_directory }}.zip" 24 | dest: /usr/local/ 25 | copy: false 26 | creates: /usr/local/sonar/COPYING 27 | 28 | - name: Move Sonar into place. 29 | command: > 30 | mv /usr/local/{{ sonar_version_directory }} /usr/local/sonar 31 | creates=/usr/local/sonar/COPYING 32 | 33 | - include: configure.yml 34 | 35 | - name: Symlink sonar bin. 36 | file: 37 | src: /usr/local/sonar/bin/linux-x86-64/sonar.sh 38 | dest: /usr/bin/sonar 39 | state: link 40 | register: sonar_symlink 41 | 42 | - name: Add sonar as init script for service management. 43 | file: 44 | src: /usr/local/sonar/bin/linux-x86-64/sonar.sh 45 | dest: /etc/init.d/sonar 46 | state: link 47 | when: "ansible_service_mgr != 'systemd'" 48 | 49 | - name: Copy SonarQube systemd unit file into place (for systemd systems). 50 | template: 51 | src: sonar.unit.j2 52 | dest: /etc/systemd/system/sonar.service 53 | owner: root 54 | group: root 55 | mode: 0755 56 | when: "ansible_service_mgr == 'systemd'" 57 | 58 | - name: Ensure Sonar is running and set to start on boot. 59 | service: name=sonar state=started enabled=yes 60 | 61 | - name: Allow Sonar time to build on first start. 62 | pause: seconds=180 63 | when: sonar_symlink.changed 64 | tags: ['skip_ansible_lint'] 65 | 66 | - name: Make sure Sonar is responding on the configured port. 67 | wait_for: port=9000 delay=3 timeout=300 68 | -------------------------------------------------------------------------------- /templates/sonar.unit.j2: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=SonarQube 3 | After=network.target network-online.target 4 | Wants=network-online.target 5 | 6 | [Service] 7 | ExecStart=/usr/bin/sonar start 8 | ExecStop=/usr/bin/sonar stop 9 | ExecReload=/usr/bin/sonar restart 10 | PIDFile=/usr/local/sonar/bin/linux-x86-64/./SonarQube.pid 11 | Type=simple 12 | 13 | [Install] 14 | WantedBy=multi-user.target 15 | --------------------------------------------------------------------------------