feat: add nomad deployment options, variables, and playbooks
All checks were successful
development / Check commit compliance (push) Successful in 26s

This commit is contained in:
Bertrand Lanson 2024-06-25 15:16:42 +02:00
parent b32815066f
commit 95a1d80f76
Signed by: lanson
SSH Key Fingerprint: SHA256:/nqc6HGqld/PS208F6FUOvZlUzTS0rGpNNwR5O2bQBw
23 changed files with 626 additions and 74 deletions

View File

@ -6,7 +6,7 @@
# enable_haproxy: "yes" # enable_haproxy: "yes"
# enable_vault: "yes" # enable_vault: "yes"
# enable_consul: "yes" # enable_consul: "yes"
enable_nomad: "no" # enable_nomad: "yes"
# haproxy_version: "2.8" # haproxy_version: "2.8"
# nomad_version: "1.7.7" # nomad_version: "1.7.7"

View File

@ -11,7 +11,7 @@ platforms:
- name: proxy01 - name: proxy01
box: generic/${MOLECULE_TEST_OS} box: generic/${MOLECULE_TEST_OS}
cpus: 2 cpus: 2
memory: 4096 memory: 2048
interfaces: interfaces:
- network_name: private_network - network_name: private_network
ip: 192.168.100.91 ip: 192.168.100.91
@ -24,7 +24,7 @@ platforms:
- name: proxy02 - name: proxy02
box: generic/${MOLECULE_TEST_OS} box: generic/${MOLECULE_TEST_OS}
cpus: 2 cpus: 2
memory: 4096 memory: 2048
interfaces: interfaces:
- network_name: private_network - network_name: private_network
ip: 192.168.100.92 ip: 192.168.100.92
@ -37,7 +37,7 @@ platforms:
- name: hashistack01 - name: hashistack01
box: generic/${MOLECULE_TEST_OS} box: generic/${MOLECULE_TEST_OS}
cpus: 4 cpus: 4
memory: 4096 memory: 2048
interfaces: interfaces:
- network_name: private_network - network_name: private_network
ip: 192.168.100.101 ip: 192.168.100.101
@ -51,7 +51,7 @@ platforms:
- name: hashistack02 - name: hashistack02
box: generic/${MOLECULE_TEST_OS} box: generic/${MOLECULE_TEST_OS}
cpus: 4 cpus: 4
memory: 4096 memory: 2048
interfaces: interfaces:
- network_name: private_network - network_name: private_network
ip: 192.168.100.102 ip: 192.168.100.102
@ -65,7 +65,7 @@ platforms:
- name: hashistack03 - name: hashistack03
box: generic/${MOLECULE_TEST_OS} box: generic/${MOLECULE_TEST_OS}
cpus: 4 cpus: 4
memory: 4096 memory: 2048
interfaces: interfaces:
- network_name: private_network - network_name: private_network
ip: 192.168.100.103 ip: 192.168.100.103
@ -76,6 +76,19 @@ platforms:
- vault_servers - vault_servers
- consul_servers - consul_servers
- nomad_servers - nomad_servers
- name: hashistack04
box: generic/${MOLECULE_TEST_OS}
cpus: 4
memory: 2048
interfaces:
- network_name: private_network
ip: 192.168.100.104
auto_config: true
type: static
groups:
- common
- nomad_clients
- consul_agents
provisioner: provisioner:
name: ansible name: ansible
config_options: config_options:

View File

@ -12,23 +12,23 @@
tags: tags:
- always - always
- name: "Deploy Consul"
tags:
- consul
when:
- enable_consul | bool
block:
- name: "Deploy Consul Control Plane" - name: "Deploy Consul Control Plane"
ansible.builtin.import_tasks: ansible.builtin.import_tasks:
file: tasks/consul/consul_deploy.yml file: tasks/consul/consul_deploy.yml
when: when:
- enable_consul | bool
- "'consul_servers' in group_names" - "'consul_servers' in group_names"
tags:
- consul
- name: "Deploy Consul Agents" - name: "Deploy Consul Agents"
ansible.builtin.include_role: ansible.builtin.include_role:
name: ednz_cloud.hashicorp_consul name: ednz_cloud.hashicorp_consul
when: when:
- enable_consul | bool
- "'consul_agents' in group_names" - "'consul_agents' in group_names"
tags:
- consul
- name: "Deploy Haproxy & Keepalived" - name: "Deploy Haproxy & Keepalived"
ansible.builtin.import_tasks: ansible.builtin.import_tasks:
@ -47,3 +47,22 @@
- "'vault_servers' in group_names" - "'vault_servers' in group_names"
tags: tags:
- vault - vault
- name: "Deploy Nomad"
tags:
- nomad
when:
- enable_nomad | bool
block:
- name: "Deploy Nomad Control Plane"
ansible.builtin.import_tasks:
file: tasks/nomad/nomad_deploy.yml
when:
- "('nomad_servers' in group_names)"
- name: "Deploy Nomad Clients"
ansible.builtin.include_role:
name: ednz_cloud.hashicorp_nomad
when:
- "('nomad_clients' in group_names)"
- "('nomad_servers' not in group_names)"

