├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── Vagrantfile ├── build.sh ├── defaults └── main.yml ├── handlers └── main.yml ├── meta └── main.yml ├── tasks ├── Debian-tarball.yml ├── Debian.yml ├── RedHat.yml ├── common-config.yml ├── main.yml ├── systemd.yml ├── tarball.yml └── upstart.yml ├── templates ├── log4j.properties.j2 ├── myid.j2 ├── zoo.cfg.j2 ├── zookeeper-env.sh.j2 ├── zookeeper.conf.j2 └── zookeeper.service.j2 └── tests ├── dependencies.yml ├── playbook.yml └── test.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant/ 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | bin/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # Installer logs 27 | pip-log.txt 28 | pip-delete-this-directory.txt 29 | 30 | # Unit test / coverage reports 31 | htmlcov/ 32 | .tox/ 33 | .coverage 34 | .cache 35 | nosetests.xml 36 | coverage.xml 37 | 38 | # Translations 39 | *.mo 40 | 41 | # Mr Developer 42 | .mr.developer.cfg 43 | .project 44 | .pydevproject 45 | 46 | # Rope 47 | .ropeproject 48 | 49 | # Django stuff: 50 | *.log 51 | *.pot 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | *.iml -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | env: 4 | matrix: 5 | - distro: ernestasposkus/centos7 6 | init: /usr/lib/systemd/systemd 7 | run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" 8 | - distro: ernestasposkus/centos6 9 | init: /sbin/init 10 | run_opts: "" 11 | - distro: ernestasposkus/ubuntu1604 12 | init: /lib/systemd/systemd 13 | run_opts: "--privileged --volume=/sys/fs/cgroup:/sys/fs/cgroup:ro" 14 | - distro: ernestasposkus/ubuntu1404 15 | init: /sbin/init 16 | run_opts: "" 17 | 18 | services: 19 | - docker 20 | 21 | before_install: 22 | # Pull container. 23 | - 'sudo docker pull ${distro}:latest' 24 | 25 | script: 26 | - container_id=$(mktemp) 27 | # Run container in detached state. 28 | - 'sudo docker run --detach --volume="${PWD}":/etc/ansible/roles/role_under_test:ro ${run_opts} ${distro}:latest "${init}" > "${container_id}"' 29 | 30 | # Inspect docker container 31 | - 'sudo docker inspect $(cat ${container_id})' 32 | 33 | # Print ansible version 34 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible --version' 35 | 36 | # Check Ansible host setup 37 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible all -i "localhost," -c local -m setup' 38 | 39 | # Install dependencies 40 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible-galaxy install geerlingguy.java' 41 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/dependencies.yml' 42 | 43 | # Ansible syntax check. 44 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/playbook.yml --syntax-check' 45 | 46 | # Test role. 47 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/playbook.yml' 48 | 49 | # Test role idempotence. 50 | - idempotence=$(mktemp) 51 | - sudo docker exec "$(cat ${container_id})" ansible-playbook /etc/ansible/roles/role_under_test/tests/playbook.yml | tee -a ${idempotence} 52 | - > 53 | tail ${idempotence} 54 | | grep -q 'changed=0.*failed=0' 55 | && (echo 'Idempotence test: pass' && exit 0) 56 | || (echo 'Idempotence test: fail' && exit 1) 57 | 58 | # Test role. 59 | - 'sudo docker exec --tty "$(cat ${container_id})" env TERM=xterm ansible-playbook /etc/ansible/roles/role_under_test/tests/test.yml' 60 | 61 | # View container logs 62 | - 'sudo docker logs "$(cat ${container_id})"' 63 | 64 | # Clean up. 65 | - 'sudo docker stop "$(cat ${container_id})"' 66 | 67 | notifications: 68 | webhooks: https://galaxy.ansible.com/api/v1/notifications/ 69 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Kien Pham 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-zookeeper 2 | ================= 3 | 4 | [![Build Status](https://travis-ci.org/AnsibleShipyard/ansible-zookeeper.svg?branch=master)](https://travis-ci.org/AnsibleShipyard/ansible-zookeeper) 5 | 6 | ZooKeeper playbook for Ansible 7 | 8 | Installation 9 | ----------- 10 | 11 | ```bash 12 | ansible-galaxy install AnsibleShipyard.ansible-zookeeper 13 | ``` 14 | 15 | Dependencies 16 | ------------ 17 | 18 | Java 19 | 20 | - https://github.com/AnsibleShipyard/ansible-java 21 | - https://github.com/geerlingguy/ansible-role-java 22 | 23 | Requirements 24 | ------------ 25 | 26 | Ansible version at least 1.6 27 | 28 | Role Variables 29 | -------------- 30 | 31 | ```yaml 32 | --- 33 | zookeeper_version: 3.4.12 34 | zookeeper_url: http://www.us.apache.org/dist/zookeeper/zookeeper-{{zookeeper_version}}/zookeeper-{{zookeeper_version}}.tar.gz 35 | 36 | # Flag that selects if systemd or upstart will be used for the init service: 37 | # Note: by default Ubuntu 15.04 and later use systemd (but support switch to upstart) 38 | zookeeper_debian_systemd_enabled: "{{ ansible_distribution_version|version_compare(15.04, '>=') }}" 39 | zookeeper_debian_apt_install: false 40 | # (Optional:) add custom 'ppa' repositories depending on the distro version (only with debian_apt_install=true) 41 | # Example: to use a community zookeeper v3.4.8 deb pkg for Ubuntu 14.04 (where latest official is v3.4.5) 42 | zookeeper_debian_apt_repositories: 43 | - repository_url: "ppa:ufscar/zookeeper" 44 | distro_version: "14.04" 45 | 46 | apt_cache_timeout: 3600 47 | zookeeper_register_path_env: false 48 | 49 | client_port: 2181 50 | init_limit: 5 51 | sync_limit: 2 52 | tick_time: 2000 53 | zookeeper_autopurge_purgeInterval: 0 54 | zookeeper_autopurge_snapRetainCount: 10 55 | zookeeper_cluster_ports: "2888:3888" 56 | zookeeper_max_client_connections: 60 57 | 58 | data_dir: /var/lib/zookeeper 59 | log_dir: /var/log/zookeeper 60 | zookeeper_dir: /opt/zookeeper-{{zookeeper_version}} # or /usr/share/zookeeper when zookeeper_debian_apt_install is true 61 | zookeeper_conf_dir: {{zookeeper_dir}} # or /etc/zookeeper when zookeeper_debian_apt_install is true 62 | zookeeper_tarball_dir: /opt/src 63 | 64 | zookeeper_hosts_hostname: "{{inventory_hostname}}" 65 | # List of dict (i.e. {zookeeper_hosts:[{host:,id:},{host:,id:},...]}) 66 | zookeeper_hosts: 67 | - host: "{{zookeeper_hosts_hostname}}" # the machine running 68 | id: 1 69 | 70 | # Dict of ENV settings to be written into the (optional) conf/zookeeper-env.sh 71 | zookeeper_env: {} 72 | 73 | # Controls Zookeeper myid generation 74 | zookeeper_force_myid: yes 75 | ``` 76 | 77 | Example Playbook 78 | ---------------- 79 | 80 | ```yaml 81 | - name: Installing ZooKeeper 82 | hosts: all 83 | sudo: yes 84 | roles: 85 | - role: AnsibleShipyard.ansible-zookeeper 86 | ``` 87 | 88 | Example Retrieving Tarball From S3 89 | ---------------------------------- 90 | 91 | ```yaml 92 | - name: Installing ZooKeeper 93 | hosts: all 94 | sudo: yes 95 | vars: 96 | zookeeper_archive_s3_bucket: my-s3-bucket 97 | zookeeper_archive_s3_object: my/s3/directory/zookeeper-{{zookeeper_version}}.tar.gz 98 | roles: 99 | - role: AnsibleShipyard.ansible-zookeeper 100 | ``` 101 | 102 | Cluster Example 103 | ---------------- 104 | 105 | ```yaml 106 | - name: Zookeeper cluster setup 107 | hosts: zookeepers 108 | sudo: yes 109 | roles: 110 | - role: AnsibleShipyard.ansible-zookeeper 111 | zookeeper_hosts: "{{groups['zookeepers']}}" 112 | ``` 113 | 114 | Assuming ```zookeepers``` is a [hosts group](http://docs.ansible.com/ansible/intro_inventory.html#group-variables) defined in inventory file. 115 | 116 | ```inventory 117 | [zookeepers] 118 | server[1:3] 119 | ``` 120 | 121 | Custom IP per host group 122 | 123 | ``` 124 | zookeeper_hosts: " 125 | {%- set ips = [] %} 126 | {%- for host in groups['zookeepers'] %} 127 | {{- ips.append(dict(id=loop.index, host=host, ip=hostvars[host]['ansible_default_ipv4'].address)) }} 128 | {%- endfor %} 129 | {{- ips -}}" 130 | ``` 131 | 132 | See this sample [playbook](https://github.com/AnsibleShipyard/ansible-galaxy-roles/blob/master/playbook.yml) 133 | which shows how to use this playbook as well as others. It is part of [ansible-galaxy-roles](https://github.com/AnsibleShipyard/ansible-galaxy-roles) and 134 | serves as a curation (and thus an example) of all our ansible playbooks. 135 | 136 | License 137 | ------- 138 | 139 | The MIT License (MIT) 140 | 141 | Copyright (c) 2014 Kien Pham 142 | 143 | Permission is hereby granted, free of charge, to any person obtaining a copy 144 | of this software and associated documentation files (the "Software"), to deal 145 | in the Software without restriction, including without limitation the rights 146 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 147 | copies of the Software, and to permit persons to whom the Software is 148 | furnished to do so, subject to the following conditions: 149 | 150 | The above copyright notice and this permission notice shall be included in all 151 | copies or substantial portions of the Software. 152 | 153 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 154 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 155 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 156 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 157 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 158 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 159 | SOFTWARE. 160 | 161 | 162 | AnsibleShipyard 163 | ------- 164 | 165 | Our related playbooks 166 | 167 | 1. [ansible-mesos](https://github.com/AnsibleShipyard/ansible-mesos) 168 | 1. [ansible-marathon](https://github.com/AnsibleShipyard/ansible-marathon) 169 | 1. [ansible-chronos](https://github.com/AnsibleShipyard/ansible-chronos) 170 | 1. [ansible-zookeeper](https://github.com/AnsibleShipyard/ansible-zookeeper) 171 | 172 | Author Information 173 | ------------------ 174 | 175 | @AnsibleShipyard/developers and others. 176 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby -*- 2 | # vi: set ft=ruby : 3 | 4 | Vagrant.configure("2") do |config| 5 | config.ssh.forward_agent = true 6 | config.vm.synced_folder Dir.getwd, "/home/vagrant/roles/ansible-zookeeper", nfs: true 7 | 8 | # ubuntu 9 | config.vm.define 'ubuntu', primary: true do |c| 10 | c.vm.network "private_network", ip: "192.168.100.2" 11 | c.vm.box = "trusty-server-cloudimg-amd64-vagrant-disk1" 12 | c.vm.box_url = "https://cloud-images.ubuntu.com/vagrant/trusty/current/trusty-server-cloudimg-amd64-vagrant-disk1.box" 13 | c.vm.provision "shell" do |s| 14 | s.inline = "apt-get update -y; apt-get install ansible -y;" 15 | s.privileged = true 16 | end 17 | end 18 | 19 | # centos: 20 | config.vm.define 'centos' do |c| 21 | c.vm.network "private_network", ip: "192.168.100.3" 22 | c.vm.box = "centos65-x86_64-20140116" 23 | c.vm.box_url = "https://github.com/2creatives/vagrant-centos/releases/download/v6.5.3/centos65-x86_64-20140116.box" 24 | c.vm.provision "shell" do |s| 25 | s.inline = "yum install -y nc java-1.7.0-openjdk-devel ansible" 26 | s.privileged = true 27 | end 28 | end 29 | 30 | # centos 7 31 | config.vm.define 'centos7' do |c| 32 | c.vm.network "private_network", ip: "192.168.100.4" 33 | c.vm.box = "centos/7" 34 | c.vm.provision "shell" do |s| 35 | s.inline = "yum install -y epel-release; yum install -y nc java-1.7.0-openjdk-devel ansible" 36 | s.privileged = true 37 | end 38 | end 39 | 40 | end 41 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DOCKERNAME="ansibleshipyard/ansible-zookeeper" 4 | DOCKER_DIR="dockerfiles" 5 | # TAGS=(ubuntu centos) 6 | TAGS=(ubuntu) 7 | CONTEXT=. 8 | 9 | usage() { 10 | local tag=$1 11 | 12 | echo 13 | echo "To pull it" 14 | echo " docker pull $DOCKERNAME:$tag" 15 | echo 16 | echo "To use this docker:" 17 | echo " docker run -d -P $DOCKERNAME:$tag" 18 | echo 19 | echo "To run in interactive mode for debug:" 20 | echo " docker run -t -i $DOCKERNAME:$tag bash" 21 | echo 22 | } 23 | 24 | build() { 25 | local tag=$1 26 | 27 | # pushd $tag 28 | 29 | # Builds the image 30 | cmd="docker build -f $DOCKER_DIR/$tag/Dockerfile --force-rm -t $DOCKERNAME:$tag $CONTEXT" 31 | 32 | echo "Command to execute: [$cmd]" 33 | 34 | $cmd 35 | 36 | if [ $? == 0 ]; then 37 | echo "$tag build successful!" 38 | usage $tag 39 | return 0 40 | else 41 | return 1 42 | fi; 43 | } 44 | 45 | main() { 46 | # pushd $DOCKER_DIR 47 | for tag in ${TAGS[@]}; do 48 | build ${tag} 49 | if [ $? != 0 ]; then 50 | echo "$tag build failed!" 51 | fi; 52 | done 53 | } 54 | 55 | main -------------------------------------------------------------------------------- /defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | zookeeper_version: 3.4.12 3 | zookeeper_url: http://www.us.apache.org/dist/zookeeper/zookeeper-{{zookeeper_version}}/zookeeper-{{zookeeper_version}}.tar.gz 4 | 5 | # Flag that selects if systemd or upstart will be used for the init service: 6 | # Note: by default Ubuntu 15.04 and later use systemd (but support switch to upstart) 7 | _ubuntu_1504: "{{ ansible_distribution == 'Ubuntu' and ansible_distribution_version|version_compare(15.04, '>=') }}" 8 | _debian_8: "{{ ansible_distribution == 'Debian' and ansible_distribution_version|version_compare(8.0, '>=') }}" 9 | zookeeper_debian_systemd_enabled: "{{ _ubuntu_1504 or _debian_8 }}" 10 | 11 | zookeeper_debian_apt_install: false 12 | zookeeper_debian_apt_repositories: [] 13 | apt_cache_timeout: 3600 14 | zookeeper_register_path_env: false 15 | 16 | client_port: 2181 17 | init_limit: 5 18 | sync_limit: 2 19 | tick_time: 2000 20 | zookeeper_autopurge_purgeInterval: 0 21 | zookeeper_autopurge_snapRetainCount: 10 22 | zookeeper_cluster_ports: "2888:3888" 23 | zookeeper_max_client_connections: 60 24 | 25 | data_dir: /var/lib/zookeeper 26 | log_dir: /var/log/zookeeper 27 | zookeeper_dir: "{{ zookeeper_debian_apt_install | ternary('/usr/share/zookeeper', '/opt/zookeeper-' + zookeeper_version) }}" 28 | zookeeper_conf_dir: "{{ zookeeper_debian_apt_install | ternary('/etc/zookeeper', zookeeper_dir) }}" 29 | zookeeper_tarball_dir: /opt/src 30 | 31 | # Rolling file appender setttings 32 | zookeeper_rolling_log_file_max_size: 10MB 33 | zookeeper_max_rolling_log_file_count: 10 34 | 35 | zookeeper_hosts_hostname: "{{inventory_hostname}}" 36 | # List of dict (i.e. {zookeeper_hosts:[{host:,id:},{host:,id:},...]}) 37 | zookeeper_hosts: 38 | - host: "{{zookeeper_hosts_hostname}}" # the machine running 39 | id: 1 40 | 41 | # Dict of ENV settings to be written into the (optional) conf/zookeeper-env.sh 42 | zookeeper_env: {} 43 | 44 | # Controls Zookeeper myid generation 45 | zookeeper_force_myid: yes 46 | -------------------------------------------------------------------------------- /handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Reload systemctl daemon 3 | command: systemctl daemon-reload 4 | when: ansible_service_mgr == 'systemd' 5 | 6 | - name: Restart zookeeper 7 | service: name=zookeeper state=restarted 8 | -------------------------------------------------------------------------------- /meta/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | galaxy_info: 3 | author: Michael Hamrah 4 | description: Ansible Zookeeper Role 5 | company: http://michaelhamrah.com 6 | license: Apache 2 7 | min_ansible_version: 2.4 8 | # 9 | # Below are all platforms currently available. Just uncomment 10 | # the ones that apply to your role. If you don't see your 11 | # platform on this list, let us know and we'll get it added! 12 | # 13 | platforms: 14 | - name: EL 15 | versions: 16 | - 6 17 | - 7 18 | #- name: GenericUNIX 19 | # versions: 20 | # - all 21 | # - any 22 | #- name: Fedora 23 | # versions: 24 | # - all 25 | # - 16 26 | # - 17 27 | # - 18 28 | # - 19 29 | # - 20 30 | #- name: opensuse 31 | # versions: 32 | # - all 33 | # - 12.1 34 | # - 12.2 35 | # - 12.3 36 | # - 13.1 37 | # - 13.2 38 | #- name: GenericBSD 39 | # versions: 40 | # - all 41 | # - any 42 | #- name: FreeBSD 43 | # versions: 44 | # - all 45 | # - 8.0 46 | # - 8.1 47 | # - 8.2 48 | # - 8.3 49 | # - 8.4 50 | # - 9.0 51 | # - 9.1 52 | # - 9.1 53 | # - 9.2 54 | - name: Ubuntu 55 | versions: 56 | - raring 57 | - saucy 58 | - trusty 59 | - utopic 60 | - vivid 61 | - wily 62 | - xenial 63 | #- name: SLES 64 | # versions: 65 | # - all 66 | # - 10SP3 67 | # - 10SP4 68 | # - 11 69 | # - 11SP1 70 | # - 11SP2 71 | # - 11SP3 72 | #- name: GenericLinux 73 | # versions: 74 | # - all 75 | # - any 76 | - name: Debian 77 | versions: 78 | - etch 79 | - lenny 80 | - squeeze 81 | - wheezy 82 | 83 | # Below are all categories currently available. Just as with 84 | # the platforms above, uncomment those that apply to your role. 85 | # 86 | categories: 87 | #- cloud 88 | #- cloud:ec2 89 | #- cloud:gce 90 | #- cloud:rax 91 | #- database 92 | #- database:nosql 93 | #- database:sql 94 | #- development 95 | #- monitoring 96 | #- networking 97 | #- packaging 98 | #- system 99 | #- web 100 | - platform 101 | 102 | galaxy_tags: 103 | - zookeeper 104 | - distributed synchronization 105 | - distributed hierarchical key-value store 106 | - synchronization service 107 | 108 | dependencies: [] 109 | # - ansible-java 110 | # - ansible-scala 111 | # - ansible-sbt 112 | # List your role dependencies here, one per line. Only 113 | # dependencies available via galaxy should be listed here. 114 | # Be sure to remove the '[]' above if you add dependencies 115 | # to this list. 116 | 117 | -------------------------------------------------------------------------------- /tasks/Debian-tarball.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - include_tasks: tarball.yml 3 | 4 | - include_tasks: upstart.yml 5 | when: not zookeeper_debian_systemd_enabled 6 | tags: deploy 7 | 8 | - include_tasks: systemd.yml 9 | when: zookeeper_debian_systemd_enabled 10 | tags: deploy 11 | -------------------------------------------------------------------------------- /tasks/Debian.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Add optional custom apt repositories (for additional zookeeper versions) 3 | apt_repository: repo={{item.repository_url}} state=present 4 | when: "{{ ansible_distribution_version|version_compare(item.distro_version, item.version_comparator|default('=')) }}" 5 | with_items: 6 | - "{{ zookeeper_debian_apt_repositories }}" 7 | 8 | - name: Update apt cache 9 | apt: update_cache=yes cache_valid_time={{apt_cache_timeout}} 10 | tags: bootstrap 11 | 12 | - name: Apt install required system packages. 13 | apt: pkg={{item}} state=installed 14 | tags: bootstrap 15 | with_items: 16 | - zookeeper 17 | - zookeeperd 18 | 19 | - name: Overwrite myid file. 20 | template: src=myid.j2 dest={{zookeeper_conf_dir}}/conf/myid force="{{ zookeeper_force_myid }}" 21 | tags: deploy 22 | notify: 23 | - Restart zookeeper 24 | 25 | - name: Overwrite default config file 26 | template: src=zoo.cfg.j2 dest={{zookeeper_conf_dir}}/conf/zoo.cfg 27 | tags: deploy 28 | notify: 29 | - Restart zookeeper 30 | -------------------------------------------------------------------------------- /tasks/RedHat.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Install OS Packages 3 | yum: name={{ item }} state=present 4 | with_items: 5 | - libselinux-python 6 | 7 | - include_tasks: tarball.yml 8 | 9 | - include_tasks: upstart.yml 10 | tags: deploy 11 | 12 | - include_tasks: systemd.yml 13 | tags: deploy 14 | -------------------------------------------------------------------------------- /tasks/common-config.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Configure zookeeper-env.sh 3 | template: src=zookeeper-env.sh.j2 dest={{ zookeeper_conf_dir }}/conf/zookeeper-env.sh owner=zookeeper group=zookeeper 4 | tags: deploy 5 | notify: 6 | - Restart zookeeper 7 | when: zookeeper_env is defined and zookeeper_env|length > 0 8 | 9 | - name: Update the log4j config with saner production values 10 | template: src=log4j.properties.j2 dest={{ zookeeper_conf_dir }}/conf/log4j.properties 11 | tags: deploy 12 | notify: 13 | - Restart zookeeper 14 | 15 | - name: Enable zookeeper service 16 | service: name=zookeeper enabled=yes 17 | tags: deploy 18 | -------------------------------------------------------------------------------- /tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | - include_tasks: Debian.yml 4 | when: ansible_os_family == 'Debian' and zookeeper_debian_apt_install 5 | 6 | - include_tasks: Debian-tarball.yml 7 | when: ansible_os_family == 'Debian' and not zookeeper_debian_apt_install 8 | 9 | - include_tasks: RedHat.yml 10 | when: ansible_os_family == 'RedHat' 11 | 12 | - include_tasks: common-config.yml 13 | -------------------------------------------------------------------------------- /tasks/systemd.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Systemd script. 3 | template: src=zookeeper.service.j2 dest=/lib/systemd/system/zookeeper.service 4 | when: ansible_service_mgr == 'systemd' 5 | notify: 6 | - Reload systemctl daemon 7 | - Restart zookeeper 8 | -------------------------------------------------------------------------------- /tasks/tarball.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: "Ensure the tarball dir exists at {{zookeeper_tarball_dir}}" 3 | file: path={{zookeeper_tarball_dir}} state=directory 4 | 5 | - name: "Ensure the zookeeper dir exists at {{zookeeper_dir}}" 6 | file: path={{zookeeper_dir}} state=directory 7 | 8 | # If the file exists already, the S3 call can experience errors 9 | - name: check whether the tarball is downloaded already 10 | stat: path={{zookeeper_tarball_dir}}/zookeeper-{{zookeeper_version}}.tar.gz 11 | register: zookeeper_tarball_script 12 | 13 | - name: Download zookeeper from S3 14 | s3: 15 | mode: get 16 | bucket: "{{zookeeper_archive_s3_bucket}}" 17 | object: "{{zookeeper_archive_s3_object}}" 18 | dest: "{{zookeeper_tarball_dir}}/zookeeper-{{zookeeper_version}}.tar.gz" 19 | register: zookeeper_s3_tarball_downloaded 20 | tags: bootstrap 21 | when: > 22 | zookeeper_archive_s3_bucket is defined and 23 | zookeeper_archive_s3_object is defined and 24 | not zookeeper_tarball_script.stat.exists 25 | 26 | - name: Download zookeeper version. 27 | get_url: url={{zookeeper_url}} dest={{zookeeper_tarball_dir}}/zookeeper-{{zookeeper_version}}.tar.gz 28 | tags: bootstrap 29 | register: zookeeper_tarball_downloaded 30 | when: > 31 | zookeeper_archive_s3_bucket is not defined or 32 | zookeeper_archive_s3_object is not defined 33 | 34 | - name: Unpack tarball. 35 | command: tar xf {{zookeeper_tarball_dir}}/zookeeper-{{zookeeper_version}}.tar.gz --strip-components=1 chdir={{zookeeper_dir}} creates={{zookeeper_dir}}/bin 36 | tags: bootstrap 37 | 38 | - group: name=zookeeper system=yes 39 | - user: name=zookeeper group=zookeeper system=yes 40 | 41 | - name: Change ownership on zookeeper directory. 42 | file: path={{zookeeper_dir}} state=directory owner=zookeeper group=zookeeper 43 | tags: bootstrap 44 | 45 | - name: "Create zookeeper {{item}} directory." 46 | file: path={{item}} state=directory owner=zookeeper group=zookeeper 47 | tags: bootstrap 48 | with_items: 49 | - "{{data_dir}}" 50 | - "{{log_dir}}" 51 | 52 | - name: Write myid file. 53 | template: src=myid.j2 dest={{data_dir}}/myid owner=zookeeper group=zookeeper force="{{ zookeeper_force_myid }}" 54 | tags: deploy 55 | notify: 56 | - Restart zookeeper 57 | 58 | - name: Configure zookeeper zoo.cfg 59 | template: src=zoo.cfg.j2 dest={{ zookeeper_dir }}/conf/zoo.cfg owner=zookeeper group=zookeeper 60 | tags: deploy 61 | notify: 62 | - Restart zookeeper 63 | 64 | - name: Add zookeeper's bin dir to the PATH 65 | copy: content="export PATH=$PATH:{{zookeeper_dir}}/bin" dest="/etc/profile.d/zookeeper_path.sh" mode=755 66 | when: zookeeper_register_path_env 67 | -------------------------------------------------------------------------------- /tasks/upstart.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if /etc/init exists 3 | stat: path=/etc/init/ 4 | register: etc_init 5 | 6 | - name: Upstart script. 7 | template: src=zookeeper.conf.j2 dest=/etc/init/zookeeper.conf 8 | when: 9 | - etc_init.stat.exists == true 10 | - ansible_service_mgr != 'systemd' 11 | notify: 12 | - Restart zookeeper 13 | -------------------------------------------------------------------------------- /templates/log4j.properties.j2: -------------------------------------------------------------------------------- 1 | # Define some default values that can be overridden by system properties 2 | zookeeper.root.logger=INFO, CONSOLE, ROLLINGFILE 3 | zookeeper.console.threshold=INFO 4 | zookeeper.log.dir=. 5 | zookeeper.log.file=zookeeper.log 6 | zookeeper.log.threshold=DEBUG 7 | zookeeper.tracelog.dir=. 8 | zookeeper.tracelog.file=zookeeper_trace.log 9 | 10 | # 11 | # ZooKeeper Logging Configuration 12 | # 13 | 14 | # Format is " (, )+ 15 | 16 | # DEFAULT: console appender only 17 | log4j.rootLogger=${zookeeper.root.logger} 18 | 19 | # Example with rolling log file 20 | #log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE 21 | 22 | # Example with rolling log file and tracing 23 | #log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE 24 | 25 | # 26 | # Log INFO level and above messages to the console 27 | # 28 | log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 29 | log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold} 30 | log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout 31 | log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n 32 | 33 | # 34 | # Add ROLLINGFILE to rootLogger to get log file output 35 | # Log DEBUG level and above messages to a log file 36 | log4j.appender.ROLLINGFILE=org.apache.log4j.RollingFileAppender 37 | log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold} 38 | log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file} 39 | 40 | # Max log file size of 10MB 41 | log4j.appender.ROLLINGFILE.MaxFileSize={{ zookeeper_rolling_log_file_max_size }} 42 | # uncomment the next line to limit number of backup files 43 | log4j.appender.ROLLINGFILE.MaxBackupIndex={{ zookeeper_max_rolling_log_file_count }} 44 | 45 | log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout 46 | log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n 47 | 48 | 49 | # 50 | # Add TRACEFILE to rootLogger to get log file output 51 | # Log DEBUG level and above messages to a log file 52 | log4j.appender.TRACEFILE=org.apache.log4j.FileAppender 53 | log4j.appender.TRACEFILE.Threshold=TRACE 54 | log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file} 55 | 56 | log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout 57 | ### Notice we are including log4j's NDC here (%x) 58 | log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n 59 | -------------------------------------------------------------------------------- /templates/myid.j2: -------------------------------------------------------------------------------- 1 | {% for server in zookeeper_hosts %} 2 | {% if server.host is defined %} 3 | {% if server.host == zookeeper_hosts_hostname %} 4 | {{ server.id }} 5 | {% endif %} 6 | {% else %} 7 | {% if server == zookeeper_hosts_hostname %} 8 | {{ loop.index }} 9 | {% endif %} 10 | {% endif %} 11 | {% endfor %} 12 | -------------------------------------------------------------------------------- /templates/zoo.cfg.j2: -------------------------------------------------------------------------------- 1 | tickTime={{ tick_time }} 2 | dataDir={{ data_dir }} 3 | dataLogDir={{ log_dir }} 4 | clientPort={{ client_port }} 5 | initLimit={{ init_limit }} 6 | syncLimit={{ sync_limit }} 7 | maxClientCnxns={{ zookeeper_max_client_connections }} 8 | {% if zookeeper_autopurge_purgeInterval > 0 %} 9 | autopurge.purgeInterval={{ zookeeper_autopurge_purgeInterval }} 10 | autopurge.snapRetainCount={{ zookeeper_autopurge_snapRetainCount }} 11 | {% endif %} 12 | 13 | {% for server in zookeeper_hosts %} 14 | {% if server.host is defined %} 15 | {% if server.ip is defined %} 16 | server.{{server.id}}={{server.ip}}:{{zookeeper_cluster_ports}} 17 | {% else %} 18 | server.{{server.id}}={{server.host}}:{{zookeeper_cluster_ports}} 19 | {% endif %} 20 | {% else %} 21 | server.{{loop.index}}={{server}}:{{zookeeper_cluster_ports}} 22 | {% endif %} 23 | {% endfor %} 24 | -------------------------------------------------------------------------------- /templates/zookeeper-env.sh.j2: -------------------------------------------------------------------------------- 1 | {% if zookeeper_env is defined %} 2 | {% for key, value in zookeeper_env.items() | sort %} 3 | {{key}}={{value}} 4 | {% endfor %} 5 | {% endif %} 6 | -------------------------------------------------------------------------------- /templates/zookeeper.conf.j2: -------------------------------------------------------------------------------- 1 | description "ZooKeeper" 2 | 3 | limit nofile 32768 32768 4 | 5 | start on runlevel [2345] 6 | stop on [!12345] 7 | 8 | respawn 9 | respawn limit 2 5 10 | 11 | umask 007 12 | 13 | kill timeout 300 14 | 15 | script 16 | # https://superuser.com/questions/213416/running-upstart-jobs-as-unprivileged-users 17 | exec su -s /bin/sh -c 'exec "$0" "$@" &>>{{ log_dir }}/init-zookeeper.log' zookeeper -- \ 18 | {{zookeeper_dir}}/bin/zkServer.sh start-foreground 19 | end script 20 | -------------------------------------------------------------------------------- /templates/zookeeper.service.j2: -------------------------------------------------------------------------------- 1 | # {{ansible_managed}} 2 | 3 | [Unit] 4 | Description=ZooKeeper 5 | After=network.target 6 | Wants=network.target 7 | 8 | [Service] 9 | Type=simple 10 | User=zookeeper 11 | Group=zookeeper 12 | ExecStart={{zookeeper_dir}}/bin/zkServer.sh start-foreground 13 | Restart=always 14 | RestartSec=3 15 | 16 | TimeoutSec=300 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /tests/dependencies.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | remote_user: root 5 | tasks: 6 | - name: installing repo for Java 8 in Ubuntu 7 | apt_repository: repo='ppa:openjdk-r/ppa' 8 | when: 9 | - ansible_os_family == 'Debian' 10 | 11 | - hosts: localhost 12 | connection: local 13 | remote_user: root 14 | roles: 15 | - role: geerlingguy.java 16 | java_packages: 17 | - openjdk-8-jdk 18 | when: ansible_os_family == 'Debian' 19 | 20 | - role: geerlingguy.java 21 | java_packages: 22 | - java-1.8.0-openjdk 23 | when: ansible_os_family == 'RedHat' 24 | -------------------------------------------------------------------------------- /tests/playbook.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | remote_user: root 5 | roles: 6 | - role: role_under_test 7 | -------------------------------------------------------------------------------- /tests/test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: localhost 3 | connection: local 4 | remote_user: root 5 | tasks: 6 | - shell: "ps aux | grep -i zookeeper" 7 | register: status 8 | failed_when: status.rc != 0 9 | when: ansible_service_mgr != 'systemd' 10 | 11 | - shell: "systemctl status zookeeper | grep running" 12 | register: status 13 | failed_when: status.rc != 0 14 | when: ansible_service_mgr == 'systemd' 15 | 16 | # 17 | # Host hash playbook 18 | # 19 | 20 | - hosts: localhost 21 | connection: local 22 | remote_user: root 23 | roles: 24 | - role: role_under_test 25 | zookeeper_hosts: 26 | - host: "{{zookeeper_hosts_hostname}}" # the machine running 27 | id: 2 28 | 29 | - hosts: localhost 30 | connection: local 31 | remote_user: root 32 | tasks: 33 | # Expecting myid to be 2 as defined in zookeeper_hosts variable 34 | - shell: "grep 2 /var/lib/zookeeper/myid" 35 | register: status 36 | failed_when: status.rc != 0 37 | 38 | # 39 | # Host list playbook 40 | # 41 | 42 | - hosts: localhost 43 | connection: local 44 | remote_user: root 45 | roles: 46 | - role: role_under_test 47 | zookeeper_hosts: 48 | - "{{zookeeper_hosts_hostname}}" 49 | 50 | - hosts: localhost 51 | connection: local 52 | remote_user: root 53 | tasks: 54 | # Expecting myid to be 1 defined by loop.index 55 | - shell: "grep 1 /var/lib/zookeeper/myid" 56 | register: status 57 | failed_when: status.rc != 0 58 | 59 | # 60 | # Host hash playbook with ip key 61 | # 62 | 63 | - hosts: localhost 64 | connection: local 65 | remote_user: root 66 | roles: 67 | - role: role_under_test 68 | zookeeper_version: 3.4.12 69 | zookeeper_dir: /opt/zookeeper-{{zookeeper_version}} 70 | zookeeper_hosts: 71 | - host: "{{zookeeper_hosts_hostname}}" # the machine running 72 | ip: '192.168.0.1' 73 | id: 2 74 | 75 | - hosts: localhost 76 | connection: local 77 | remote_user: root 78 | vars: 79 | zookeeper_version: 3.4.12 80 | zookeeper_dir: /opt/zookeeper-{{zookeeper_version}} 81 | zookeeper_cluster_ports: "2888:3888" 82 | tasks: 83 | # Expecting myid to be 2 as defined in zookeeper_hosts variable 84 | - shell: "grep 2 /var/lib/zookeeper/myid" 85 | register: status 86 | failed_when: status.rc != 0 87 | 88 | # Expecting zoo.cfg to include serve definition with custom IP 89 | - shell: "grep 'server.2=192.168.0.1:{{ zookeeper_cluster_ports }}' {{ zookeeper_dir }}/conf/zoo.cfg" 90 | register: status 91 | failed_when: status.rc != 0 92 | 93 | --------------------------------------------------------------------------------