a235b70b2e
Follows-up I4b40d73ab329dc219ee7a387201b0747a6233ed4 Do not fail if haproxy container UUID changes. Reasoning behind: at the time the chgrp&HUP block is executed, the new cert has already been deployed on the host, with the correct owner already set. So if the container_id changes at this time, it will pick up the new cert automatically. That means that by ignoring errors caused by mismatching UUID we'd skip an unnecessary consequent restart of the newly spawned container, ending up with the same result. So the safest path here would provide a sort of a cascading failure for the crasher->restarted->reloaded once again containers. Related rhbz#1973674 Closes-bug: #1940729 Signed-off-by: Bogdan Dobrelya <bdobreli@redhat.com> Change-Id: Ib0dd1516592428413452b8a260182f36e42d5b3d
191 lines
7.2 KiB
YAML
191 lines
7.2 KiB
YAML
heat_template_version: wallaby
|
|
|
|
description: >
|
|
HAProxy deployment with TLS enabled, with an injected certificate
|
|
|
|
parameters:
|
|
ServiceData:
|
|
default: {}
|
|
description: Dictionary packing service data
|
|
type: json
|
|
ServiceNetMap:
|
|
default: {}
|
|
description: Mapping of service_name -> network name. Typically set
|
|
via parameter_defaults in the resource registry. Use
|
|
parameter_merge_strategies to merge it with the defaults.
|
|
type: json
|
|
RoleName:
|
|
default: ''
|
|
description: Role name on which the service is applied
|
|
type: string
|
|
RoleParameters:
|
|
default: {}
|
|
description: Parameters specific to the role
|
|
type: json
|
|
EndpointMap:
|
|
default: {}
|
|
description: Mapping of service endpoint -> protocol. Typically set
|
|
via parameter_defaults in the resource registry.
|
|
type: json
|
|
# Can be overridden via parameter_defaults in the environment
|
|
SSLCertificate:
|
|
default: ''
|
|
description: >
|
|
The content of the SSL certificate (without Key) in PEM format.
|
|
type: string
|
|
SSLIntermediateCertificate:
|
|
default: ''
|
|
description: >
|
|
The content of an SSL intermediate CA certificate in PEM format.
|
|
type: string
|
|
# NOTE(jaosorior): Adding this default is only while we enable TLS by default
|
|
# for the overcloud. It'll be removed in a subsequent patch.
|
|
SSLKey:
|
|
default: ''
|
|
description: >
|
|
The content of the SSL Key in PEM format.
|
|
type: string
|
|
hidden: true
|
|
DeployedSSLCertificatePath:
|
|
default: '/etc/pki/tls/private/overcloud_endpoint.pem'
|
|
description: >
|
|
The filepath of the certificate as it will be stored in the controller.
|
|
type: string
|
|
|
|
outputs:
|
|
role_data:
|
|
description: Role data for the HAProxy public TLS injection.
|
|
value:
|
|
service_name: haproxy_public_tls_inject
|
|
config_settings: {}
|
|
certificates_specs: {}
|
|
metadata_settings: null
|
|
host_prep_tasks:
|
|
- name: get parameters
|
|
set_fact:
|
|
cert_path: {get_param: DeployedSSLCertificatePath}
|
|
cert_content: {get_param: SSLCertificate}
|
|
chain_content: {get_param: SSLIntermediateCertificate}
|
|
key_content: {get_param: SSLKey}
|
|
no_log: "{{ hide_sensitive_logs | bool }}"
|
|
|
|
# We want to ensure we run all this block IFF we have
|
|
# a certificate content.
|
|
- name: manage certificate
|
|
when:
|
|
- cert_content is defined
|
|
- cert_content != ''
|
|
block:
|
|
- name: get DeployedSSLCertificatePath attributes
|
|
register: attr_cert_path
|
|
stat:
|
|
path: "{{cert_path}}"
|
|
|
|
- name: set is_haproxy_bootstrap_node fact
|
|
set_fact: is_haproxy_bootstrap_node={{haproxy_short_bootstrap_node_name | lower == ansible_facts['hostname'] | lower}}
|
|
when:
|
|
- haproxy_short_bootstrap_node_name|default(false)
|
|
|
|
- name: get haproxy status
|
|
register: haproxy_state
|
|
systemd:
|
|
name: haproxy
|
|
|
|
- name: get pacemaker status
|
|
register: pacemaker_state
|
|
systemd:
|
|
name: pacemaker
|
|
|
|
- name: get docker status
|
|
register: docker_state
|
|
systemd:
|
|
name: docker
|
|
|
|
- name: get container_id
|
|
when:
|
|
- docker_state.status.ActiveState == 'active' or container_cli == 'podman'
|
|
- attr_cert_path.stat.exists
|
|
- attr_cert_path.stat.isdir == False
|
|
command: "{{ container_cli }} ps -q -f name=haproxy"
|
|
register: container_id
|
|
|
|
- name: get pcs resource name for haproxy container
|
|
when:
|
|
- bootstrap_node is defined
|
|
- is_haproxy_bootstrap_node
|
|
- pacemaker_state.status.ActiveState == 'active'
|
|
- attr_cert_path.stat.exists
|
|
- attr_cert_path.stat.isdir
|
|
shell: |
|
|
pcs status resources | sed -n 's/^.*container.*: \(haproxy.*\) .*/\1/p'
|
|
register: pacemaker_resource
|
|
|
|
# It might happen docker has started priori the file creation - it will then create a
|
|
# directory. We have to drop that directory in order to push our file.
|
|
- name: remove DeployedSSLCertificatePath if is dir
|
|
when: attr_cert_path.stat.isdir is defined and attr_cert_path.stat.isdir
|
|
file:
|
|
path: "{{cert_path}}"
|
|
state: absent
|
|
|
|
# In containerized env, haproxy group does not exist.
|
|
# We hence need to do this file creation in two distinct steps
|
|
# and ignore failure on the ownership change.
|
|
- name: push certificate content
|
|
no_log: "{{ hide_sensitive_logs | bool }}"
|
|
copy:
|
|
dest: "{{cert_path}}"
|
|
mode: 0440
|
|
owner: root
|
|
content: |
|
|
{{cert_content}}
|
|
{{chain_content}}
|
|
{{key_content}}
|
|
|
|
# Set certificate group IFF we're not in container context
|
|
# Also, restart HAProxy service without more concern
|
|
- name: BM haproxy non-pacemaker context
|
|
when: haproxy_state.status.ActiveState == 'active'
|
|
block:
|
|
- name: set certificate ownership
|
|
file:
|
|
path: "{{cert_path}}"
|
|
group: haproxy
|
|
|
|
- name: reload haproxy if enabled
|
|
service:
|
|
name: haproxy
|
|
state: reloaded
|
|
|
|
- name: restart pacemaker resource for haproxy
|
|
when:
|
|
- pacemaker_resource is defined
|
|
- pacemaker_resource.stdout is defined
|
|
- pacemaker_resource.stdout != ''
|
|
command: pcs resource restart "{{pacemaker_resource.stdout}}"
|
|
|
|
# We can't use kolla for certificate updates, so we have to
|
|
# set its rights and restart the service.
|
|
- name: dedicated part for containers
|
|
when:
|
|
- container_id is defined
|
|
- container_id.stdout is defined
|
|
- container_id.stdout != ''
|
|
block:
|
|
- name: copy certificate, chgrp, restart haproxy
|
|
shell: |
|
|
set -e
|
|
if {{ container_cli }} ps -f "id={{ item }}" --format "{{ '{{' }}.Names{{ '}}' }}" | grep -q "^haproxy-bundle"; then
|
|
tar -c {{ cert_path }} | {{container_cli}} exec -i {{ item }} tar -C / -xv
|
|
else
|
|
{{ container_cli }} cp {{ cert_path }} {{ item }}:{{ cert_path }}
|
|
fi
|
|
{{ container_cli }} exec --user root {{ item }} chgrp haproxy {{ cert_path }}
|
|
{{ container_cli }} kill --signal=HUP {{ item }}
|
|
register: container_kill_result
|
|
failed_when:
|
|
- container_kill_result.rc != 0
|
|
- ("no such container" not in container_kill_result.stderr)
|
|
- ("container state improper" not in container_kill_result.stderr)
|
|
with_items: "{{ container_id.stdout.split('\n') }}"
|