View File

@ -6,6 +6,12 @@
gather_facts: true gather_facts: true
become: true become: true
tasks: tasks:
- name: "Import variables"
ansible.builtin.import_tasks:
file: tasks/load_vars.yml
tags:
- always
- name: "Create temporary cert directory in {{ sub_configuration_directories['certificates'] }}" # noqa: run-once[task] - name: "Create temporary cert directory in {{ sub_configuration_directories['certificates'] }}" # noqa: run-once[task]
ansible.builtin.file: ansible.builtin.file:
path: "{{ sub_configuration_directories['certificates'] }}/external" path: "{{ sub_configuration_directories['certificates'] }}/external"
@ -271,5 +277,3 @@
owner: "{{ lookup('env', 'USER') }}" owner: "{{ lookup('env', 'USER') }}"
group: "{{ lookup('env', 'USER') }}" group: "{{ lookup('env', 'USER') }}"
mode: "0644" mode: "0644"
# - fail:

View File

@ -18,14 +18,24 @@
- name: "Generate consul agents credentials" - name: "Generate consul agents credentials"
ansible.builtin.set_fact: ansible.builtin.set_fact:
_cosul_agents_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}" _consul_agents_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
_consul_agents_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}" _consul_agents_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
- name: "Generate consul vault credentials" - name: "Generate consul vault credentials"
ansible.builtin.set_fact: ansible.builtin.set_fact:
_cosul_vault_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}" _consul_vault_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
_consul_vault_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}" _consul_vault_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
- name: "Generate consul nomad server credentials"
ansible.builtin.set_fact:
_consul_nomad_server_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
_consul_nomad_server_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
- name: "Generate consul nomad client credentials"
ansible.builtin.set_fact:
_consul_nomad_client_accessor: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
_consul_nomad_client_token: "{{ lookup('ansible.builtin.password', '/dev/null', chars=['ascii_letters','digits']) | to_uuid }}"
- name: "Generate nomad credentials" - name: "Generate nomad credentials"
block: block:
- name: "Generate nomad gossip encryption key" - name: "Generate nomad gossip encryption key"
@ -43,5 +53,3 @@
owner: "{{ lookup('env', 'USER') }}" owner: "{{ lookup('env', 'USER') }}"
group: "{{ lookup('env', 'USER') }}" group: "{{ lookup('env', 'USER') }}"
mode: '0644' mode: '0644'
# - fail:

View File

@ -75,8 +75,7 @@ hashicorp_consul_data_dir: "/opt/consul"
hashicorp_consul_extra_files: true hashicorp_consul_extra_files: true
hashicorp_consul_extra_files_list: "{{ ([] + hashicorp_consul_extra_files_list: "{{ ([] +
(consul_certificates_extra_files_dir if consul_enable_tls else []) + (consul_certificates_extra_files_dir if consul_enable_tls else []) +
(vault_plugin_extra_files_dir if vault_enable_plugins else []) + consul_extra_files_list)
vault_extra_files_list)
| unique | unique
| sort | sort
}}" }}"
@ -102,13 +101,10 @@ hashicorp_consul_configuration:
rejoin_after_leave: "{{ consul_rejoin_after_leave }}" rejoin_after_leave: "{{ consul_rejoin_after_leave }}"
enable_script_checks: "{{ consul_enable_script_checks }}" enable_script_checks: "{{ consul_enable_script_checks }}"
enable_syslog: true enable_syslog: true
log_level: INFO
acl: "{{ consul_acl_configuration }}" acl: "{{ consul_acl_configuration }}"
dns_config: "{{ consul_dns_configuration }}" dns_config: "{{ consul_dns_configuration }}"
ports: ports:
dns: 8600 dns: 8600
grpc: 8502
grpc_tls: 8503
server: 8300 server: 8300
serf_lan: 8301 serf_lan: 8301
serf_wan: 8302 serf_wan: 8302
@ -119,7 +115,11 @@ hashicorp_consul_configuration:
# this is used to circumvent jinja limitation to convert string to integer # this is used to circumvent jinja limitation to convert string to integer
hashicorp_consul_configuration_string: | hashicorp_consul_configuration_string: |
bootstrap_expect: {{ (groups['consul_servers'] | length) }}
ports: ports:
http: {{ (consul_api_port.http|int) if not consul_enable_tls else ('-1' | int) }} http: {{ (consul_api_port.http|int) if not consul_enable_tls else ('-1' | int) }}
https: {{ (consul_api_port.https|int) if consul_enable_tls else ('-1' | int) }} https: {{ (consul_api_port.https|int) if consul_enable_tls else ('-1' | int) }}
grpc: {{ ('8502'|int) if not consul_enable_tls else ('-1' | int) }}
grpc_tls: {{ ('8503'|int) if consul_enable_tls else ('-1' | int) }}
hashicorp_consul_servers_configuration_string: |
bootstrap_expect: {{ (groups['consul_servers'] | length) }}

