    # Note the indentation here is required as it's joined
    # to create a playbook in deploy-steps.j2
    ##################################################
    # Step 1 block, write data for subsequent steps
    ##################################################
    - name: gather facts needed by role
      setup:
        gather_subset: "!min,python"
      when: ansible_python is not defined
      tags:
        - container_config_tasks

    - name: set python_cmd
      set_fact:
        python_cmd: "python{{ ansible_python.version.major }}"
        cacheable: true
      when: python_cmd is not defined
      tags:
        - container_config_tasks

    #####################################################
    # Per step puppet configuration of the baremetal host
    #####################################################

    - name: Set host puppet debugging fact string
      set_fact:
        host_puppet_config_debug: "--debug --verbose"
      when:
        - enable_puppet | bool
        - enable_debug | bool
      tags:
        - host_config

    - name: Check for /etc/puppet/check-mode directory for check mode
      stat:
        path: /etc/puppet/check-mode
      register: check_mode_dir
      when: ansible_check_mode|bool
      tags:
        - host_config
        - container_config

    - name: Create /etc/puppet/check-mode/hieradata directory for check mode
      file:
        path: /etc/puppet/check-mode/hieradata
        state: directory
        setype: svirt_sandbox_file_t
        selevel: s0
        recurse: true
      check_mode: no
      when:
        - ansible_check_mode|bool
        - not check_mode_dir.stat.exists
      tags:
        - host_config
        - container_config

    - name: Write the config_step hieradata
      no_log: True
      copy:
        content: "{{ dict(step=step|int) | to_json }}"
        dest: /etc/puppet/{{ ansible_check_mode | bool | ternary('check-mode/', '') }}hieradata/config_step.json
        force: true
        mode: '0600'
      check_mode: no
      tags:
        - host_config

    - name: Create puppet check-mode files if they don't exist for check mode
      shell: |
        cp -a /etc/puppet/hiera.yaml /etc/puppet/check-mode/hiera.yaml
        cp -a /etc/puppet/hieradata/* /etc/puppet/check-mode/hieradata/
        sed -i 's/\/etc\/puppet\/hieradata/\/etc\/puppet\/check-mode\/hieradata/' /etc/puppet/check-mode/hiera.yaml
      when:
        - ansible_check_mode|bool
        - not check_mode_dir.stat.exists
      check_mode: no
      tags:
        - host_config
        - container_config

    - name: Run puppet host configuration for step {{ step }}
      when: enable_puppet|bool
      shell: >-
        set -o pipefail;
        puppet apply {{ host_puppet_config_debug | default('') }}
        --modulepath=/etc/puppet/modules:/opt/stack/puppet-modules:/usr/share/openstack-puppet/modules
        --detailed-exitcodes
        --summarize
        --color=false
        {{ ansible_check_mode | bool | ternary('--noop', '') }}
        {{ ansible_check_mode | bool | ternary('--hiera_config /etc/puppet/check-mode/hiera.yaml', '') }}
        /var/lib/tripleo-config/{{ ansible_check_mode | bool | ternary('check-mode/', '') }}puppet_step_config.pp
        2>&1 | logger -s -t puppet-user
      changed_when: outputs.rc == 2
      register: outputs
      failed_when: false
      no_log: true
      tags:
        - host_config
      check_mode: no

    - name: "Debug output for task: Run puppet host configuration for step {{ step }}"
      debug:
        var: outputs.stdout_lines | default([]) | union(outputs.stderr_lines | default([]))
      when:
        - enable_puppet | bool
        - outputs.rc is defined
      failed_when: outputs.rc not in [0, 2]
      tags:
        - host_config
      ignore_errors: "{{ ansible_check_mode|bool }}"

    #########################################
    # Pre-cache facts for container-puppet.py
    #########################################
    # We don't want the pre-cache tasks to be skipped in dry-run so we force
    # check_mode to "no".
    # https://bugzilla.redhat.com/show_bug.cgi?id=1738529
    - name: Pre-cache facts for container-puppet.py
      include_role:
        name: tripleo-puppet-cache
      tags:
        - container_config
        - container_config_tasks

    ######################################
    # Generate config via container-puppet.py
    ######################################

    - name: Run container-puppet tasks (generate config) during step {{ step }}
      shell: "{{ python_cmd }} /var/lib/container-puppet/container-puppet.py"
      environment:
        NET_HOST: 'true'
        DEBUG: '{{ docker_puppet_debug | bool }}'
        PROCESS_COUNT: "{{ docker_puppet_process_count }}"
        CONTAINER_CLI: "{{ container_cli }}"
        CONFIG: '/var/lib/container-puppet/{{ ansible_check_mode | bool | ternary("check-mode/", "") }}container-puppet.json'
        CONFIG_VOLUME_PREFIX: '/var/lib/config-data{{ ansible_check_mode | bool | ternary("/check-mode", "") }}'
        CHECK_MODE: '{{ ansible_check_mode | bool | ternary(1, 0) }}'
        STARTUP_CONFIG_PATTERN: '/var/lib/tripleo-config/container-startup-config/*/{{ ansible_check_mode | bool | ternary("check-mode/", "") }}*.json'
        MOUNT_HOST_PUPPET: '{{docker_puppet_mount_host_puppet | default(true)}}'
        CONTAINER_LOG_STDOUT_PATH: "{{ container_log_stdout_path }}"
        CONTAINER_HEALTHCHECK_DISABLED: "{{ container_healthcheck_disabled }}"
        SHORT_HOSTNAME: "{{ ansible_hostname }}"
      when: step|int == 1
      changed_when: false
      check_mode: no
      register: outputs
      failed_when: false
      no_log: true
      tags:
        - container_config

    - name: "Debug output for task: Run container-puppet tasks (generate config) during step {{ step }}"
      debug:
        var: outputs.stdout_lines | default([]) | union(outputs.stderr_lines | default([]))
      when: outputs.rc is defined
      failed_when: outputs.rc != 0
      tags:
        - container_config
      ignore_errors: "{{ ansible_check_mode|bool }}"

    - name: Diff container-puppet.py puppet-generated changes for check mode
      shell: |
        diff -ruN --no-dereference -q /var/lib/config-data/puppet-generated /var/lib/config-data/check-mode/puppet-generated
        diff -ruN --no-dereference /var/lib/config-data/puppet-generated /var/lib/config-data/check-mode/puppet-generated
      register: diff_results
      tags:
        - container_config
      check_mode: no
      when:
        - step|int == 1
        - ansible_check_mode|bool
        - ansible_diff_mode
      failed_when: false
      changed_when: diff_results.rc == 1

    - name: Diff container-puppet.py puppet-generated changes for check mode
      debug:
        var: diff_results.stdout_lines
      changed_when: diff_results.rc == 1
      when:
        - step|int == 1
        - ansible_check_mode|bool
        - ansible_diff_mode
      tags:
        - container_config

    #####################################
    # Per step starting of the containers
    #####################################

    # Note container-puppet.py generates the hashed-*.json file, which is a copy of
    # the *step_n.json with a hash of the generated external config added
    # This acts as a salt to enable restarting the container if config changes
    - name: Per step starting of the containers using Paunch
      when: enable_paunch|default(true)
      block:
        - name: Start containers for step {{ step }} using paunch
          environment:
            TRIPLEO_MINOR_UPDATE: '{{ tripleo_minor_update | default(false) }}'
          paunch:
            config: "/var/lib/tripleo-config/container-startup-config/step_{{ step }}"
            config_id: "tripleo_step{{ step }}"
            action: apply
            container_cli: "{{ container_cli }}"
            container_log_stdout_path: "{{ container_log_stdout_path }}"
            healthcheck_disabled: "{{ container_healthcheck_disabled | bool }}"
            managed_by: "tripleo-{{ tripleo_role_name }}"
            debug: "{{ enable_debug | bool }}"
          register: outputs
          failed_when: false
          tags:
            - container_startup_configs

        - name: "Debug output for task: Start containers for step {{ step }}"
          debug:
            var: outputs.stdout_lines | default([]) | union(outputs.stderr_lines | default([]))
          when: outputs.rc is defined
          failed_when: outputs.rc != 0
          tags:
            - container_startup_configs

    # This is experimental, do not use for production now
    - name: Per step starting of the containers using tripleo-ansible
      when: not enable_paunch|default(true)
      environment:
        TRIPLEO_MINOR_UPDATE: '{{ tripleo_minor_update | default(false) }}'
      block:
        - name: "Manage containers for step {{ step }} with tripleo-ansible"
          include_role:
            name: tripleo-container-manage
          vars:
            tripleo_container_manage_systemd_order: true
            tripleo_container_manage_cli: "{{ container_cli }}"
            tripleo_container_manage_config: "/var/lib/tripleo-config/container-startup-config/step_{{ step }}"
            tripleo_container_manage_config_id: "tripleo_step{{ step }}"
            tripleo_container_manage_debug: "{{ enable_debug | bool }}"
            tripleo_container_manage_healthcheck_disabled: "{{ container_healthcheck_disabled | bool }}"
            tripleo_container_manage_log_path: "{{ container_log_stdout_path }}"
          tags:
            - container_startup_configs

    ########################################################
    # Bootstrap tasks - run any tasks that have been defined
    ########################################################

    - name: "Clean container_puppet_tasks for {{ansible_hostname}} step {{step}}"
      file:
        path: /var/lib/container-puppet/container-puppet-tasks{{step}}.json
        state: absent
      tags:
        - container_config_tasks

    - name: Calculate container_puppet_tasks for {{ansible_hostname}} step {{step}}
      set_fact:
        host_container_puppet_tasks: "{{host_container_puppet_tasks|default([]) + [item]}}"
      loop: "{{container_puppet_tasks.get('step_' + step, [])}}"
      when: (groups[item.service_name] | default ([]) | map('extract', hostvars, 'inventory_hostname') | sort | first) == ansible_hostname
      vars:
        container_puppet_tasks: "{{ lookup('file', tripleo_role_name + '/container_puppet_tasks.yaml', errors='ignore') | default({}, True) | from_yaml }}"
      tags:
        - container_config_tasks

    - name: Write container-puppet-tasks json file for {{ansible_hostname}} step {{step}}
      no_log: True
      copy:
        content: "{{host_container_puppet_tasks|to_nice_json}}"
        dest: "/var/lib/container-puppet/container-puppet-tasks{{step}}.json"
        force: yes
        mode: '0600'
      tags:
        - container_config_tasks
      when: host_container_puppet_tasks is defined

    - name: Run container-puppet tasks (bootstrap tasks) for step {{ step }}
      shell: "{{ python_cmd }} /var/lib/container-puppet/container-puppet.py"
      environment:
        CONFIG: /var/lib/container-puppet/{{ ansible_check_mode | bool | ternary('check-mode/', '') }}container-puppet-tasks{{ step }}.json
        CONFIG_VOLUME_PREFIX: '/var/lib/config-data{{ ansible_check_mode | bool | ternary("/check-mode", "") }}'
        NET_HOST: "true"
        NO_ARCHIVE: "true"
        STEP: "{{ step }}"
        CONTAINER_CLI: "{{ container_cli }}"
        DEBUG: "{{ docker_puppet_debug }}"
        MOUNT_HOST_PUPPET: '{{docker_puppet_mount_host_puppet}}'
        SHORT_HOSTNAME: "{{ ansible_hostname }}"
        PROCESS_COUNT: "{{ docker_puppet_process_count }}"
      when: host_container_puppet_tasks is defined
      changed_when: false
      register: outputs
      failed_when: false
      no_log: true
      tags:
        - container_config_tasks

    - name: "Debug output for task: Run container-puppet tasks (bootstrap tasks) for step {{ step }}"
      debug:
        var: outputs.stdout_lines | default([]) | union(outputs.stderr_lines | default([]))
      when: outputs.rc is defined
      failed_when: outputs.rc != 0
      tags:
        - container_config_tasks
