bstinson / centos / releng

Forked from centos/releng 3 years ago
Clone
Blob Blame History Raw
#!/usr/bin/python
import sys
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils import common_koji


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


DOCUMENTATION = '''
---
module: koji_cg

short_description: Create and manage Koji content generators
description:
   - This module can grant or revoke access to a `content generator
     <https://docs.pagure.org/koji/content_generators/>`_ for a user account.
   - Your Koji Hub must be version 1.19 or newer in order to use the new
     `listCGs <https://pagure.io/koji/pull-request/1160>`_ RPC.


options:
   name:
     description:
       - The name of the Koji content generator.
       - 'Example: "debian".'
     required: true
   user:
     description:
       - The name of the Koji user account.
       - This user account must already exist in Koji's database. For example,
         you may run an authenticated "koji hello" command to create the
         account database entry.
       - 'Example: "cguser".'
     required: true
requirements:
  - "python >= 2.7"
  - "koji"
'''

EXAMPLES = '''
- name: Grant a user access to a content generator.
  hosts: localhost
  tasks:
    - name: Grant access to the rcm/debbuild account
      koji_cg:
        name: debian
        user: rcm/debbuild
        state: present
'''

RETURN = ''' # '''


class UnknownCGsError(Exception):
    """ We cannot know what CGs are present """
    pass


def list_cgs(session):
    """ Return the result of listCGs, or raise UnknownCGsError """
    koji_profile = sys.modules[session.__module__]
    try:
        return session.listCGs()
    except koji_profile.GenericError as e:
        if str(e) == 'Invalid method: listCGs':
            # Kojihub before version 1.20 will raise this error.
            raise UnknownCGsError
        raise


def ensure_cg(session, user, name, state, cgs, check_mode):
    """
    Ensure that a content generator and user is present or absent.

    :param session: koji ClientSession
    :param str user: koji user name
    :param str name: content generator name
    :param str state: "present" or "absent"
    :param dict cgs: existing content generators and users
    :param bool check_mode: if True, show what would happen, but don't do it.
    :returns: result
    """
    result = {'changed': False}
    if state == 'present':
        if name not in cgs or user not in cgs[name]['users']:
            if not check_mode:
                common_koji.ensure_logged_in(session)
                session.grantCGAccess(user, name, create=True)
            result['changed'] = True
    elif state == 'absent':
        if name in cgs and user in cgs[name]['users']:
            if not check_mode:
                common_koji.ensure_logged_in(session)
                session.revokeCGAccess(user, name)
            result['changed'] = True
    return result


def ensure_unknown_cg(session, user, name, state):
    """
    Ensure that a content generator and user is present or absent.

    This method is for older versions of Koji where we do not have the listCGs
    RPC. This method does not support check_mode.

    :param session: koji ClientSession
    :param str user: koji user name
    :param str name: content generator name
    :param str state: "present" or "absent"
    :returns: result
    """
    result = {'changed': False}
    koji_profile = sys.modules[session.__module__]
    common_koji.ensure_logged_in(session)
    if state == 'present':
        # The "grant" method will at least raise an error if the permission
        # was already granted, so we can set the "changed" result based on
        # that.
        try:
            session.grantCGAccess(user, name, create=True)
            result['changed'] = True
        except koji_profile.GenericError as e:
            if 'User already has access to content generator' not in str(e):
                raise
    elif state == 'absent':
        # There's no indication whether this changed anything, so we're going
        # to be pessimistic and say we're always changing it.
        session.revokeCGAccess(user, name)
        result['changed'] = True
    return result


def run_module():
    module_args = dict(
        koji=dict(type='str', required=False),
        name=dict(type='str', required=True),
        user=dict(type='str', required=True),
        state=dict(type='str', choices=[
                   'present', 'absent'], required=False, default='present'),
    )
    module = AnsibleModule(
        argument_spec=module_args,
        supports_check_mode=True
    )

    if not common_koji.HAS_KOJI:
        module.fail_json(msg='koji is required for this module')

    check_mode = module.check_mode
    params = module.params
    profile = params['koji']
    name = params['name']
    user = params['user']
    state = params['state']

    session = common_koji.get_session(profile)

    try:
        cgs = list_cgs(session)
        result = ensure_cg(session, user, name, state, cgs, check_mode)
    except UnknownCGsError:
        if check_mode:
            msg = 'check mode does not work without listCGs'
            result = {'changed': False, 'msg': msg}
        else:
            result = ensure_unknown_cg(session, user, name, state)

    module.exit_json(**result)


def main():
    run_module()


if __name__ == '__main__':
    main()