View File

@ -9,7 +9,7 @@ enable_consul: "yes"
enable_nomad: "yes" enable_nomad: "yes"
haproxy_version: "2.8" haproxy_version: "2.8"
nomad_version: "1.7.7" nomad_version: "1.8.1"
consul_version: "1.18.1" consul_version: "1.18.1"
vault_version: "1.16.2" vault_version: "1.16.2"

View File

@ -49,11 +49,11 @@ deploy_haproxy_frontends:
{%- set haproxy_options = haproxy_options + tls_options -%} {%- set haproxy_options = haproxy_options + tls_options -%}
{%- endif -%} {%- endif -%}
{%- set haproxy_options = haproxy_options + consul_haproxy_frontend_options + vault_haproxy_frontend_options -%} {%- set haproxy_options = haproxy_options + consul_haproxy_frontend_options + vault_haproxy_frontend_options + nomad_haproxy_frontend_options -%}
{{ haproxy_options }} {{ haproxy_options }}
deploy_haproxy_backends: "{{ consul_haproxy_backends + vault_haproxy_backends }}" deploy_haproxy_backends: "{{ consul_haproxy_backends + vault_haproxy_backends + nomad_haproxy_backends }}"
deploy_haproxy_listen: deploy_haproxy_listen:
- name: monitoring - name: monitoring

View File

