{"heat_template_version": "wallaby", "description": "OpenStack containerized HAproxy service\n", "parameters": {"ContainerHAProxyImage": {"description": "image", "type": "string", "tags": ["role_specific"]}, "ContainerHAProxyConfigImage": {"description": "The container image to use for the haproxy config_volume", "type": "string", "tags": ["role_specific"]}, "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"}, "EndpointMap": {"default": {}, "description": "Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry.", "type": "json"}, "HAProxyStatsPassword": {"description": "Password for HAProxy stats endpoint", "hidden": true, "type": "string"}, "HAProxyStatsUser": {"description": "User for HAProxy stats endpoint", "default": "admin", "type": "string"}, "HAProxyLoggingSource": {"type": "json", "default": {"tag": "openstack.haproxy", "file": "/var/log/containers/haproxy/haproxy.log", "startmsg.regex": "^[a-zA-Z]{3} [ 123][0-9] [:0-9]{8}"}}, "HAProxySyslogAddress": {"default": "/dev/log", "description": "Syslog address where HAproxy will send its log", "type": "string"}, "HAProxySyslogFacility": {"default": "local0", "description": "Syslog facility HAProxy will use for its logs", "type": "string"}, "SSLCertificate": {"default": "", "description": "The content of the SSL certificate (without Key) in PEM format.\n", "type": "string"}, "PublicSSLCertificateAutogenerated": {"default": false, "description": "Whether the public SSL certificate was autogenerated or not.\n", "type": "boolean"}, "EnablePublicTLS": {"default": true, "description": "Whether to enable TLS on the public interface or not.\n", "type": "boolean"}, "DeployedSSLCertificatePath": {"default": "/etc/pki/tls/private/overcloud_endpoint.pem", "description": "The filepath of the certificate as it will be stored in the controller.\n", "type": "string"}, "RedisPassword": {"description": "The password for the redis service account.", "type": "string", "hidden": true}, "MonitoringSubscriptionHaproxy": {"default": "overcloud-haproxy", "type": "string"}, "RoleName": {"default": "", "description": "Role name on which the service is applied", "type": "string"}, "RoleParameters": {"default": {}, "description": "Parameters specific to the role", "type": "json"}, "EnableInternalTLS": {"type": "boolean", "default": false}, "InternalTLSCAFile": {"default": "/etc/ipa/ca.crt", "type": "string", "description": "Specifies the default CA cert to use if TLS is used for services in the internal network."}, "ConfigDebug": {"default": false, "description": "Whether to run config management (e.g. Puppet) in debug mode.", "type": "boolean"}, "EnableLoadBalancer": {"default": true, "description": "Whether to deploy a LoadBalancer, set to false when an external load balancer is used.", "type": "boolean"}, "HAProxyStatsEnabled": {"default": true, "description": "Whether or not to enable the HAProxy stats interface.", "type": "boolean"}, "InternalTLSCRLPEMFile": {"default": "/etc/pki/CA/crl/overcloud-crl.pem", "type": "string", "description": "Specifies the default CRL PEM file to use for revocation if TLS is used for services in the internal network."}, "InternalTLSCRLPEMDir": {"default": "/etc/pki/CA/crl/", "type": "string", "description": "The directory of the CRL PEM file to be mounted."}}, "conditions": {"public_tls_enabled": {"and": [{"get_param": "EnablePublicTLS"}, {"or": [{"not": {"equals": [{"get_param": "SSLCertificate"}, ""]}}, {"get_param": "PublicSSLCertificateAutogenerated"}]}]}}, "resources": {"ContainersCommon": {"type": "file:///usr/share/openstack-tripleo-heat-templates/deployment/containers-common.yaml"}, "HAProxyLogging": {"type": "OS::TripleO::Services::Logging::HAProxy"}, "HAProxyPublicTLS": {"type": "OS::TripleO::Services::HAProxyPublicTLS", "properties": {"ServiceData": {"get_param": "ServiceData"}, "ServiceNetMap": {"get_param": "ServiceNetMap"}, "EndpointMap": {"get_param": "EndpointMap"}, "RoleName": {"get_param": "RoleName"}, "RoleParameters": {"get_param": "RoleParameters"}}}, "HAProxyInternalTLS": {"type": "OS::TripleO::Services::HAProxyInternalTLS", "properties": {"ServiceData": {"get_param": "ServiceData"}, "ServiceNetMap": {"get_param": "ServiceNetMap"}, "EndpointMap": {"get_param": "EndpointMap"}, "RoleName": {"get_param": "RoleName"}, "RoleParameters": {"get_param": "RoleParameters"}}}, "RoleParametersValue": {"type": "OS::Heat::Value", "properties": {"type": "json", "value": {"map_replace": [{"map_replace": [{"ContainerHAProxyImage": "ContainerHAProxyImage", "ContainerHAProxyConfigImage": "ContainerHAProxyConfigImage"}, {"values": {"get_param": ["RoleParameters"]}}]}, {"values": {"ContainerHAProxyImage": {"get_param": "ContainerHAProxyImage"}, "ContainerHAProxyConfigImage": {"get_param": "ContainerHAProxyConfigImage"}}}]}}}}, "outputs": {"role_data": {"description": "Role data for the HAproxy role.", "value": {"service_name": "haproxy", "firewall_rules": {"107 haproxy stats": {"dport": 1993}}, "monitoring_subscription": {"get_param": "MonitoringSubscriptionHaproxy"}, "ansible_group_vars": {"tripleo_firewall_frontend_enabled": true, "tripleo_firewall_ssl_frontend_enabled": {"if": ["public_tls_enabled", true]}}, "config_settings": {"map_merge": [{"get_attr": ["HAProxyLogging", "config_settings"]}, {"tripleo::haproxy::haproxy_service_manage": false, "tripleo::haproxy::haproxy_log_address": {"get_param": "HAProxySyslogAddress"}, "tripleo::haproxy::haproxy_log_facility": {"get_param": "HAProxySyslogFacility"}, "tripleo::haproxy::haproxy_stats_user": {"get_param": "HAProxyStatsUser"}, "tripleo::haproxy::haproxy_stats_password": {"get_param": "HAProxyStatsPassword"}, "tripleo::haproxy::haproxy_stats_bind_address": {"str_replace": {"template": "%{hiera('$NETWORK')}", "params": {"$NETWORK": {"get_param": ["ServiceNetMap", "HaproxyNetwork"]}}}}, "tripleo::haproxy::redis_password": {"get_param": "RedisPassword"}, "tripleo::haproxy::crl_file": null, "tripleo::haproxy::haproxy_stats": {"get_param": "HAProxyStatsEnabled"}, "enable_load_balancer": {"get_param": "EnableLoadBalancer"}, "tripleo::profile::base::haproxy::certificates_specs": {"map_merge": [{"get_attr": ["HAProxyPublicTLS", "role_data", "certificates_specs"]}, {"get_attr": ["HAProxyInternalTLS", "role_data", "certificates_specs"]}]}, "tripleo::haproxy::service_certificate": {"if": ["public_tls_enabled", {"get_param": "DeployedSSLCertificatePath"}]}, "tripleo::haproxy::ca_bundle": {"if": [{"get_param": "EnableInternalTLS"}, {"get_param": "InternalTLSCAFile"}]}}, {"get_attr": ["HAProxyPublicTLS", "role_data", "config_settings"]}, {"get_attr": ["HAProxyInternalTLS", "role_data", "config_settings"]}]}, "service_config_settings": {"rsyslog": {"tripleo_logging_sources_haproxy": [{"get_param": "HAProxyLoggingSource"}]}}, "puppet_config": {"config_volume": "haproxy", "puppet_tags": "haproxy_config", "step_config": "class {'tripleo::profile::base::haproxy': manage_firewall => false}\n", "config_image": {"get_attr": ["RoleParametersValue", "value", "ContainerHAProxyConfigImage"]}, "volumes": {"list_concat": [{"if": ["public_tls_enabled", [{"list_join": [":", [{"get_param": "DeployedSSLCertificatePath"}, {"get_param": "DeployedSSLCertificatePath"}, "ro,shared"]]}]]}, {"if": [{"get_param": "EnableInternalTLS"}, ["/etc/pki/tls/certs/haproxy:/etc/pki/tls/certs/haproxy:ro,shared", "/etc/pki/tls/private/haproxy:/etc/pki/tls/private/haproxy:ro,shared", {"list_join": [":", [{"get_param": "InternalTLSCAFile"}, {"get_param": "InternalTLSCAFile"}, "ro,shared"]]}, {"list_join": [":", [{"get_param": "InternalTLSCRLPEMDir"}, {"get_param": "InternalTLSCRLPEMDir"}, "ro,shared"]]}]]}]}}, "kolla_config": {"/var/lib/kolla/config_files/haproxy.json": {"command": "bash -c $* -- eval if [ -f /usr/sbin/haproxy-systemd-wrapper ]; then exec /usr/sbin/haproxy-systemd-wrapper -f /etc/haproxy/haproxy.cfg; else exec /usr/sbin/haproxy -f /etc/haproxy/haproxy.cfg -Ws; fi", "config_files": [{"source": "/var/lib/kolla/config_files/src/*", "dest": "/", "merge": true, "preserve_properties": true}, {"source": "/var/lib/kolla/config_files/src-tls/*", "dest": "/", "merge": true, "preserve_properties": true, "optional": true}], "permissions": [{"path": "/var/lib/haproxy", "owner": "haproxy:haproxy", "recurse": true}, {"path": "/etc/pki/tls/certs/haproxy", "owner": "haproxy:haproxy", "recurse": true, "optional": true}]}}, "container_config_scripts": {"get_attr": ["ContainersCommon", "container_config_scripts"]}, "docker_config": {"step_1": {"map_merge": [{"get_attr": ["HAProxyLogging", "docker_config", "step_1"]}, {"haproxy": {"start_order": 1, "image": {"get_attr": ["RoleParametersValue", "value", "ContainerHAProxyImage"]}, "net": "host", "restart": "always", "security_opt": ["label=disable"], "volumes": {"list_concat": [{"get_attr": ["ContainersCommon", "volumes"]}, {"get_attr": ["HAProxyLogging", "volumes"]}, ["/var/lib/kolla/config_files/haproxy.json:/var/lib/kolla/config_files/config.json:ro", "/var/lib/config-data/puppet-generated/haproxy:/var/lib/kolla/config_files/src:ro", "/var/lib/haproxy:/var/lib/haproxy:rw,z"], {"if": ["public_tls_enabled", [{"list_join": [":", [{"get_param": "DeployedSSLCertificatePath"}, {"list_join": ["", ["/var/lib/kolla/config_files/src-tls", {"get_param": "DeployedSSLCertificatePath"}]]}, "ro,shared"]]}]]}, {"if": [{"get_param": "EnableInternalTLS"}, ["/etc/pki/tls/certs/haproxy:/var/lib/kolla/config_files/src-tls/etc/pki/tls/certs/haproxy:ro,shared", "/etc/pki/tls/private/haproxy:/var/lib/kolla/config_files/src-tls/etc/pki/tls/private/haproxy:ro,shared", {"list_join": [":", [{"get_param": "InternalTLSCRLPEMDir"}, {"get_param": "InternalTLSCRLPEMDir"}, "ro"]]}]]}]}, "environment": {"KOLLA_CONFIG_STRATEGY": "COPY_ALWAYS"}}}]}}, "deploy_steps_tasks": {"list_concat": [[{"name": "Configure rsyslog for HAproxy container", "when": "step|int == 1", "block": [{"name": "Check if rsyslog exists", "shell": "systemctl is-active rsyslog", "register": "rsyslog_config"}, {"when": ["rsyslog_config is changed", "rsyslog_config.rc == 0"], "block": [{"name": "Forward logging to haproxy.log file", "blockinfile": {"content": "if $syslogfacility-text == '{{facility}}' and $programname == 'haproxy' then -/var/log/containers/haproxy/haproxy.log\n& stop\n", "create": true, "path": "/etc/rsyslog.d/openstack-haproxy.conf"}, "vars": {"facility": {"get_param": "HAProxySyslogFacility"}}, "register": "logconfig"}, {"name": "restart rsyslog service after logging conf change", "service": {"name": "rsyslog", "state": "restarted"}, "when": "logconfig is changed"}]}]}, {"name": "Run puppet on the host to apply IPtables rules", "no_log": true, "when": "step|int == 1", "register": "puppet_host_outputs", "shell": "puppet apply {{ (puppet_debug|bool) | ternary('--debug --verbose', '') }} --detailed-exitcodes --summarize --color=false \\\n --modulepath '{{ puppet_modulepath }}' --tags '{{ puppet_tags }}' -e '{{ puppet_execute }}'\n", "changed_when": "puppet_host_outputs.rc == 2", "failed_when": false, "vars": {"puppet_execute": "include tripleo::profile::base::haproxy", "puppet_tags": "tripleo::firewall::rule", "puppet_modulepath": "/etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules", "puppet_debug": {"get_param": "ConfigDebug"}}}, {"name": "Debug output for task: Run puppet on the host to apply IPtables rules", "debug": {"var": "puppet_host_outputs.stdout_lines | default([]) | union(puppet_host_outputs.stderr_lines | default([]))"}, "when": ["not (ansible_check_mode | bool)", "puppet_host_outputs.rc is defined"], "failed_when": "puppet_host_outputs.rc not in [0, 2]"}], {"if": ["public_tls_enabled", {"get_attr": ["HAProxyPublicTLS", "role_data", "deploy_steps_tasks"]}]}, {"if": [{"get_param": "EnableInternalTLS"}, {"get_attr": ["HAProxyInternalTLS", "role_data", "deploy_steps_tasks"]}]}]}, "upgrade_tasks": [{"name": "ensure we have haproxy log dir with the correct setype", "file": {"path": "/var/log/containers/haproxy", "state": "directory", "setype": "var_log_t", "recurse": true}, "when": "step|int == 1"}], "external_upgrade_tasks": [{"when": ["step|int == 1"], "tags": ["never", "system_upgrade_transfer_data", "system_upgrade_stop_services"], "block": [{"name": "Stop haproxy container", "import_role": {"name": "tripleo_container_stop"}, "vars": {"tripleo_containers_to_stop": ["haproxy"], "tripleo_delegate_to": "{{ groups['haproxy'] | difference(groups['excluded_overcloud']) }}"}}]}], "host_prep_tasks": {"list_concat": [{"get_attr": ["HAProxyPublicTLS", "role_data", "host_prep_tasks"]}, [{"name": "create persistent directories", "file": {"path": "{{ item.path }}", "state": "directory", "setype": "{{ item.setype }}", "mode": "{{ item.mode|default(omit) }}"}, "with_items": [{"path": "/var/log/containers/haproxy", "setype": "var_log_t", "mode": "0750"}, {"path": "/var/lib/haproxy", "setype": "container_file_t"}]}]]}, "metadata_settings": {"list_concat": [{"get_attr": ["HAProxyPublicTLS", "role_data", "metadata_settings"]}, {"get_attr": ["HAProxyInternalTLS", "role_data", "metadata_settings"]}]}}}}}