123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- DOCUMENTATION = '''
- ---
- module: oc_atomic_container
- short_description: Manage the container images on the atomic host platform
- description:
- - Manage the container images on the atomic host platform
- - Allows to execute the commands on the container images
- requirements:
- - atomic
- - "python >= 2.6"
- options:
- name:
- description:
- - Name of the container
- required: True
- default: null
- image:
- description:
- - The image to use to install the container
- required: True
- default: null
- state:
- description:
- - State of the container
- required: True
- choices: ["latest", "absent", "latest", "rollback"]
- default: "latest"
- values:
- description:
- - Values for the installation of the container
- required: False
- default: None
- '''
- import json
- import os
- from distutils.version import StrictVersion
- from ansible.module_utils.basic import AnsibleModule
- def _install(module, container, image, values_list):
- ''' install a container using atomic CLI. values_list is the list of --set arguments.
- container is the name given to the container. image is the image to use for the installation. '''
-
- args = ['atomic', 'install', '--system', '--system-package=no',
- '--name=%s' % container] + values_list + [image]
- rc, out, err = module.run_command(args, check_rc=False)
- if rc != 0:
- return rc, out, err, False
- else:
- changed = "Extracting" in out or "Copying blob" in out
- return rc, out, err, changed
- def _uninstall(module, name):
- ''' uninstall an atomic container by its name. '''
- args = ['atomic', 'uninstall', name]
- rc, out, err = module.run_command(args, check_rc=False)
- return rc, out, err, False
- def _ensure_service_file_is_removed(container):
- '''atomic install won't overwrite existing service file, so it needs to be removed'''
- service_path = '/etc/systemd/system/{}.service'.format(container)
- if not os.path.exists(service_path):
- return
- os.remove(service_path)
- def do_install(module, container, image, values_list):
- ''' install a container and exit the module. '''
- _ensure_service_file_is_removed(container)
- rc, out, err, changed = _install(module, container, image, values_list)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- else:
- module.exit_json(msg=out, changed=changed)
- def do_uninstall(module, name):
- ''' uninstall a container and exit the module. '''
- rc, out, err, changed = _uninstall(module, name)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- module.exit_json(msg=out, changed=changed)
- def do_update(module, container, old_image, image, values_list):
- ''' update a container and exit the module. If the container uses a different
- image than the current installed one, then first uninstall the old one '''
-
- if old_image != image:
- rc, out, err, _ = _uninstall(module, container)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- return do_install(module, container, image, values_list)
-
- args = ['atomic', 'containers', 'update'] + values_list + [container]
- rc, out, err = module.run_command(args, check_rc=False)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- else:
- changed = "Extracting" in out or "Copying blob" in out
- module.exit_json(msg=out, changed=changed)
- def do_rollback(module, name):
- ''' move to the previous deployment of the container, if present, and exit the module. '''
- args = ['atomic', 'containers', 'rollback', name]
- rc, out, err = module.run_command(args, check_rc=False)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- else:
- changed = "Rolling back" in out
- module.exit_json(msg=out, changed=changed)
- def core(module):
- ''' entrypoint for the module. '''
- name = module.params['name']
- image = module.params['image']
- values = module.params['values']
- state = module.params['state']
- module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C')
- out = {}
- err = {}
- rc = 0
- values_list = ["--set=%s" % x for x in values] if values else []
- args = ['atomic', 'containers', 'list', '--json', '--all', '-f', 'container=%s' % name]
- rc, out, err = module.run_command(args, check_rc=False)
- if rc != 0:
- module.fail_json(rc=rc, msg=err)
- return
-
-
- containers = json.loads(out or '[]')
- present = len(containers) > 0
- old_image = containers[0]["image_name"] if present else None
- if state == 'present' and present:
- module.exit_json(msg=out, changed=False)
- elif (state in ['latest', 'present']) and not present:
- do_install(module, name, image, values_list)
- elif state == 'latest':
- do_update(module, name, old_image, image, values_list)
- elif state == 'absent':
- if not present:
- module.exit_json(msg="", changed=False)
- else:
- do_uninstall(module, name)
- elif state == 'rollback':
- do_rollback(module, name)
- def main():
- module = AnsibleModule(
- argument_spec=dict(
- name=dict(default=None, required=True),
- image=dict(default=None, required=True),
- state=dict(default='latest', choices=['present', 'absent', 'latest', 'rollback']),
- values=dict(type='list', default=[]),
- ),
- )
-
- rc, version_out, err = module.run_command('rpm -q --queryformat "%{VERSION}\n" atomic', check_rc=False)
- if rc != 0:
- module.fail_json(msg="Error in running atomic command", err=err)
-
- atomic_version = StrictVersion(version_out.replace('\n', ''))
- if atomic_version < StrictVersion('1.17.2'):
- module.fail_json(
- msg="atomic version 1.17.2+ is required",
- err=str(atomic_version))
- try:
- core(module)
- except Exception as e:
- module.fail_json(msg=str(e))
- if __name__ == '__main__':
- main()
|