diff --git a/CHANGELOG.md b/CHANGELOG.md index da2be77e..1e43970a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -621,3 +621,7 @@ - Initial Windows support (thanks @judy) - Update documentation - Update CONTRIBUTORS + +## v1.20.1 + +- Update main tasks to move Windows specific tasks into blocks diff --git a/tasks/main.yml b/tasks/main.yml index 8e949580..d142d599 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,5 +1,10 @@ --- # File: main.yml - Main tasks for Consul +# +# Unfortunately, this playbook violates DRY somewhat to handle installation +# on both non-Windows and Windows systems due to such bad words as casting +# dicts, and being so over YAML that this stuff just needs to get pitched +# into the rubbish bin at some point in the immediate future :lol: - name: Include checks/asserts include: asserts.yml @@ -8,314 +13,419 @@ include_vars: "{{ ansible_os_family }}.yml" tags: always -# Gathers facts (bind address) from servers not currently targeted. -# 'delegate_facts' is currently rather buggy in Ansible so this might not -# always work. Hence 'consul_gather_server_facts' defaults to 'no'. -- name: Gather facts from other servers - setup: - delegate_to: "{{ item }}" - delegate_facts: True - with_items: "{{ consul_servers | difference(play_hosts) }}" - ignore_errors: yes - when: consul_gather_server_facts | bool - -- name: Expose bind_address, datacenter and node_role as facts - set_fact: - consul_bind_address: "{{ consul_bind_address }}" - consul_datacenter: "{{ consul_datacenter }}" - consul_node_role: "{{ consul_node_role }}" - -- name: Read bootstrapped state - stat: - path: "{{ consul_bootstrap_state }}" - register: bootstrap_state - ignore_errors: true - tags: always - when: ansible_os_family != 'Windows' +############################################################################# +# Tasks for all *NIX operating systems +############################################################################# +- block: -- name: Read bootstrapped state on Windows - win_stat: - path: "{{ consul_bootstrap_state }}" - register: bootstrap_state - ignore_errors: true - tags: always - when: ansible_os_family == 'Windows' + # Gathers facts (bind address) from servers not currently targeted. + # 'delegate_facts' is currently rather buggy in Ansible so this might not + # always work. Hence 'consul_gather_server_facts' defaults to 'no'. + - name: Gather facts from other servers + setup: + delegate_to: "{{ item }}" + delegate_facts: True + with_items: "{{ consul_servers | difference(play_hosts) }}" + ignore_errors: yes + when: consul_gather_server_facts | bool -- name: Include user and group settings - include: user_group.yml - when: ansible_os_family != 'Windows' + - name: Expose bind_address, datacenter and node_role as facts + set_fact: + consul_bind_address: "{{ consul_bind_address }}" + consul_datacenter: "{{ consul_datacenter }}" + consul_node_role: "{{ consul_node_role }}" + + - name: Read bootstrapped state + stat: + path: "{{ consul_bootstrap_state }}" + register: bootstrap_state + ignore_errors: true + tags: always + + - name: Include user and group settings + include: user_group.yml + + - name: Include directory settings + include: dirs.yml + + - name: Check for existing Consul binary + stat: + path: "{{ consul_binary }}" + register: consul_binary_installed + + - name: Install OS packages and consul - locally + include: install.yml + when: + - not consul_binary_installed.stat.exists | bool + - not consul_install_remotely | bool + + - name: Install OS packages and consul - remotely + include: install_remote.yml + when: + - not consul_binary_installed.stat.exists | bool + - consul_install_remotely | bool + + # XXX: Individual gossip tasks are deprecated and need to be removed + # - include: ../tasks/encrypt_gossip.yml + + - block: + - name: Check for gossip encryption key on previously boostrapped server + slurp: + src: "{{ consul_config_path }}/config.json" + register: consul_config_b64 + ignore_errors: yes + + - name: Deserialize existing configuration + set_fact: + consul_config: "{{ consul_config_b64.content | b64decode | from_json }}" + when: consul_config_b64.content is defined + + - name: Save gossip encryption key from existing configuration + set_fact: + consul_raw_key: "{{ consul_config.encrypt }}" + when: consul_config is defined + + no_log: true + when: + - consul_raw_key is not defined + - bootstrap_state.stat.exists | bool + - inventory_hostname in consul_servers + + # Key provided by extra vars or the above block + - name: Write gossip encryption key locally for use with new servers + copy: + content: "{{ consul_raw_key }}" + dest: '/tmp/consul_raw.key' + become: no + no_log: true + run_once: true + register: consul_local_key + delegate_to: localhost + when: consul_raw_key is defined + + # Generate new key if non was found + - block: + - name: Generate gossip encryption key + shell: "PATH={{ consul_bin_path }}:$PATH consul keygen" + register: consul_keygen + + - name: Write key locally to share with other nodes + copy: + content: "{{ consul_keygen.stdout }}" + dest: '/tmp/consul_raw.key' + become: no + delegate_to: localhost + + no_log: true + run_once: true + when: + - not consul_local_key.changed + - not bootstrap_state.stat.exists | bool + + - name: Read gossip encryption key for servers that require it + set_fact: + consul_raw_key: "{{ lookup('file', '/tmp/consul_raw.key') }}" + no_log: true + when: + - consul_raw_key is not defined + + - name: Delete gossip encryption key file + file: + path: '/tmp/consul_raw.key' + state: absent + become: no + run_once: true + delegate_to: localhost -- name: Include directory settings - include: dirs.yml + - name: Create Consul configuration + include: config.yml + + - name: Create ACL configuration + include: acl.yml + when: consul_acl_enable | bool + + - name: Create TLS configuration + include: tls.yml + when: consul_tls_enable | bool + + - block: + + - name: Create BSD init script + template: + src: consul_bsdinit.j2 + dest: /etc/rc.d/consul + owner: root + group: wheel + mode: 0755 + when: ansible_os_family == "FreeBSD" + + - name: Create SYSV init script + template: + src: consul_sysvinit.j2 + dest: /etc/init.d/consul + owner: root + group: root + mode: 0755 + when: + - not ansible_service_mgr == "systemd" + - not ansible_os_family == "Debian" + - not ansible_os_family == "FreeBSD" + - not ansible_os_family == "Solaris" + + - name: Create Debian init script + template: + src: consul_debianinit.j2 + dest: /etc/init.d/consul + owner: root + group: root + mode: 0755 + when: + - not ansible_service_mgr == "systemd" + - ansible_os_family == "Debian" + - not ansible_os_family == "FreeBSD" + - not ansible_os_family == "Solaris" + + - name: Create systemd script + template: + src: consul_systemd.service.j2 + dest: /lib/systemd/system/consul.service + owner: root + group: root + mode: 0644 + when: + - ansible_service_mgr == "systemd" + - not ansible_os_family == "FreeBSD" + - not ansible_os_family == "Solaris" + + - name: Create smf manifest + template: + src: consul_smf_manifest.j2 + dest: "{{ consul_smf_manifest }}" + owner: root + group: root + mode: 0644 + when: ansible_os_family == "Solaris" + register: smfmanifest + + - name: Import smf manifest + shell: "svccfg import {{ consul_smf_manifest }}" + when: + - smfmanifest | changed + - ansible_os_family == "Solaris" + + - name: Import smf script + shell: "svcadm refresh consul" + when: + - smfmanifest | changed + - ansible_os_family == "Solaris" + + + - name: Start Consul + service: + name: consul + state: started + enabled: yes + + - name: Check Consul HTTP API + wait_for: + delay: 15 + port: 8500 + + - name: Create bootstrapped state file + file: + dest: /etc/consul/.consul_bootstrapped + state: touch + + - include: ../tasks/dnsmasq.yml + when: consul_dnsmasq_enable | bool + + - include: ../tasks/iptables.yml + when: consul_iptables_enable | bool + + - include: ../tasks/client.yml + when: + - consul_node_role == "client" + - ansible_os_family == "Debian" + + when: not bootstrap_state.stat.exists -- name: Check for existing Consul binary - stat: - path: "{{ consul_binary }}" - register: consul_binary_installed when: ansible_os_family != 'Windows' -- name: Check for existing Consul binary on Windows - win_stat: - path: "{{ consul_binary }}" - register: consul_binary_installed - when: ansible_os_family == 'Windows' +############################################################################# +# End of tasks for all *NIX operating systems +############################################################################# -- name: Install OS packages and consul - locally - include: install.yml - when: - - not consul_binary_installed.stat.exists | bool - - not consul_install_remotely | bool - - ansible_os_family != 'Windows' - -- name: Install OS packages and consul - remotely - include: install_remote.yml - when: - - not consul_binary_installed.stat.exists | bool - - consul_install_remotely | bool - - ansible_os_family != 'Windows' - -- name: Install OS packages and consul - Windows - include: install_windows.yml - when: - - not consul_binary_installed.stat.exists | bool - - ansible_os_family == 'Windows' - -# XXX: Individual gossip tasks are deprecated and need to be removed -# - include: ../tasks/encrypt_gossip.yml +############################################################################# +# Tasks for Windows +############################################################################# - block: - - name: Check for gossip encryption key on previously boostrapped server - slurp: - src: "{{ consul_config_path }}/config.json" - register: consul_config_b64 + + # Gathers facts (bind address) from servers not currently targeted. + # 'delegate_facts' is currently rather buggy in Ansible so this might not + # always work. Hence 'consul_gather_server_facts' defaults to 'no'. + - name: (Windows) Gather facts from other servers + setup: + delegate_to: "{{ item }}" + delegate_facts: True + with_items: "{{ consul_servers | difference(play_hosts) }}" ignore_errors: yes + when: consul_gather_server_facts | bool - - name: Deserialize existing configuration + - name: (Windows) Expose bind_address, datacenter and node_role as facts set_fact: - consul_config: "{{ consul_config_b64.content | b64decode | from_json }}" - when: consul_config_b64.content is defined + consul_bind_address: "{{ consul_bind_address }}" + consul_datacenter: "{{ consul_datacenter }}" + consul_node_role: "{{ consul_node_role }}" + + - name: (Windows) Read bootstrapped state + win_stat: + path: "{{ consul_bootstrap_state }}" + register: bootstrap_state + ignore_errors: true + tags: always + + - name: (Windows) Include directory settings + include: dirs.yml + + - name: (Windows) Check for existing Consul binary + win_stat: + path: "{{ consul_binary }}" + register: consul_binary_installed + + - name: (Windows) Install OS packages and consul + include: install_windows.yml + when: + - not consul_binary_installed.stat.exists | bool + + - block: + - name: (Windows) Check for gossip encryption key on previously boostrapped server + slurp: + src: "{{ consul_config_path }}/config.json" + register: consul_config_b64 + ignore_errors: yes + + - name: (Windows) Deserialize existing configuration + set_fact: + consul_config: "{{ consul_config_b64.content | b64decode | from_json }}" + when: consul_config_b64.content is defined + + - name: (Windows) Save gossip encryption key from existing configuration + set_fact: + consul_raw_key: "{{ consul_config.encrypt }}" + when: consul_config is defined + + no_log: true + when: + - consul_raw_key is not defined + - bootstrap_state.stat.exists | bool + - inventory_hostname in consul_servers + + # Key provided by extra vars or the above block + - name: (Windows) Write gossip encryption key locally for use with new servers + copy: + content: "{{ consul_raw_key }}" + dest: '/tmp/consul_raw.key' + become: no + no_log: true + run_once: true + register: consul_local_key + delegate_to: localhost + when: consul_raw_key is defined - - name: Save gossip encryption key from existing configuration - set_fact: - consul_raw_key: "{{ consul_config.encrypt }}" - when: consul_config is defined - - no_log: true - when: - - consul_raw_key is not defined - - bootstrap_state.stat.exists | bool - - inventory_hostname in consul_servers - -# Key provided by extra vars or the above block -- name: Write gossip encryption key locally for use with new servers - copy: - content: "{{ consul_raw_key }}" - dest: '/tmp/consul_raw.key' - become: no - no_log: true - run_once: true - register: consul_local_key - delegate_to: localhost - when: consul_raw_key is defined - -# Generate new key if non was found -- block: - - name: Generate gossip encryption key - shell: "PATH={{ consul_bin_path }}:$PATH consul keygen" - register: consul_keygen - when: ansible_os_family != 'Windows' + # Generate new key if non was found + - block: - - name: Generate gossip encryption key - win_shell: "{{consul_binary}} keygen" - register: consul_keygen - when: ansible_os_family == 'Windows' + - name: (Windows) Generate gossip encryption key + win_shell: "{{consul_binary}} keygen" + register: consul_keygen - - name: Write key locally to share with other nodes - copy: - content: "{{ consul_keygen.stdout }}" - dest: '/tmp/consul_raw.key' + - name: (Windows) Write key locally to share with other nodes + copy: + content: "{{ consul_keygen.stdout }}" + dest: '/tmp/consul_raw.key' + become: no + delegate_to: localhost + + no_log: true + run_once: true + when: + - not consul_local_key.changed + - not bootstrap_state.stat.exists | bool + + - name: (Windows) Read gossip encryption key for servers that require it + set_fact: + consul_raw_key: "{{ lookup('file', '/tmp/consul_raw.key') }}" + no_log: true + when: + - consul_raw_key is not defined + + - name: (Windows) Delete gossip encryption key file + file: + path: '/tmp/consul_raw.key' + state: absent become: no + run_once: true delegate_to: localhost - no_log: true - run_once: true - when: - - not consul_local_key.changed - - not bootstrap_state.stat.exists | bool - -- name: Read gossip encryption key for servers that require it - set_fact: - consul_raw_key: "{{ lookup('file', '/tmp/consul_raw.key') }}" - no_log: true - when: - - consul_raw_key is not defined - -- name: Delete gossip encryption key file - file: - path: '/tmp/consul_raw.key' - state: absent - become: no - run_once: true - delegate_to: localhost - -- name: Create Consul configuration - include: config.yml - when: ansible_os_family != 'Windows' + - name: (Windows) Create Consul configuration + include: config_windows.yml -- name: Create Consul configuration for Windows - include: config_windows.yml - when: ansible_os_family == 'Windows' + - name: (Windows) Ensure neither ACL nor TLS are requested + fail: + msg: "ACL and TLS are not supported on Windows hosts yet." + when: + - (consul_acl_enable | bool) or (consul_tls_enable | bool) -- name: Ensure neither ACL nor TLS are requested for windows hosts - fail: - msg: "ACL and TLS are not supported on Windows hosts yet." - when: - - ansible_os_family == 'Windows' - - (consul_acl_enable | bool) or (consul_tls_enable | bool) + - name: (Windows) Create ACL configuration + include: acl.yml + when: consul_acl_enable | bool -- name: Create ACL configuration - include: acl.yml - when: consul_acl_enable | bool + - name: (Windows) Create TLS configuration + include: tls.yml + when: consul_tls_enable | bool -- name: Create TLS configuration - include: tls.yml - when: consul_tls_enable | bool + - block: -- block: + - name: (Windows) Install NSSM + win_chocolatey: + name: nssm + state: latest + + - name: (Windows) Start Consul on Windows + win_nssm: + name: consul + state: started + application: "{{ consul_binary }}" + app_parameters_free_form: "agent -config-file='{{ consul_config_path }}/config.json' -config-dir='{{ consul_configd_path }}'" + stdout_file: "{{ consul_log_path }}/consul-nssm-output.log" + stderr_file: "{{ consul_log_path }}/consul-nssm-error.log" + + - name: (Windows) Check Consul HTTP API + local_action: + module: wait_for + delay: 5 + host: "{{inventory_hostname_short}}" + port: 8500 + + + - name: (Windows) Create bootstrapped state file + win_file: + dest: "{{consul_bootstrap_state}}" + state: touch + when: ansible_os_family == "Windows" - - name: Create BSD init script - template: - src: consul_bsdinit.j2 - dest: /etc/rc.d/consul - owner: root - group: wheel - mode: 0755 - when: ansible_os_family == "FreeBSD" - - - name: Create SYSV init script - template: - src: consul_sysvinit.j2 - dest: /etc/init.d/consul - owner: root - group: root - mode: 0755 - when: - - ansible_service_mgr is defined - - not ansible_service_mgr == "systemd" - - not ansible_os_family == "Debian" - - not ansible_os_family == "FreeBSD" - - not ansible_os_family == "Solaris" - - not ansible_os_family == "Windows" - - - name: Create Debian init script - template: - src: consul_debianinit.j2 - dest: /etc/init.d/consul - owner: root - group: root - mode: 0755 - when: - - ansible_service_mgr is defined - - not ansible_service_mgr == "systemd" - - ansible_os_family == "Debian" - - not ansible_os_family == "FreeBSD" - - not ansible_os_family == "Solaris" - - not ansible_os_family == "Windows" - - - name: Create systemd script - template: - src: consul_systemd.service.j2 - dest: /lib/systemd/system/consul.service - owner: root - group: root - mode: 0644 - when: - - ansible_service_mgr is defined - - ansible_service_mgr == "systemd" - - not ansible_os_family == "FreeBSD" - - not ansible_os_family == "Solaris" - - not ansible_os_family == "Windows" - - - name: Create smf manifest - template: - src: consul_smf_manifest.j2 - dest: "{{ consul_smf_manifest }}" - owner: root - group: root - mode: 0644 - when: ansible_os_family == "Solaris" - register: smfmanifest - - - name: Import smf manifest - shell: "svccfg import {{ consul_smf_manifest }}" - when: - - smfmanifest | changed - - ansible_os_family == "Solaris" - - - name: Import smf script - shell: "svcadm refresh consul" - when: - - smfmanifest | changed - - ansible_os_family == "Solaris" - - - - name: Start Consul - service: - name: consul - state: started - enabled: yes - when: ansible_os_family != "Windows" - - - name: Install NSSM - win_chocolatey: - name: nssm - state: latest - - - name: Start Consul on Windows - win_nssm: - name: consul - state: started - application: "{{ consul_binary }}" - app_parameters_free_form: "agent -config-file='{{ consul_config_path }}/config.json' -config-dir='{{ consul_configd_path }}'" - stdout_file: "{{ consul_log_path }}/consul-nssm-output.log" - stderr_file: "{{ consul_log_path }}/consul-nssm-error.log" - when: ansible_os_family == "Windows" - - - name: Check Consul HTTP API - wait_for: - delay: 15 - port: 8500 - when: ansible_os_family != "Windows" - - - name: Check Consul HTTP API - local_action: - module: wait_for - delay: 5 - host: "{{inventory_hostname_short}}" - port: 8500 - when: ansible_os_family == "Windows" - - - name: Create bootstrapped state file - file: - dest: "{{consul_bootstrap_state}}" - state: touch - when: ansible_os_family != "Windows" - - - name: Create bootstrapped state file - win_file: - dest: "{{consul_bootstrap_state}}" - state: touch - when: ansible_os_family == "Windows" - - - include: ../tasks/dnsmasq.yml - when: consul_dnsmasq_enable | bool - - - include: ../tasks/iptables.yml - when: consul_iptables_enable | bool - - - include: ../tasks/client.yml - when: - - consul_node_role == "client" - - ansible_os_family == "Debian" - - when: not bootstrap_state.stat.exists + - include: ../tasks/dnsmasq.yml + when: consul_dnsmasq_enable | bool + + - include: ../tasks/iptables.yml + when: consul_iptables_enable | bool + + - include: ../tasks/client.yml + when: + - consul_node_role == "client" + - ansible_os_family == "Debian" + + when: not bootstrap_state.stat.exists + + when: ansible_os_family == 'Windows' diff --git a/version.txt b/version.txt index c858d1e1..9c01bd7c 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -v1.20.0 +v1.20.1