@ -7,6 +7,61 @@
nomad_datacenter: dc1 nomad_datacenter: dc1
####################
# nomad api config #
####################
nomad_api_addr: "{{ nomad_api_scheme }}://{{ api_interface_address }}:{{ nomad_api_port[nomad_api_scheme] }}"
nomad_api_scheme: "{{ 'https' if nomad_enable_tls else 'http' }}"
nomad_api_port:
http: "{{ nomad_address_configuration.ports.http }}"
https: "{{ nomad_address_configuration.ports.http }}"
#########################
# nomad haproxy backend #
#########################
nomad_haproxy_frontend_options:
- acl is_nomad hdr(host) -i {{ nomad_fqdn }}
- use_backend nomad_external if is_nomad
nomad_haproxy_backends:
- name: nomad_external
options: "{{ nomad_external_backend_options + nomad_external_backend_servers }}"
nomad_external_backend_options:
- description nomad external http backend
- option forwardfor
- option httpchk
- http-check send meth GET uri /
- default-server inter 2s fastinter 1s downinter 1s
nomad_external_backend_servers: |
[
{% for host in groups['nomad_servers'] %}
'server nomad-{{ hostvars[host].api_interface_address }} {{ hostvars[host].api_interface_address }}:{{ hostvars[host].nomad_api_port[nomad_api_scheme] }} check {{ 'ssl verify none ' if nomad_enable_tls }}inter 5s'{% if not loop.last %},{% endif %}
{% endfor %}
]
###############################
# nomad address configuration #
###############################
nomad_address_configuration:
bind_addr: "{{ api_interface_address }}"
addresses:
http: "{{ api_interface_address }}"
rpc: "{{ api_interface_address }}"
serf: "{{ api_interface_address }}"
advertise:
http: "{{ api_interface_address }}"
rpc: "{{ api_interface_address }}"
serf: "{{ api_interface_address }}"
ports:
http: 4646
rpc: 4647
serf: 4648
########################### ###########################
# nomad ACL configuration # # nomad ACL configuration #
########################### ###########################
@ -28,7 +83,49 @@ nomad_autopilot_configuration: {}
############################ ############################
nomad_enable_consul_integration: "{{ enable_consul | bool }}" nomad_enable_consul_integration: "{{ enable_consul | bool }}"
nomad_consul_integration_configuration: {} nomad_consul_integration_configuration:
address: "127.0.0.1:{{ hashicorp_consul_configuration.ports.https if consul_enable_tls else hashicorp_consul_configuration.ports.http }}"
auto_advertise: true
ssl: "{{ consul_enable_tls | bool }}"
token: "{{ _credentials.consul.tokens.nomad.server.secret_id if nomad_enable_server else _credentials.consul.tokens.nomad.client.secret_id}}"
tags: []
nomad_consul_integration_tls_configuration:
ca_file: "/etc/ssl/certs/ca-certificates.crt"
nomad_consul_integration_server_configuration:
server_auto_join: true
nomad_consul_integration_client_configuration:
client_auto_join: true
grpc_address: "127.0.0.1:{{ hashicorp_consul_configuration.ports.grpc_tls if consul_enable_tls else hashicorp_consul_configuration.ports.grpc }}"
nomad_consul_integration_client_tls_configuration:
grpc_ca_file: "/etc/ssl/certs/ca-certificates.crt"
nomad_consul_integration_server_policy: |
agent_prefix "" {
policy = "read"
}
node_prefix "" {
policy = "read"
}
service_prefix "" {
policy = "write"
}
acl = "write"
mesh = "write"
nomad_consul_integration_client_policy: |
agent_prefix "" {
policy = "read"
}
node_prefix "" {
policy = "read"
}
service_prefix "" {
policy = "write"
}
############################ ############################
# nomad vault integration # # nomad vault integration #
@ -43,15 +140,23 @@ nomad_vault_integration_configuration: {}
# node will leave the cluster if the process is stopped # node will leave the cluster if the process is stopped
# and if it is only a client # and if it is only a client
nomad_leave_on_interrupt: "{{ (('nomad_clients' in group_names) and (not 'nomad_servers' in group_names)) | bool }}" nomad_leave_on_interrupt: "{{ (('nomad_clients' in group_names) and not ('nomad_servers' in group_names)) | bool }}"
nomad_leave_on_terminate: "{{ (('nomad_clients' in group_names) and (not 'nomad_servers' in group_names)) | bool }}" nomad_leave_on_terminate: "{{ (('nomad_clients' in group_names) and not ('nomad_servers' in group_names)) | bool }}"
##########################
# nomad ui configuration #
##########################
nomad_ui_configuration:
enabled: "{{ ('nomad_servers' in group_names) | bool }}"
############################## ##############################
# nomad server configuration # # nomad server configuration #
############################## ##############################
nomad_enable_server: "{{ ('nomad_servers' in group_names) | bool }}"
nomad_server_configuration: nomad_server_configuration:
enabled: "{{ 'nomad_servers' in group_names }}" enabled: "{{ nomad_enable_server }}"
data_dir: "{{ hashicorp_nomad_data_dir }}/server" data_dir: "{{ hashicorp_nomad_data_dir }}/server"
encrypt: "{{ _credentials.nomad.gossip_encryption_key }}" encrypt: "{{ _credentials.nomad.gossip_encryption_key }}"
@ -59,29 +164,74 @@ nomad_server_configuration:
# nomad client configuration # # nomad client configuration #
############################## ##############################
nomad_enable_client: "{{ ('nomad_clients' in group_names) | bool }}"
nomad_client_configuration: nomad_client_configuration:
enabled: "{{ 'nomad_clients' in group_names | bool }}" enabled: "{{ nomad_enable_client }}"
state_dir: "{{ hashicorp_nomad_data_dir }}/client" state_dir: "{{ hashicorp_nomad_data_dir }}/client"
bridge_network_name: nomad
bridge_network_subnet: "172.26.64.0/20"
###############################
# nomad drivers configuration #
###############################
######################
# nomad internal tls #
######################
nomad_enable_tls: false
nomad_tls_configuration:
http: true
rpc: true
ca_file: "/etc/ssl/certs/ca-certificates.crt"
cert_file: "{{ nomad_certificates_directory }}/cert.pem"
key_file: "{{ nomad_certificates_directory }}/key.pem"
verify_server_hostname: true
nomad_certificates_directory: "{{ hashicorp_nomad_config_dir }}/tls"
nomad_certificates_extra_files_dir:
- src: "{{ sub_configuration_directories['certificates'] }}/nomad/{{ inventory_hostname }}"
dest: "{{ nomad_certificates_directory }}"
#######################
# extra configuration #
#######################
nomad_extra_configuration: {}
nomad_extra_files_list: []
########################
# nomad role variables #
########################
hashicorp_nomad_start_service: true hashicorp_nomad_start_service: true
hashicorp_nomad_service_name: "nomad" hashicorp_nomad_service_name: "nomad"
hashicorp_nomad_cni_plugins_install: true hashicorp_nomad_cni_plugins_install: true
hashicorp_nomad_cni_plugins_version: latest hashicorp_nomad_cni_plugins_version: latest
hashicorp_nomad_cni_plugins_install_path: /opt/cni/bin hashicorp_nomad_cni_plugins_install_path: /opt/cni/bin
hashicorp_nomad_version: latest hashicorp_nomad_version: "{{ nomad_version }}"
hashicorp_nomad_deploy_method: host # deployment method, either host or docker
hashicorp_nomad_env_variables: {} hashicorp_nomad_env_variables: {}
hashicorp_nomad_config_dir: "/etc/nomad.d" hashicorp_nomad_config_dir: "/etc/nomad.d"
hashicorp_nomad_data_dir: /opt/nomad hashicorp_nomad_data_dir: /opt/nomad
hashicorp_nomad_extra_files: false hashicorp_nomad_extra_files: false
hashicorp_nomad_extra_files_src: /tmp/extra_files hashicorp_nomad_extra_files_list: "{{ ([] +
hashicorp_nomad_extra_files_dst: /etc/nomad.d/extra_files (nomad_certificates_extra_files_dir if nomad_enable_tls else []) +
nomad_extra_files_list)
| unique
| sort
}}"
hashicorp_nomad_configuration: hashicorp_nomad_configuration:
datacenter: "{{ nomad_datacenter }}" datacenter: "{{ nomad_datacenter }}"
bind_addr: "0.0.0.0" bind_addr: "0.0.0.0"
data_dir: "{{ hashicorp_nomad_data_dir }}" data_dir: "{{ hashicorp_nomad_data_dir }}"
leave_on_interrupt: "{{ (('nomad_clients' in group_names) and (not 'nomad_servers' in group_names)) | bool }}" leave_on_interrupt: "{{ nomad_leave_on_interrupt }}"
leave_on_terminate: "{{ (('nomad_clients' in group_names) and (not 'nomad_servers' in group_names)) | bool }}" leave_on_terminate: "{{ nomad_leave_on_terminate }}"
acl: "{{ nomad_acl_configuration }}" acl: "{{ nomad_acl_configuration }}"
server: "{{ nomad_server_configuration }}" server: "{{ nomad_server_configuration }}"
client: "{{ nomad_client_configuration }}" client: "{{ nomad_client_configuration }}"
ui: "{{ nomad_ui_configuration }}"
# this is used to circumvent jinja limitation to convert string to integer
hashicorp_nomad_configuration_string: |
server:
bootstrap_expect: {{ (groups['nomad_servers'] | length) }}

