<filename>tripleo_ansible/ansible_plugins/modules/paunch.py
# Copyright 2019 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
__metaclass__ = type

from ansible.module_utils.basic import AnsibleModule

import json
import os
import paunch as p
import re
import yaml
from paunch import runner as prunner
from paunch.builder import compose1 as pcompose1
from paunch.builder import podman as ppodman
from paunch.utils import common as putils_common


ANSIBLE_METADATA = {
    'metadata_version': '1.0',
    'status': ['preview'],
    'supported_by': 'community'
}

DOCUMENTATION = """
---
module: paunch
author:
    - OpenStack TripleO Contributors
version_added: '1.0'
short_description: Manage containers with Paunch
notes: []
requirements:
  - "paunch module"
  - "podman or docker"
description:
    - Start or stop containers with Paunch
options:
  config:
    description:
      - JSON file or directory of JSON files containing configuration data
  config_id:
    description:
      - ID to assign to containers
    required: True
    type: list
  action:
    description:
      - The desired action to apply for the container.
    default: apply
    choices:
      - apply
      - cleanup
  config_overrides:
    description:
      - Dictionary to override containers configs
    default: {}
    type: dict
  container_cli:
    description:
      - The container CLI.
    default: podman
    choices:
      - podman
      - docker
  container_log_stdout_path:
    description:
      - Absolute path to a directory where container stdout will be stored.
    default: /var/log/containers/stdouts
  healthcheck_disabled:
    description:
      - Whether or not we disable the Containers Healthchecks
    type: bool
    default: False
  managed_by:
    description:
      - Name of the tool managing the containers. Only containers labelled with
        this will be modified
    default: paunch
  debug:
    description:
      - Whether or not we enable Debug
    type: bool
    default: True
  log_file:
    description:
      - Absolute path for the paunch log file.
    default: /var/log/paunch.log
"""

EXAMPLES = """
# Paunch apply example
- name: Start containers for step 1
  paunch:
    config: /var/lib/tripleo-config/hashed-container-startup-config-step_1.json
    config_overrides:
      haproxy:
        image: docker.io/tripleomaster/centos-binary-haproxy:current-tripleo-hotfix
    config_id: tripleo_step1
    action: apply
# Paunch cleanup example
- name: Cleanup containers for step 1 and step 2
  paunch:
    config_id:
      - tripleo_step1
      - tripleo_step2
    action: cleanup
"""


class PaunchManager:

    def __init__(self, module, results):

        super(PaunchManager, self).__init__()

        self.module = module
        self.results = results
        self.config = self.module.params['config']
        if (isinstance(self.module.params['config_id'], list)
           and len(self.module.params['config_id']) == 1):
            self.config_id = self.module.params['config_id'][0]
        else:
            self.config_id = self.module.params['config_id']
        self.action = self.module.params['action']
        self.healthcheck_disabled = \
            self.module.params['healthcheck_disabled']
        self.container_cli = self.module.params['container_cli']
        self.config_overrides = self.module.params['config_overrides']
        self.container_log_stdout_path = \
            self.module.params['container_log_stdout_path']
        self.managed_by = self.module.params['managed_by']
        self.debug = self.module.params['debug']
        self.log_file = self.module.params['log_file']

        if self.debug:
            self.log_level = 3
        else:
            # if debug is disabled, only show WARNING level
            self.log_level = 1

        self.log = putils_common.configure_logging('paunch-ansible',
                                                   level=self.log_level,
                                                   log_file=self.log_file)

        if self.config:
            self.config_yaml = putils_common.load_config(
                self.config,
                overrides=self.config_overrides)

        if self.action == 'apply':
            self.paunch_apply()
        elif self.action == 'cleanup':
            self.paunch_cleanup()

    def paunch_apply(self):

        self.results['action'].append('Applying config_id %s' % self.config_id)
        if not self.config:
            self.module.fail_json(
                msg="Paunch apply requires 'config' parameter",
                stdout='',
                stderr='',
                rc=1)

        stdout_list, stderr_list, rc = p.apply(
            self.config_id,
            self.config_yaml,
            managed_by=self.managed_by,
            labels=[],
            cont_cmd=self.container_cli,
            log_level=self.log_level,
            log_file=self.log_file,
            cont_log_path=self.container_log_stdout_path,
            healthcheck_disabled=self.healthcheck_disabled
        )
        stdout, stderr = ["\n".join(i) for i in (stdout_list, stderr_list)]

        # Test paunch idempotency how we can.
        changed_strings = ['rm -f', 'Completed', 'Created']
        if any(s in stdout for s in changed_strings):
            self.results['changed'] = True

        self.results.update({"stdout": stdout, "stderr": stderr, "rc": rc})
        if rc != 0:
            self.module.fail_json(
                msg="Paunch failed with config_id %s" % self.config_id,
                stdout=stdout,
                stderr=stderr,
                rc=rc)

        self.module.exit_json(**self.results)

    def paunch_cleanup(self):

        self.results['action'].append('Cleaning-up config_id(s) '
                                      '%s' % self.config_id)
        p.cleanup(
            self.config_id,
            managed_by=self.managed_by,
            cont_cmd=self.container_cli,
            log_level=self.log_level,
            log_file=self.log_file
        )

        self.module.exit_json(**self.results)


