Provides a list of per-service ctlplane IPs to the workflows env
[apex-tripleo-heat-templates.git] / docker / docker-steps.j2
1 # certain initialization steps (run in a container) will occur
2 # on the role marked as primary controller or the first role listed
3 {%- set primary_role = [roles[0]] -%}
4 {%- for role in roles -%}
5   {%- if 'primary' in role.tags and 'controller' in role.tags -%}
6     {%- set _ = primary_role.pop() -%}
7     {%- set _ = primary_role.append(role) -%}
8   {%- endif -%}
9 {%- endfor -%}
10 {%- set primary_role_name = primary_role[0].name -%}
11 # primary role is: {{primary_role_name}}
12 {% set deploy_steps_max = 6 -%}
13
14 heat_template_version: pike
15
16 description: >
17   Post-deploy configuration steps via puppet for all roles,
18   as defined in ../roles_data.yaml
19
20 parameters:
21   servers:
22     type: json
23     description: Mapping of Role name e.g Controller to a list of servers
24   stack_name:
25     type: string
26     description: Name of the topmost stack
27   role_data:
28     type: json
29     description: Mapping of Role name e.g Controller to the per-role data
30   DeployIdentifier:
31     default: ''
32     type: string
33     description: >
34       Setting this to a unique value will re-run any deployment tasks which
35       perform configuration on a Heat stack-update.
36   EndpointMap:
37     default: {}
38     description: Mapping of service endpoint -> protocol. Typically set
39                  via parameter_defaults in the resource registry.
40     type: json
41   ctlplane_service_ips:
42     type: json
43
44 conditions:
45 {% for step in range(1, deploy_steps_max) %}
46   WorkflowTasks_Step{{step}}_Enabled:
47     or:
48     {% for role in roles %}
49       - not:
50           equals:
51             - get_param: [role_data, {{role.name}}, service_workflow_tasks, step{{step}}]
52             - ''
53       - False
54     {% endfor %}
55 {% endfor %}
56
57 resources:
58
59   # These utility tasks use docker-puppet.py to execute tasks via puppet
60   # We only execute these on the first node in the primary role
61   {{primary_role_name}}DockerPuppetTasks:
62     type: OS::Heat::Value
63     properties:
64       type: json
65       value:
66         yaql:
67           expression:
68             $.data.default_tasks + dict($.data.docker_puppet_tasks.where($1 != null).selectMany($.items()).groupBy($[0], $[1]))
69           data:
70             docker_puppet_tasks: {get_param: [role_data, {{primary_role_name}}, docker_puppet_tasks]}
71             default_tasks:
72 {%- for step in range(1, deploy_steps_max) %}
73               step_{{step}}: {}
74 {%- endfor %}
75
76   RoleConfig:
77     type: OS::Heat::SoftwareConfig
78     properties:
79       group: ansible
80       options:
81         modulepath: /usr/share/ansible-modules
82       inputs:
83         - name: step
84         - name: role_name
85         - name: update_identifier
86         - name: bootstrap_server_id
87       config: {get_file: deploy-steps-playbook.yaml}
88
89 {%- for step in range(1, deploy_steps_max) %}
90 # BEGIN service_workflow_tasks handling
91   WorkflowTasks_Step{{step}}:
92     type: OS::Mistral::Workflow
93     condition: WorkflowTasks_Step{{step}}_Enabled
94     depends_on:
95     {% if step == 1 %}
96     {% for dep in roles %}
97       - {{dep.name}}PreConfig
98       - {{dep.name}}ArtifactsDeploy
99     {% endfor %}
100     {% else %}
101     {% for dep in roles %}
102       - {{dep.name}}Deployment_Step{{step -1}}
103     {% endfor %}
104     {% endif %}
105     properties:
106       name: {list_join: [".", ["tripleo", {get_param: stack_name}, "workflowtasks", "step{{step}}"]]}
107       type: direct
108       tasks:
109         yaql:
110           expression: $.data.where($ != '').select($.get('step{{step}}')).where($ != null).flatten()
111           data:
112           {% for role in roles %}
113             - get_param: [role_data, {{role.name}}, service_workflow_tasks]
114           {% endfor %}
115
116   WorkflowTasks_Step{{step}}_Execution:
117     type: OS::Mistral::ExternalResource
118     condition: WorkflowTasks_Step{{step}}_Enabled
119     depends_on: WorkflowTasks_Step{{step}}
120     properties:
121       actions:
122         CREATE:
123           workflow: { get_resource: WorkflowTasks_Step{{step}} }
124           params:
125             env:
126               service_ips: { get_param: ctlplane_service_ips }
127         UPDATE:
128           workflow: { get_resource: WorkflowTasks_Step{{step}} }
129           params:
130             env:
131               service_ips: { get_param: ctlplane_service_ips }
132       always_update: true
133 # END service_workflow_tasks handling
134 {% endfor %}
135
136 {% for role in roles %}
137   # Post deployment steps for all roles
138   # A single config is re-applied with an incrementing step number
139   # {{role.name}} Role steps
140   {{role.name}}ArtifactsConfig:
141     type: ../puppet/deploy-artifacts.yaml
142
143   {{role.name}}ArtifactsDeploy:
144     type: OS::Heat::StructuredDeploymentGroup
145     properties:
146       servers:  {get_param: [servers, {{role.name}}]}
147       config: {get_resource: {{role.name}}ArtifactsConfig}
148
149   {{role.name}}HostPrepConfig:
150     type: OS::Heat::SoftwareConfig
151     properties:
152       group: ansible
153       options:
154         modulepath: /usr/share/ansible-modules
155       config:
156         str_replace:
157           template: _PLAYBOOK
158           params:
159             _PLAYBOOK:
160               - hosts: localhost
161                 connection: local
162                 vars:
163                   puppet_config: {get_param: [role_data, {{role.name}}, puppet_config]}
164                   docker_puppet_script: {get_file: docker-puppet.py}
165                   docker_puppet_tasks: {get_attr: [{{primary_role_name}}DockerPuppetTasks, value]}
166                   docker_startup_configs: {get_attr: [{{role.name}}DockerConfig, value]}
167                   kolla_config: {get_param: [role_data, {{role.name}}, kolla_config]}
168                   bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
169                   puppet_step_config: {get_attr: [{{role.name}}PuppetStepConfig, value]}
170                 tasks:
171                   # Join host_prep_tasks with the other per-host configuration
172                   yaql:
173                     expression: $.data.host_prep_tasks + $.data.template_tasks
174                     data:
175                       host_prep_tasks: {get_param: [role_data, {{role.name}}, host_prep_tasks]}
176                       template_tasks:
177 {%- raw %}
178                         # Write the manifest for baremetal puppet configuration
179                         - name: Create /var/lib/tripleo-config directory
180                           file: path=/var/lib/tripleo-config state=directory
181                         - name: Write the puppet step_config manifest
182                           copy: content="{{puppet_step_config}}" dest=/var/lib/tripleo-config/puppet_step_config.pp force=yes
183                         # This is the docker-puppet configs end in
184                         - name: Create /var/lib/docker-puppet
185                           file: path=/var/lib/docker-puppet state=directory
186                         # this creates a JSON config file for our docker-puppet.py script
187                         - name: Write docker-puppet-tasks json files
188                           copy: content="{{puppet_config | to_json}}" dest=/var/lib/docker-puppet/docker-puppet.json force=yes
189                         # FIXME: can we move docker-puppet somewhere so it's installed via a package?
190                         - name: Write docker-puppet.py
191                           copy: content="{{docker_puppet_script}}" dest=/var/lib/docker-puppet/docker-puppet.py force=yes
192                         # Here we are dumping all the docker container startup configuration data
193                         # so that we can have access to how they are started outside of heat
194                         # and docker-cmd.  This lets us create command line tools to test containers.
195                         # FIXME do we need the docker-container-startup-configs.json or is the new per-step
196                         # data consumed by paunch enough?
197                         - name: Write docker-container-startup-configs
198                           copy: content="{{docker_startup_configs | to_json}}" dest=/var/lib/docker-container-startup-configs.json force=yes
199                         - name: Write per-step docker-container-startup-configs
200                           copy: content="{{item.value|to_json}}" dest="/var/lib/tripleo-config/docker-container-startup-config-{{item.key}}.json" force=yes
201                           with_dict: "{{docker_startup_configs}}"
202                         - name: Create /var/lib/kolla/config_files directory
203                           file: path=/var/lib/kolla/config_files state=directory
204                         - name: Write kolla config json files
205                           copy: content="{{item.value|to_json}}" dest="{{item.key}}" force=yes
206                           with_dict: "{{kolla_config}}"
207                         ########################################################
208                         # Bootstrap tasks, only performed on bootstrap_server_id
209                         ########################################################
210                         - name: Write docker-puppet-tasks json files
211                           copy: content="{{item.value|to_json}}" dest=/var/lib/docker-puppet/docker-puppet-tasks{{item.key.replace("step_", "")}}.json force=yes
212                           with_dict: "{{docker_puppet_tasks}}"
213                           when: deploy_server_id == bootstrap_server_id
214 {%- endraw %}
215
216   {{role.name}}HostPrepDeployment:
217     type: OS::Heat::SoftwareDeploymentGroup
218     properties:
219       servers: {get_param: [servers, {{role.name}}]}
220       config: {get_resource: {{role.name}}HostPrepConfig}
221
222   {{role.name}}PuppetStepConfig:
223     type: OS::Heat::Value
224     properties:
225       type: string
226       value:
227         yaql:
228           expression:
229             # select 'step_config' only from services that do not have a docker_config
230             $.data.service_names.zip($.data.step_config, $.data.docker_config).where($[2] = null).where($[1] != null).select($[1]).join("\n")
231           data:
232             service_names: {get_param: [role_data, {{role.name}}, service_names]}
233             step_config: {get_param: [role_data, {{role.name}}, step_config]}
234             docker_config: {get_param: [role_data, {{role.name}}, docker_config]}
235
236   {{role.name}}DockerConfig:
237     type: OS::Heat::Value
238     properties:
239       type: json
240       value:
241         yaql:
242           expression:
243             # select 'docker_config' only from services that have it
244             $.data.service_names.zip($.data.docker_config).where($[1] != null).select($[1]).reduce($1.mergeWith($2), {})
245           data:
246             service_names: {get_param: [role_data, {{role.name}}, service_names]}
247             docker_config: {get_param: [role_data, {{role.name}}, docker_config]}
248
249   # BEGIN CONFIG STEPS
250
251   {{role.name}}PreConfig:
252     type: OS::TripleO::Tasks::{{role.name}}PreConfig
253     depends_on: {{role.name}}HostPrepDeployment
254     properties:
255       servers: {get_param: [servers, {{role.name}}]}
256       input_values:
257         update_identifier: {get_param: DeployIdentifier}
258
259   {% for step in range(1, deploy_steps_max) %}
260
261   {{role.name}}Deployment_Step{{step}}:
262     type: OS::Heat::StructuredDeploymentGroup
263     depends_on:
264       - WorkflowTasks_Step{{step}}_Execution
265     # TODO(gfidente): the following if/else condition
266     # replicates what is already defined for the
267     # WorkflowTasks_StepX resource and can be remove
268     # if https://bugs.launchpad.net/heat/+bug/1700569
269     # is fixed.
270     {% if step == 1 %}
271     {% for dep in roles %}
272       - {{dep.name}}PreConfig
273       - {{dep.name}}ArtifactsDeploy
274     {% endfor %}
275     {% else %}
276     {% for dep in roles %}
277       - {{dep.name}}Deployment_Step{{step -1}}
278     {% endfor %}
279     {% endif %}
280     properties:
281       name: {{role.name}}Deployment_Step{{step}}
282       servers: {get_param: [servers, {{role.name}}]}
283       config: {get_resource: RoleConfig}
284       input_values:
285         step: {{step}}
286         role_name: {{role.name}}
287         update_identifier: {get_param: DeployIdentifier}
288         bootstrap_server_id: {get_param: [servers, {{primary_role_name}}, '0']}
289
290   {% endfor %}
291   # END CONFIG STEPS
292
293   # Note, this should be the last step to execute configuration changes.
294   # Ensure that all {{role.name}}ExtraConfigPost steps are executed
295   # after all the previous deployment steps.
296   {{role.name}}ExtraConfigPost:
297     depends_on:
298   {% for dep in roles %}
299       - {{dep.name}}Deployment_Step5
300   {% endfor %}
301     type: OS::TripleO::NodeExtraConfigPost
302     properties:
303         servers: {get_param: [servers, {{role.name}}]}
304
305   # The {{role.name}}PostConfig steps are in charge of
306   # quiescing all services, i.e. in the Controller case,
307   # we should run a full service reload.
308   {{role.name}}PostConfig:
309     type: OS::TripleO::Tasks::{{role.name}}PostConfig
310     depends_on:
311   {% for dep in roles %}
312       - {{dep.name}}ExtraConfigPost
313   {% endfor %}
314     properties:
315       servers:  {get_param: servers}
316       input_values:
317         update_identifier: {get_param: DeployIdentifier}
318
319
320 {% endfor %}