# certain initialization steps (run in a container) will occur # on the first role listed in the roles file {% set primary_role_name = roles[0].name -%} heat_template_version: ocata description: > Post-deploy configuration steps via puppet for all roles, as defined in ../roles_data.yaml parameters: servers: type: json description: Mapping of Role name e.g Controller to a list of servers role_data: type: json description: Mapping of Role name e.g Controller to the per-role data DeployIdentifier: default: '' type: string description: > Setting this to a unique value will re-run any deployment tasks which perform configuration on a Heat stack-update. EndpointMap: default: {} description: Mapping of service endpoint -> protocol. Typically set via parameter_defaults in the resource registry. type: json resources: # These utility tasks use docker-puppet.py to execute tasks via puppet # We only execute these on the first node in the primary role {{primary_role_name}}DockerPuppetTasks: type: OS::Heat::Value properties: type: json value: yaql: expression: dict($.data.docker_puppet_tasks.where($1 != null).selectMany($.items()).groupBy($[0], $[1])) data: docker_puppet_tasks: {get_param: [role_data, {{primary_role_name}}, docker_puppet_tasks]} # BEGIN primary_role_name docker-puppet-tasks (run only on a single node) {% for step in range(1, 6) %} {{primary_role_name}}DockerPuppetJsonConfig{{step}}: type: OS::Heat::StructuredConfig properties: group: json-file config: /var/lib/docker-puppet/docker-puppet-tasks{{step}}.json: {get_attr: [{{primary_role_name}}DockerPuppetTasks, value, 'step_{{step}}']} {{primary_role_name}}DockerPuppetJsonDeployment{{step}}: type: OS::Heat::SoftwareDeployment properties: server: {get_param: [servers, {{primary_role_name}}, '0']} config: {get_resource: {{primary_role_name}}DockerPuppetJsonConfig{{step}}} {{primary_role_name}}DockerPuppetTasksConfig{{step}}: type: OS::Heat::SoftwareConfig properties: group: script config: {get_file: docker-puppet.py} inputs: - name: CONFIG - name: NET_HOST - name: NO_ARCHIVE - name: STEP {{primary_role_name}}DockerPuppetTasksDeployment{{step}}: type: OS::Heat::SoftwareDeployment depends_on: {% for dep in roles %} - {{dep.name}}Deployment_Step{{step}} - {{dep.name}}ContainersDeployment_Step{{step}} {% endfor %} - {{primary_role_name}}DockerPuppetJsonDeployment{{step}} properties: name: {{primary_role_name}}DockerPuppetJsonDeployment{{step}} server: {get_param: [servers, {{primary_role_name}}, '0']} config: {get_resource: {{primary_role_name}}DockerPuppetTasksConfig{{step}}} input_values: CONFIG: /var/lib/docker-puppet/docker-puppet-tasks{{step}}.json NET_HOST: 'true' NO_ARCHIVE: 'true' STEP: {{step}} {% endfor %} # END primary_role_name docker-puppet-tasks {% for role in roles %} # Post deployment steps for all roles # A single config is re-applied with an incrementing step number # {{role.name}} Role steps {{role.name}}ArtifactsConfig: type: ../puppet/deploy-artifacts.yaml {{role.name}}ArtifactsDeploy: type: OS::Heat::StructuredDeploymentGroup properties: servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}ArtifactsConfig} {{role.name}}PreConfig: type: OS::TripleO::Tasks::{{role.name}}PreConfig properties: servers: {get_param: [servers, {{role.name}}]} input_values: update_identifier: {get_param: DeployIdentifier} {{role.name}}CreateConfigDir: type: OS::Heat::SoftwareConfig properties: group: script config: {get_file: create-config-dir.sh} {{role.name}}CreateConfigDirDeployment: type: OS::Heat::SoftwareDeploymentGroup properties: servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}CreateConfigDir} {{role.name}}HostPrepAnsible: type: OS::Heat::Value properties: value: str_replace: template: CONFIG params: CONFIG: - hosts: localhost connection: local tasks: {get_param: [role_data, {{role.name}}, host_prep_tasks]} {{role.name}}HostPrepConfig: type: OS::Heat::SoftwareConfig properties: group: ansible options: modulepath: /usr/share/ansible-modules config: {get_attr: [{{role.name}}HostPrepAnsible, value]} {{role.name}}HostPrepDeployment: type: OS::Heat::SoftwareDeploymentGroup properties: servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}HostPrepConfig} # this creates a JSON config file for our docker-puppet.py script {{role.name}}GenPuppetConfig: type: OS::Heat::StructuredConfig properties: group: json-file config: /var/lib/docker-puppet/docker-puppet.json: {get_param: [role_data, {{role.name}}, puppet_config]} {{role.name}}GenPuppetDeployment: type: OS::Heat::SoftwareDeploymentGroup properties: servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}GenPuppetConfig} {{role.name}}GenerateConfig: type: OS::Heat::SoftwareConfig properties: group: script config: {get_file: docker-puppet.py} {{role.name}}GenerateConfigDeployment: type: OS::Heat::SoftwareDeploymentGroup depends_on: [{{role.name}}GenPuppetDeployment, {{role.name}}ArtifactsDeploy, {{role.name}}CreateConfigDirDeployment, {{role.name}}HostPrepDeployment] properties: name: {{role.name}}GenerateConfigDeployment servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}GenerateConfig} {{role.name}}PuppetStepConfig: type: OS::Heat::Value properties: type: string value: yaql: expression: # select 'step_config' only from services that do not have a docker_config $.data.service_names.zip($.data.step_config, $.data.docker_config).where($[2] = null).where($[1] != null).select($[1]).join("\n") data: service_names: {get_param: [role_data, {{role.name}}, service_names]} step_config: {get_param: [role_data, {{role.name}}, step_config]} docker_config: {get_param: [role_data, {{role.name}}, docker_config]} {{role.name}}DockerConfig: type: OS::Heat::Value properties: type: json value: yaql: expression: # select 'docker_config' only from services that have it $.data.service_names.zip($.data.docker_config).where($[1] != null).select($[1]).reduce($1.mergeWith($2), {}) data: service_names: {get_param: [role_data, {{role.name}}, service_names]} docker_config: {get_param: [role_data, {{role.name}}, docker_config]} # Here we are dumping all the docker container startup configuration data # so that we can have access to how they are started outside of heat # and docker-cmd. This lets us create command line tools to start and # test these containers. {{role.name}}DockerConfigJsonStartupData: type: OS::Heat::StructuredConfig properties: group: json-file config: /var/lib/docker-container-startup-configs.json: {get_attr: [{{role.name}}DockerConfig, value]} {{role.name}}DockerConfigJsonStartupDataDeployment: type: OS::Heat::SoftwareDeploymentGroup properties: config: {get_resource: {{role.name}}DockerConfigJsonStartupData} servers: {get_param: [servers, {{role.name}}]} {{role.name}}KollaJsonConfig: type: OS::Heat::StructuredConfig properties: group: json-file config: {get_param: [role_data, {{role.name}}, kolla_config]} {{role.name}}KollaJsonDeployment: type: OS::Heat::SoftwareDeploymentGroup properties: name: {{role.name}}KollaJsonDeployment config: {get_resource: {{role.name}}KollaJsonConfig} servers: {get_param: [servers, {{role.name}}]} # BEGIN BAREMETAL CONFIG STEPS {% if role.name == 'Controller' %} ControllerPrePuppet: type: OS::TripleO::Tasks::ControllerPrePuppet properties: servers: {get_param: [servers, Controller]} input_values: update_identifier: {get_param: DeployIdentifier} {% endif %} {{role.name}}Config: type: OS::TripleO::{{role.name}}Config properties: StepConfig: {get_attr: [{{role.name}}PuppetStepConfig, value]} {% for step in range(1, 6) %} {{role.name}}Deployment_Step{{step}}: type: OS::Heat::StructuredDeploymentGroup {% if step == 1 %} depends_on: [{{role.name}}PreConfig, {{role.name}}ArtifactsDeploy] {% else %} depends_on: {% for dep in roles %} - {{dep.name}}Deployment_Step{{step -1}} - {{dep.name}}ContainersDeployment_Step{{step -1}} {% endfor %} - {{primary_role_name}}DockerPuppetTasksDeployment{{step -1}} {% endif %} properties: name: {{role.name}}Deployment_Step{{step}} servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}Config} input_values: step: {{step}} update_identifier: {get_param: DeployIdentifier} {% endfor %} # END BAREMETAL CONFIG STEPS # BEGIN CONTAINER CONFIG STEPS {% for step in range(1, 6) %} {{role.name}}ContainersConfig_Step{{step}}: type: OS::Heat::StructuredConfig properties: group: docker-cmd config: {get_attr: [{{role.name}}DockerConfig, value, step_{{step}}]} {{role.name}}ContainersDeployment_Step{{step}}: type: OS::Heat::StructuredDeploymentGroup {% if step == 1 %} depends_on: - {{role.name}}PreConfig - {{role.name}}KollaJsonDeployment - {{role.name}}GenPuppetDeployment - {{role.name}}GenerateConfigDeployment {% else %} depends_on: {% for dep in roles %} - {{dep.name}}ContainersDeployment_Step{{step -1}} - {{dep.name}}Deployment_Step{{step}} # baremetal steps of the same level run first - {{dep.name}}Deployment_Step{{step -1}} {% endfor %} - {{primary_role_name}}DockerPuppetTasksDeployment{{step -1}} {% endif %} properties: name: {{role.name}}ContainersDeployment_Step{{step}} servers: {get_param: [servers, {{role.name}}]} config: {get_resource: {{role.name}}ContainersConfig_Step{{step}}} {% endfor %} # END CONTAINER CONFIG STEPS {{role.name}}PostConfig: type: OS::TripleO::Tasks::{{role.name}}PostConfig depends_on: {% for dep in roles %} - {{dep.name}}Deployment_Step5 - {{primary_role_name}}DockerPuppetTasksDeployment5 {% endfor %} properties: servers: {get_param: servers} input_values: update_identifier: {get_param: DeployIdentifier} # Note, this should come last, so use depends_on to ensure # this is created after any other resources. {{role.name}}ExtraConfigPost: depends_on: {% for dep in roles %} - {{dep.name}}PostConfig {% endfor %} type: OS::TripleO::NodeExtraConfigPost properties: servers: {get_param: [servers, {{role.name}}]} {% if role.name == 'Controller' %} ControllerPostPuppet: depends_on: - ControllerExtraConfigPost type: OS::TripleO::Tasks::ControllerPostPuppet properties: servers: {get_param: [servers, Controller]} input_values: update_identifier: {get_param: DeployIdentifier} {% endif %} {% endfor %}