def main():
    module = AnsibleModule(
        argument_spec=yaml.safe_load(DOCUMENTATION)['options'],
        supports_check_mode=False,
    )

    results = dict(
        changed=False,
        action=[]
    )

    PaunchManager(module, results)


if __name__ == '__main__':
    main()

<filename>tripleo_ansible/ansible_plugins/modules/paunch.py
# Copyright 2019 Red Hat, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
__metaclass__ = type

from ansible.module_utils.basic import AnsibleModule

import json
import os
import paunch as p
import re
import yaml
from paunch import runner as prunner
from paunch.builder import compose1 as pcompose1
from paunch.builder import podman as ppodman
from paunch.utils import common as putils_common


ANSIBLE_METADATA = {
    'metadata_version': '1.0',
    'status': ['preview'],
    'supported_by': 'community'
}

DOCUMENTATION = """
---
module: paunch
author:
    - OpenStack TripleO Contributors
version_added: '1.0'
short_description: Manage containers with Paunch
notes: []
requirements:
  - "paunch module"
  - "podman or docker"
description:
    - Start or stop containers with Paunch
options:
  config:
    description:
      - JSON file or directory of JSON files containing configuration data
  config_id:
    description:
      - ID to assign to containers
    required: True
    type: list
  action:
    description:
      - The desired action to apply for the container.
    default: apply
    choices:
      - apply
      - cleanup
  config_overrides:
    description:
      - Dictionary to override containers configs
    default: {}
    type: dict
  container_cli:
    description:
      - The container CLI.
    default: podman
    choices:
      - podman
      - docker
  container_log_stdout_path:
    description:
      - Absolute path to a directory where container stdout will be stored.
    default: /var/log/containers/stdouts
  healthcheck_disabled:
    description:
      - Whether or not we disable the Containers Healthchecks
    type: bool
    default: False
  managed_by:
    description:
      - Name of the tool managing the containers. Only containers labelled with
        this will be modified
    default: paunch
  debug:
    description:
      - Whether or not we enable Debug
    type: bool
    default: True
  log_file:
    description:
      - Absolute path for the paunch log file.
    default: /var/log/paunch.log
"""

EXAMPLES = """
# Paunch apply example
- name: Start containers for step 1
  paunch:
    config: /var/lib/tripleo-config/hashed-container-startup-config-step_1.json
    config_overrides:
      haproxy:
        image: docker.io/tripleomaster/centos-binary-haproxy:current-tripleo-hotfix
    config_id: tripleo_step1
    action: apply
# Paunch cleanup example
- name: Cleanup containers for step 1 and step 2
  paunch:
    config_id:
      - tripleo_step1
      - tripleo_step2
    action: cleanup
"""