View File

@ -12,15 +12,22 @@ consul01
consul02 consul02
consul03 consul03
[consul_agents:children]
haproxy_servers
vault_servers
[nomad_servers] [nomad_servers]
nomad01 nomad01
nomad02 nomad02
nomad03 nomad03
[nomad_clients]
nomad-client01
nomad-client02
nomad-client03
[consul_agents:children]
haproxy_servers
vault_servers
nomad_servers
nomad_clients
[deployment] [deployment]
localhost ansible_connection=local localhost ansible_connection=local

View File

@ -211,10 +211,6 @@
msg: "Please check the api_interface settings - interface {{ api_interface }} is not active" msg: "Please check the api_interface settings - interface {{ api_interface }} is not active"
when: not hostvars[inventory_hostname].ansible_facts[api_interface]['active'] when: not hostvars[inventory_hostname].ansible_facts[api_interface]['active']
- name: "Debug"
ansible.builtin.debug:
msg: "{{ api_interface_address }}"
- name: "Checking the api_interface ip address configuration" - name: "Checking the api_interface ip address configuration"
ansible.builtin.fail: ansible.builtin.fail:
msg: "Please check the api_interface settings - interface {{ api_interface }} ip address problem" msg: "Please check the api_interface settings - interface {{ api_interface }} ip address problem"

View File

@ -31,7 +31,7 @@
- name: "Create consul agents token" - name: "Create consul agents token"
when: when:
- _consul_init_secret.changed # - _consul_init_secret.changed
- consul_acl_configuration.enabled - consul_acl_configuration.enabled
block: block:
- name: "Create consul agents token" # noqa: run-once[task] no-handler - name: "Create consul agents token" # noqa: run-once[task] no-handler

View File

@ -10,6 +10,17 @@
}}" }}"
when: when:
- hashicorp_consul_configuration_string is defined - hashicorp_consul_configuration_string is defined
- name: "Consul | Merge servers specific stringified configuration"
vars:
_config_to_merge: "{{ hashicorp_consul_servers_configuration_string }}"
ansible.builtin.set_fact:
hashicorp_consul_configuration: "{{
hashicorp_consul_configuration |
combine(_config_to_merge|from_yaml, recursive=true)
}}"
when:
- hashicorp_consul_configuration_string is defined
- "'consul_servers' in group_names" - "'consul_servers' in group_names"
- name: "Consul | Merge addresses configuration" - name: "Consul | Merge addresses configuration"

View File

@ -15,6 +15,10 @@
- name: "Register haproxy services in consul" - name: "Register haproxy services in consul"
community.general.consul: community.general.consul:
token: "{{ _credentials.consul.root_token.secret_id }}" token: "{{ _credentials.consul.root_token.secret_id }}"
host: "127.0.0.1"
scheme: "{{ consul_api_scheme }}"
port: "{{ consul_api_port[consul_api_scheme] }}"
validate_certs: false
service_name: haproxy service_name: haproxy
service_port: 80 service_port: 80
interval: 20s interval: 20s

View File

@ -45,3 +45,10 @@
when: when:
- enable_vault | bool - enable_vault | bool
- "'vault_servers' in group_names" - "'vault_servers' in group_names"
- name: "Merge nomad configurations"
ansible.builtin.import_tasks:
file: "nomad/nomad_vars.yml"
when:
- enable_nomad | bool
- "('nomad_servers' in group_names) or ('nomad_clients' in group_names)"

View File

