diff --git a/ansible-tendermint/.gitignore b/ansible-tendermint/.gitignore new file mode 100644 index 000000000..7193038e5 --- /dev/null +++ b/ansible-tendermint/.gitignore @@ -0,0 +1,2 @@ +.vagrant/ +*.retry diff --git a/ansible-tendermint/LICENSE b/ansible-tendermint/LICENSE new file mode 100644 index 000000000..64a33ddf1 --- /dev/null +++ b/ansible-tendermint/LICENSE @@ -0,0 +1,192 @@ +Copyright (C) 2017 Tendermint + + + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/ansible-tendermint/README.md b/ansible-tendermint/README.md new file mode 100644 index 000000000..c1eca7e61 --- /dev/null +++ b/ansible-tendermint/README.md @@ -0,0 +1,65 @@ +# Deploy a Tendermint network using Ansible + +## Requirements + +This role requires Ansible 2.0 or higher. + +## Variables + +Here is a list of all the default variables for this role, which are also +available in `defaults/main.yml`. + +``` +tendermint_version: 0.9.0 +tendermint_archive: "tendermint_{{tendermint_version}}_linux_amd64.zip" +tendermint_download: "https://s3-us-west-2.amazonaws.com/tendermint/{{tendermint_version}}/{{tendermint_archive}}" +tendermint_download_folder: /tmp + +tendermint_user: tendermint +tendermint_group: tendermint + +# Upstart start/stop conditions can vary by distribution and environment +tendermint_upstart_start_on: start on runlevel [345] +tendermint_upstart_stop_on: stop on runlevel [!345] +tendermint_manage_service: true + +tendermint_home: /opt/tendermint +tendermint_rpc_port: 46657 +tendermint_proxy_app: tcp://127.0.0.1:46658 + +tendermint_log_file: /var/log/tendermint.log + +tendermint_chain_id: mychain +tendermint_genesis_time: "{{ansible_date_time.iso8601_micro}}" +``` + +## Handlers + +These are the handlers that are defined in `handlers/main.yml`. + +* restart tendermint + +## Example playbook that configures a Tendermint on Ubuntu + +``` +--- + +- hosts: all + vars: + tendermint_chain_id: MyAwesomeChain + roles: + - ansible-tendermint +``` + +This playbook will install Tendermint and will create all the required +directories. But **it won't start the Tendermint if there are no validators in +genesis file**. See `templates/genesis.json.j2`. + +You will need to collect validators public keys manually or using `genesis.yml` +given you have SSH access to all the nodes. + +## Testing + +``` +vagrant up +``` diff --git a/ansible-tendermint/Vagrantfile b/ansible-tendermint/Vagrantfile new file mode 100644 index 000000000..bc6f9fde0 --- /dev/null +++ b/ansible-tendermint/Vagrantfile @@ -0,0 +1,20 @@ +# -*- mode: ruby -*- +# vi: set ft=ruby : + +# Vagrantfile API/syntax version. Don't touch unless you know what you're doing! +VAGRANTFILE_API_VERSION = "2" + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + # All Vagrant configuration is done here. The most common configuration + # options are documented and commented below. For a complete reference, + # please see the online documentation at vagrantup.com. + + # Every Vagrant virtual environment requires a box to build off of. + config.vm.box = "ubuntu/trusty64" + + config.vm.provision :ansible do |ansible| + ansible.playbook = "test.yml" + ansible.verbose = 'vv' + ansible.sudo = true + end +end diff --git a/ansible-tendermint/ansible.cfg b/ansible-tendermint/ansible.cfg new file mode 100644 index 000000000..613d83b12 --- /dev/null +++ b/ansible-tendermint/ansible.cfg @@ -0,0 +1,2 @@ +[defaults] +roles_path = ../ diff --git a/ansible-tendermint/defaults/main.yml b/ansible-tendermint/defaults/main.yml new file mode 100644 index 000000000..b854a3a20 --- /dev/null +++ b/ansible-tendermint/defaults/main.yml @@ -0,0 +1,22 @@ +--- +tendermint_version: 0.9.0 +tendermint_archive: "tendermint_{{tendermint_version}}_linux_amd64.zip" +tendermint_download: "https://s3-us-west-2.amazonaws.com/tendermint/{{tendermint_version}}/{{tendermint_archive}}" +tendermint_download_folder: /tmp + +tendermint_user: tendermint +tendermint_group: tendermint + +# Upstart start/stop conditions can vary by distribution and environment +tendermint_upstart_start_on: start on runlevel [345] +tendermint_upstart_stop_on: stop on runlevel [!345] +tendermint_manage_service: true + +tendermint_home: /opt/tendermint +tendermint_rpc_port: 46657 +tendermint_proxy_app: tcp://127.0.0.1:46658 + +tendermint_log_file: /var/log/tendermint.log + +tendermint_chain_id: mychain +tendermint_genesis_time: "{{ansible_date_time.iso8601_micro}}" diff --git a/ansible-tendermint/genesis.yml b/ansible-tendermint/genesis.yml new file mode 100644 index 000000000..914ea9d77 --- /dev/null +++ b/ansible-tendermint/genesis.yml @@ -0,0 +1,11 @@ +--- +# Gathers validator public keys from all the nodes to help you form genesis file + +- hosts: all + vars: + tendermint_home: /opt/tendermint + tasks: + - shell: cat "{{tendermint_home}}/priv_validator.json" | jq ".pub_key[1]" + register: pk + + - debug: var=pk.stdout_lines diff --git a/ansible-tendermint/handlers/main.yml b/ansible-tendermint/handlers/main.yml new file mode 100644 index 000000000..788c67456 --- /dev/null +++ b/ansible-tendermint/handlers/main.yml @@ -0,0 +1,5 @@ +--- + +- name: restart tendermint + action: service name=tendermint state=restarted enabled=yes + when: tendermint_manage_service diff --git a/ansible-tendermint/tasks/install.yml b/ansible-tendermint/tasks/install.yml new file mode 100644 index 000000000..4f5e9ade1 --- /dev/null +++ b/ansible-tendermint/tasks/install.yml @@ -0,0 +1,111 @@ +--- +- name: update apt + apt: > + update_cache=yes + cache_valid_time=3600 + when: ansible_os_family == "Debian" + +- name: install deps (Ubuntu) + apt: > + pkg={{item}} + state=installed + with_items: + - unzip + - jq + when: ansible_os_family == "Debian" + +- name: install deps (RHEL) + yum: > + pkg={{item}} + state=installed + with_items: + - unzip + - jq + when: ansible_os_family == "RedHat" + +- name: create group + group: > + name={{tendermint_group}} + state=present + system=yes + register: tendermint_group_created + +- name: create user + user: > + home={{tendermint_home}} + name={{tendermint_user}} + group={{tendermint_group}} + system=yes + when: tendermint_group_created|changed + +- name: create directory + file: > + path={{tendermint_home}} + state=directory + owner={{tendermint_user}} + group={{tendermint_group}} + mode=0755 + +# Check before creating log dir to prevent aggressively overwriting permissions +- name: check for log directory + stat: > + path={{ tendermint_log_file|dirname }} + register: logdir + +- name: create log directory if it does not exist + file: > + state=directory + path={{ tendermint_log_file|dirname }} + owner={{ tendermint_user }} + group={{ tendermint_group }} + when: not logdir.stat.exists + +- name: touch the log file + file: > + state=touch + path={{ tendermint_log_file }} + owner={{ tendermint_user }} + group={{ tendermint_group }} + changed_when: false + +- name: copy and unpack binary + unarchive: > + src={{tendermint_download}} + dest=/usr/local/bin + remote_src=true + mode=0755 + creates=/usr/local/bin/tendermint + +- name: generate private validator + shell: tendermint gen_validator >> priv_validator.json + args: + chdir: "{{tendermint_home}}" + creates: priv_validator.json + +- name: copy config + template: > + src=config.toml.j2 + dest={{tendermint_home}}/config.toml + owner={{tendermint_user}} + group={{tendermint_group}} + mode=0644 + register: config_was_copied + # notify: restart tendermint + +- name: set ownership + file: > + state=directory + path={{tendermint_home}} + owner={{tendermint_user}} + group={{tendermint_group}} + recurse=yes + when: config_was_copied|changed + +- name: copy upstart script + template: > + src=tendermint.conf.j2 + dest=/etc/init/tendermint.conf + owner=root + group=root + mode=0644 + # notify: restart tendermint diff --git a/ansible-tendermint/tasks/main.yml b/ansible-tendermint/tasks/main.yml new file mode 100644 index 000000000..f7a109370 --- /dev/null +++ b/ansible-tendermint/tasks/main.yml @@ -0,0 +1,13 @@ +--- +- name: gather OS specific variables + include_vars: "{{ item }}" + with_first_found: + - "{{ ansible_os_family }}-{{ ansible_distribution_major_version}}.yml" + - "{{ ansible_os_family }}.yml" +- include: install.yml +- service: > + name=tendermint + state=stopped + enabled=yes + when: tendermint_manage_service +- include: start.yml diff --git a/ansible-tendermint/tasks/start.yml b/ansible-tendermint/tasks/start.yml new file mode 100644 index 000000000..8159af0c3 --- /dev/null +++ b/ansible-tendermint/tasks/start.yml @@ -0,0 +1,20 @@ +--- + +- name: copy genesis file + template: > + src=genesis.json.j2 + dest={{tendermint_home}}/genesis.json + owner={{tendermint_user}} + group={{tendermint_group}} + mode=0644 + register: genesis_file_copied + +- name: get validators number from genesis file + shell: cat {{tendermint_home}}/genesis.json | jq ".validators | length" + register: num_validators + when: genesis_file_copied|changed + +- name: restart tendermint if number of validators greater than 0 + shell: echo "restarting ..." + when: genesis_file_copied|changed and num_validators.stdout|int > 0 + notify: restart tendermint diff --git a/ansible-tendermint/templates/config.toml.j2 b/ansible-tendermint/templates/config.toml.j2 new file mode 100644 index 000000000..e9ee7c19f --- /dev/null +++ b/ansible-tendermint/templates/config.toml.j2 @@ -0,0 +1,7 @@ +proxy_app = "{{tendermint_proxy_app}}" +node_laddr = "tcp://0.0.0.0:46656" +seeds = "" +fast_sync = true +db_backend = "leveldb" +log_level = "notice" +rpc_laddr = "tcp://0.0.0.0:{{tendermint_rpc_port}}" diff --git a/ansible-tendermint/templates/genesis.json.j2 b/ansible-tendermint/templates/genesis.json.j2 new file mode 100644 index 000000000..201d5465f --- /dev/null +++ b/ansible-tendermint/templates/genesis.json.j2 @@ -0,0 +1,7 @@ +{ + "app_hash": "", + "chain_id": "{{tendermint_chain_id}}", + "genesis_time": "{{tendermint_genesis_time}}", + "validators": [ + ] +} diff --git a/ansible-tendermint/templates/tendermint.conf.j2 b/ansible-tendermint/templates/tendermint.conf.j2 new file mode 100644 index 000000000..b1d9f04dd --- /dev/null +++ b/ansible-tendermint/templates/tendermint.conf.j2 @@ -0,0 +1,16 @@ +# Tendermint (Upstart unit) +description "Tendermint" + +start on {{ tendermint_upstart_start_on }} +stop on {{ tendermint_upstart_stop_on }} + +script + # Use su to become tendermint user non-interactively on old Upstart versions (see http://superuser.com/a/234541/76168) + exec su -s /bin/sh -c 'TMROOT={{tendermint_home}} exec "$0" "$@" > {{ tendermint_log_file }} &2>1' tendermint -- /usr/local/bin/tendermint node \ + --moniker={{inventory_hostname}} +end script + +respawn +respawn limit 10 10 + +kill timeout 10 diff --git a/ansible-tendermint/test.yml b/ansible-tendermint/test.yml new file mode 100644 index 000000000..6f219164c --- /dev/null +++ b/ansible-tendermint/test.yml @@ -0,0 +1,7 @@ +--- + +- hosts: all + roles: + - ansible-tendermint + vars: + tendermint_proxy_app: dummy diff --git a/ansible-tendermint/vars/Debian.yml b/ansible-tendermint/vars/Debian.yml new file mode 100644 index 000000000..642304b92 --- /dev/null +++ b/ansible-tendermint/vars/Debian.yml @@ -0,0 +1,3 @@ +--- +consul_upstart_start_on: (local-filesystems and net-device-up IFACE!=lo) +consul_upstart_stop_on: runlevel [016] diff --git a/ansible-tendermint/vars/RedHat.yml b/ansible-tendermint/vars/RedHat.yml new file mode 100644 index 000000000..4c2bb72b2 --- /dev/null +++ b/ansible-tendermint/vars/RedHat.yml @@ -0,0 +1,3 @@ +--- +consul_upstart_start_on: (runlevel [345] and started network) +consul_upstart_stop_on: (runlevel [!345] or stopping network)