class PaunchManager:

    def __init__(self, module, results):

        super(PaunchManager, self).__init__()

        self.module = module
        self.results = results
        self.config = self.module.params['config']
        if (isinstance(self.module.params['config_id'], list)
           and len(self.module.params['config_id']) == 1):
            self.config_id = self.module.params['config_id'][0]
        else:
            self.config_id = self.module.params['config_id']
        self.action = self.module.params['action']
        self.healthcheck_disabled = \
            self.module.params['healthcheck_disabled']
        self.container_cli = self.module.params['container_cli']
        self.config_overrides = self.module.params['config_overrides']
        self.container_log_stdout_path = \
            self.module.params['container_log_stdout_path']
        self.managed_by = self.module.params['managed_by']
        self.debug = self.module.params['debug']
        self.log_file = self.module.params['log_file']

        if self.debug:
            self.log_level = 3
        else:
            # if debug is disabled, only show WARNING level
            self.log_level = 1

        self.log = putils_common.configure_logging('paunch-ansible',
                                                   level=self.log_level,
                                                   log_file=self.log_file)

        if self.config:
            self.config_yaml = putils_common.load_config(
                self.config,
                overrides=self.config_overrides)

        if self.action == 'apply':
            self.paunch_apply()
        elif self.action == 'cleanup':
            self.paunch_cleanup()

    def paunch_apply(self):

        self.results['action'].append('Applying config_id %s' % self.config_id)
        if not self.config:
            self.module.fail_json(
                msg="Paunch apply requires 'config' parameter",
                stdout='',
                stderr='',
                rc=1)

        stdout_list, stderr_list, rc = p.apply(
            self.config_id,
            self.config_yaml,
            managed_by=self.managed_by,
            labels=[],
            cont_cmd=self.container_cli,
            log_level=self.log_level,
            log_file=self.log_file,
            cont_log_path=self.container_log_stdout_path,
            healthcheck_disabled=self.healthcheck_disabled
        )
        stdout, stderr = ["\n".join(i) for i in (stdout_list, stderr_list)]

        # Test paunch idempotency how we can.
        changed_strings = ['rm -f', 'Completed', 'Created']
        if any(s in stdout for s in changed_strings):
            self.results['changed'] = True

        self.results.update({"stdout": stdout, "stderr": stderr, "rc": rc})
        if rc != 0:
            self.module.fail_json(
                msg="Paunch failed with config_id %s" % self.config_id,
                stdout=stdout,
                stderr=stderr,
                rc=rc)

        self.module.exit_json(**self.results)

    def paunch_cleanup(self):

        self.results['action'].append('Cleaning-up config_id(s) '
                                      '%s' % self.config_id)
        p.cleanup(
            self.config_id,
            managed_by=self.managed_by,
            cont_cmd=self.container_cli,
            log_level=self.log_level,
            log_file=self.log_file
        )

        self.module.exit_json(**self.results)


def main():
    module = AnsibleModule(
        argument_spec=yaml.safe_load(DOCUMENTATION)['options'],
        supports_check_mode=False,
    )

    results = dict(
        changed=False,
        action=[]
    )

    PaunchManager(module, results)


if __name__ == '__main__':
    main()

# Copyright 2019 Red Hat, Inc. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # #     http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. --- module: paunch author:     - OpenStack TripleO Contributors version_added: '1.0' short_description: Manage containers with Paunch notes: [] requirements:   - "paunch module"   - "podman or docker" description:     - Start or stop containers with Paunch options:   config:     description:       - JSON file or directory of JSON files containing configuration data   config_id:     description:       - ID to assign to containers     required: True     type: list   action:     description:       - The desired action to apply for the container.     default: apply     choices:       - apply       - cleanup   config_overrides:     description:       - Dictionary to override containers configs     default: {}     type: dict   container_cli:     description:       - The container CLI.     default: podman     choices:       - podman       - docker   container_log_stdout_path:     description:       - Absolute path to a directory where container stdout will be stored.     default: /var/log/containers/stdouts   healthcheck_disabled:     description:       - Whether or not we disable the Containers Healthchecks     type: bool     default: False   managed_by:     description:       - Name of the tool managing the containers. Only containers labelled with         this will be modified     default: paunch   debug:     description:       - Whether or not we enable Debug     type: bool     default: True   log_file:     description:       - Absolute path for the paunch log file.     default: /var/log/paunch.log # Paunch apply example - name: Start containers for step 1   paunch:     config: /var/lib/tripleo-config/hashed-container-startup-config-step_1.json     config_overrides:       haproxy:         image: docker.io/tripleomaster/centos-binary-haproxy:current-tripleo-hotfix     config_id: tripleo_step1     action: apply # Paunch cleanup example - name: Cleanup containers for step 1 and step 2   paunch:     config_id:       - tripleo_step1       - tripleo_step2     action: cleanup # if debug is disabled, only show WARNING level # Test paunch idempotency how we can.