@ -142,9 +142,6 @@
delegate_to: localhost delegate_to: localhost
when: _hashistack_ca_directory.stat.exists and _hashistack_ca_directory.stat.isdir when: _hashistack_ca_directory.stat.exists and _hashistack_ca_directory.stat.isdir
- ansible.builtin.debug:
msg: "{{ _hashistack_cacert_files }}"
- name: "Ensure remote ca directory exists" - name: "Ensure remote ca directory exists"
ansible.builtin.file: ansible.builtin.file:
path: "{{ hashistack_remote_config_dir }}/ca" path: "{{ hashistack_remote_config_dir }}/ca"
@ -207,10 +204,3 @@
when: when:
- enable_vault | bool - enable_vault | bool
- "'vault_servers' in group_names" - "'vault_servers' in group_names"
- debug:
msg: "{{ deploy_haproxy_frontends }}"
- debug:
msg: "{{ deploy_haproxy_backends }}"
# - fail:

View File

@ -13,9 +13,6 @@
delegate_to: localhost delegate_to: localhost
when: _hashistack_ca_directory.stat.exists and _hashistack_ca_directory.stat.isdir when: _hashistack_ca_directory.stat.exists and _hashistack_ca_directory.stat.isdir
- ansible.builtin.debug:
msg: "{{ _hashistack_cacert_files }}"
- name: "Ensure remote ca directory exists" - name: "Ensure remote ca directory exists"
ansible.builtin.file: ansible.builtin.file:
path: "{{ hashistack_remote_config_dir }}/ca" path: "{{ hashistack_remote_config_dir }}/ca"

View File

@ -44,7 +44,3 @@
_credentials: "{{ _credentials | combine(_config_to_merge, recursive=true) }}" _credentials: "{{ _credentials | combine(_config_to_merge, recursive=true) }}"
when: _vault_credentials_file.stat.exists when: _vault_credentials_file.stat.exists
delegate_to: localhost delegate_to: localhost
- name: "Debug _credentials"
ansible.builtin.debug:
msg: "{{ _credentials }}"

View File

@ -0,0 +1,82 @@
---
- name: "Nomad"
block:
- name: "Create consul tokens for service registration"
when:
- enable_consul
- nomad_enable_consul_integration
delegate_to: "{{ groups['consul_servers'] | first }}"
vars:
_consul_host: "{{ hostvars[groups['consul_servers'][0]].api_interface_address }}"
_consul_port: "{{ hostvars[groups['consul_servers'][0]].consul_api_port[hostvars[groups['consul_servers'][0]].consul_api_scheme] }}"
_consul_scheme: "{{ hostvars[groups['consul_servers'][0]].consul_api_scheme }}"
run_once: true
block:
- name: "Create server credentials"
block:
- name: "Create consul server policy"
community.general.consul_policy:
token: "{{ _credentials.consul.root_token.secret_id }}"
host: "{{ _consul_host }}"
port: "{{ _consul_port }}"
scheme: "{{ _consul_scheme }}"
validate_certs: false
state: present
name: nomad-server-policy
rules: "{{ nomad_consul_integration_server_policy }}"
register: _consul_nomad_server_policy
- name: "Create consul server token"
community.general.consul_token:
token: "{{ _credentials.consul.root_token.secret_id }}"
host: "{{ _consul_host }}"
port: "{{ _consul_port }}"
scheme: "{{ _consul_scheme }}"
validate_certs: false
accessor_id: "{{ _credentials.consul.tokens.nomad.server.accessor_id }}"
secret_id: "{{ _credentials.consul.tokens.nomad.server.secret_id }}"
policies:
- id: "{{ _consul_nomad_server_policy.policy.ID }}"
state: present
when: _consul_nomad_server_policy.changed
- name: "Create client credentials"
block:
- name: "Create consul client policy"
community.general.consul_policy:
token: "{{ _credentials.consul.root_token.secret_id }}"
host: "{{ _consul_host }}"
port: "{{ _consul_port }}"
scheme: "{{ _consul_scheme }}"
validate_certs: false
state: present
name: nomad-client-policy
rules: "{{ nomad_consul_integration_client_policy }}"
register: _consul_nomad_client_policy
- name: "Create consul client token"
community.general.consul_token:
token: "{{ _credentials.consul.root_token.secret_id }}"
host: "{{ _consul_host }}"
port: "{{ _consul_port }}"
scheme: "{{ _consul_scheme }}"
validate_certs: false
accessor_id: "{{ _credentials.consul.tokens.nomad.client.accessor_id }}"
secret_id: "{{ _credentials.consul.tokens.nomad.client.secret_id }}"
policies:
- id: "{{ _consul_nomad_client_policy.policy.ID }}"
state: present
when: _consul_nomad_client_policy.changed
- name: "Include ednz_cloud.hashicorp_nomad"
ansible.builtin.include_role:
name: ednz_cloud.hashicorp_nomad
- name: "Initialize nomad cluster" # noqa: run-once[task]
ednz_cloud.hashistack.nomad_acl_bootstrap:
bootstrap_secret: "{{ _credentials.nomad.root_token.secret_id }}"
api_url: "{{ nomad_api_addr }}"
run_once: true
delegate_to: "{{ groups['nomad_servers'] | first }}"
register: _nomad_init_secret
when: hashicorp_nomad_configuration.acl.enabled

