tripleo-heat-templates/deployment/haproxy/haproxy-public-tls-inject.yaml
Bogdan Dobrelya a235b70b2e Fix the failure condition for HAproxy chgrp script
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
2021-09-01 16:05:45 +00:00

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') }}"