View File

@ -0,0 +1,115 @@
---
# hashistack configuration merging for nomad
- name: "Nomad | Merge stringified configuration"
vars:
_config_to_merge: "{{ hashicorp_nomad_configuration_string }}"
ansible.builtin.set_fact:
hashicorp_nomad_configuration: "{{
hashicorp_nomad_configuration |
combine(_config_to_merge|from_yaml, recursive=true)
}}"
when:
- hashicorp_nomad_configuration_string is defined
- "'nomad_servers' in group_names"
- name: "Nomad | Merge addresses configuration"
vars:
_config_to_merge: "{{ nomad_address_configuration }}"
ansible.builtin.set_fact:
hashicorp_nomad_configuration: "{{
hashicorp_nomad_configuration |
combine(_config_to_merge, recursive=true)
}}"
when: nomad_address_configuration is defined
- name: "Nomad | Merge consul integration configuration"
when:
- enable_consul | bool
- nomad_enable_consul_integration | bool
block:
- name: "Nomad | Merge consul tls configuration"
when:
- nomad_consul_integration_configuration.ssl is defined
- nomad_consul_integration_configuration.ssl | bool
block:
- name: "Nomad | Merge consul default client configuration"
vars:
_config_to_merge: "{{ nomad_consul_integration_tls_configuration }}"
ansible.builtin.set_fact:
nomad_consul_integration_configuration: "{{
nomad_consul_integration_configuration |
combine(_config_to_merge, recursive=true)
}}"
- name: "Nomad | Merge consul configuration for nomad servers"
when:
- nomad_enable_server
block:
- name: "Nomad | Merge consul default server configuration"
vars:
_config_to_merge: "{{ nomad_consul_integration_server_configuration }}"
ansible.builtin.set_fact:
nomad_consul_integration_configuration: "{{
nomad_consul_integration_configuration |
combine(_config_to_merge, recursive=true)
}}"
- name: "Nomad | Merge consul configuration for nomad clients"
when:
- nomad_enable_client
block:
- name: "Nomad | Merge consul default client configuration"
vars:
_config_to_merge: "{{ nomad_consul_integration_client_configuration }}"
ansible.builtin.set_fact:
nomad_consul_integration_configuration: "{{
nomad_consul_integration_configuration |
combine(_config_to_merge, recursive=true)
}}"
- name: "Nomad | Merge consul tls client configuration"
vars:
_config_to_merge: "{{ nomad_consul_integration_client_tls_configuration }}"
ansible.builtin.set_fact:
nomad_consul_integration_configuration: "{{
nomad_consul_integration_configuration |
combine(_config_to_merge, recursive=true)
}}"
when:
- nomad_consul_integration_configuration.ssl is defined
- nomad_consul_integration_configuration.ssl | bool
- name: "Nomad | Merge consul block into main configuration"
vars:
_config_to_merge:
consul: "{{ nomad_consul_integration_configuration }}"
ansible.builtin.set_fact:
hashicorp_nomad_configuration: "{{
hashicorp_nomad_configuration |
combine(_config_to_merge, recursive=true)
}}"
- name: "Nomad | Merge TLS configuration"
vars:
_config_to_merge:
tls: "{{ nomad_tls_configuration }}"
ansible.builtin.set_fact:
hashicorp_nomad_configuration: "{{
hashicorp_nomad_configuration |
combine(_config_to_merge, recursive=true)
}}"
when: nomad_enable_tls
- name: "Nomad | Merge extra configuration settings"
vars:
_config_to_merge: "{{ nomad_extra_configuration }}"
ansible.builtin.set_fact:
hashicorp_nomad_configuration: "{{
hashicorp_nomad_configuration |
combine(_config_to_merge, recursive=true)
}}"
when: nomad_extra_configuration is defined
- name: "Print nomad configuration"
ansible.builtin.debug:
msg: "{{ hashicorp_nomad_configuration }}"

View File

@ -10,6 +10,13 @@ consul:
vault: vault:
accessor_id: "{{ _consul_vault_accessor }}" accessor_id: "{{ _consul_vault_accessor }}"
secret_id: "{{ _consul_vault_token }}" secret_id: "{{ _consul_vault_token }}"
nomad:
server:
accessor_id: "{{ _consul_nomad_server_accessor }}"
secret_id: "{{ _consul_nomad_server_token }}"
client:
accessor_id: "{{ _consul_nomad_client_accessor }}"
secret_id: "{{ _consul_nomad_client_token }}"
nomad: nomad:
gossip_encryption_key: "{{ _nomad_gossip_encryption_key }}" gossip_encryption_key: "{{ _nomad_gossip_encryption_key }}"
root_token: root_token:

View File

@ -0,0 +1,146 @@
#!/usr/bin/python
from __future__ import absolute_import, division, print_function
from typing import Tuple
__metaclass__ = type
DOCUMENTATION = r"""
---
module: ednz_cloud.hashistack.nomad_acl_bootstrap
short_description: Manages the ACL bootstrap of HashiCorp Nomad.
description:
- This module bootstraps HashiCorp Nomad ACL, ensuring that it is securely set up for use.
requirements:
- C(requests) (L(Python library,https://requests.readthedocs.io/en/latest/))
options:
api_url:
description: The URL of the HashiCorp Nomad API.
required: true
type: str
bootstrap_secret:
description:
- The secret to use for the bootstrap operation.
required: false
type: str
tls_verify:
description:
- Whether to verify the TLS certificate of the Nomad API URL.
- Default is true.
required: false
type: bool
default: true
author:
- Bertrand Lanson (@ednz_cloud)
"""
EXAMPLES = r"""
# Example: Bootstrap HashiCorp Nomad ACL with default settings
- name: Bootstrap HashiCorp Nomad ACL
ednz_cloud.hashistack.nomad_acl_bootstrap:
api_url: https://nomad.example.com
# Example: Bootstrap HashiCorp Nomad ACL with a custom bootstrap secret
- name: Bootstrap HashiCorp Nomad ACL with custom settings
ednz_cloud.hashistack.nomad_acl_bootstrap:
api_url: https://nomad.example.com
bootstrap_secret: 2b778dd9-f5f1-6f29-b4b4-9a5fa948757a
"""
RETURN = r"""
state:
description:
- Information about the state of HashiCorp Nomad after ACL bootstrap.
- This is a complex dictionary with details of the bootstrap.
type: dict
returned: always
sample:
- AccessorID: "b780e702-98ce-521f-2e5f-c6b87de05b24",
- SecretID: "3f4a0fcd-7c42-773c-25db-2d31ba0c05fe",
- Name: "Bootstrap Token",
- Type: "management",
- Policies: null,
- Global: true,
- CreateTime: "2017-08-23T22:47:14.695408057Z",
- CreateIndex: 7,
- ModifyIndex: 7
"""
from ansible.module_utils.basic import AnsibleModule
import traceback
try:
import requests
except ImportError:
HAS_REQUESTS = False
REQUESTS_IMPORT_ERROR = traceback.format_exc()
else:
REQUESTS_IMPORT_ERROR = None
HAS_REQUESTS = True
def bootstrap_nomad_acl(
api_url: str, tls_verify: bool, bootstrap_secret: str
) -> Tuple[bool, dict]:
payload = {}
if bootstrap_secret:
payload["BootstrapSecret"] = bootstrap_secret
try:
response = requests.put(
f"{api_url}/v1/acl/bootstrap", json=payload, verify=tls_verify
)
response.raise_for_status()
return True, response.json()
except requests.exceptions.RequestException as e:
if (
response.status_code == 400
and "ACL bootstrap already done" in response.text
):
return False, {"message": "Nomad ACL system is already bootstrapped"}
raise ValueError(f"Nomad ACL bootstrap failed: {str(e)}")
def run_module():
module_args = dict(
api_url=dict(type="str", required=True),
bootstrap_secret=dict(type="str", required=False, no_log=True),
tls_verify=dict(type="bool", required=False, default=True),
)
result = dict(changed=False, state="")
module = AnsibleModule(argument_spec=module_args, supports_check_mode=False)
if not HAS_REQUESTS:
module.fail_json(
msg="Missing required library: requests", exception=REQUESTS_IMPORT_ERROR
)
try:
changed, response_data = bootstrap_nomad_acl(
api_url=module.params["api_url"],
tls_verify=module.params["tls_verify"],
bootstrap_secret=module.params.get("bootstrap_secret"),
)
result["changed"] = changed
result["state"] = response_data
module.exit_json(**result)
except ValueError as e:
module.fail_json(msg=str(e))
def main():
run_module()
if __name__ == "__main__":
main()

View File

@ -44,12 +44,12 @@ author:
EXAMPLES = r""" EXAMPLES = r"""
# Example: Initialize HashiCorp Vault with default settings # Example: Initialize HashiCorp Vault with default settings
- name: Initialize HashiCorp Vault - name: Initialize HashiCorp Vault
my_namespace.my_collection.my_test: ednz_cloud.hashistack.vault_init:
api_url: https://vault.example.com api_url: https://vault.example.com
# Example: Initialize HashiCorp Vault with custom key shares and threshold # Example: Initialize HashiCorp Vault with custom key shares and threshold
- name: Initialize HashiCorp Vault with custom settings - name: Initialize HashiCorp Vault with custom settings
my_namespace.my_collection.my_test: ednz_cloud.hashistack.vault_init:
api_url: https://vault.example.com api_url: https://vault.example.com
key_shares: 7 key_shares: 7
key_threshold: 4 key_threshold: 4