bstinson / centos / releng

Forked from centos/releng 3 years ago
Clone

Blame koji-tags/library/koji_host.py

6e61fb
#!/usr/bin/python
6e61fb
from ansible.module_utils.basic import AnsibleModule
6e61fb
from ansible.module_utils import common_koji
6e61fb
6e61fb
6e61fb
ANSIBLE_METADATA = {
6e61fb
    'metadata_version': '1.0',
6e61fb
    'status': ['preview'],
6e61fb
    'supported_by': 'community'
6e61fb
}
6e61fb
6e61fb
6e61fb
DOCUMENTATION = '''
6e61fb
---
6e61fb
module: koji_host
6e61fb
6e61fb
short_description: Create and manage Koji build hosts
6e61fb
description:
6e61fb
   - This module can add new hosts and manage existing hosts.
6e61fb
   - 'Koji only supports adding new hosts, not deleting them. Once they are
6e61fb
     defined, you can enable or disable the hosts with "state: enabled" or
6e61fb
     "state: disabled".'
6e61fb
6e61fb
options:
6e61fb
   name:
6e61fb
     description:
6e61fb
       - The name of the Koji builder.
6e61fb
       - 'Example: "builder1.example.com".'
6e61fb
     required: true
6e61fb
   arches:
6e61fb
     description:
6e61fb
       - The list of arches this host supports.
6e61fb
       - 'Example: [x86_64]'
6e61fb
     required: true
6e61fb
   channels:
6e61fb
     description:
6e61fb
       - The list of channels this host should belong to.
6e61fb
       - If you specify a completely new channel here, Ansible will create the
6e61fb
         channel on the hub. For example, when you set up OSBS with Koji, you
6e61fb
         must add a builder host to a new "container" channel. You can simply
6e61fb
         specify "container" in the list here, and Ansible will create the new
6e61fb
         "container" channel when it adds your host to that channel.
6e61fb
       - 'Example: [default, createrepo]'
6e61fb
     required: false
6e61fb
   state:
6e61fb
     description:
6e61fb
       - Whether to set this host as "enabled" or "disabled". If unset, this
6e61fb
         defaults to "enabled".
6e61fb
   krb_principal:
6e61fb
     description:
6e61fb
       - Set a non-default krb principal for this host. If unset, Koji will
6e61fb
         use the standard krb principal scheme for builder accounts.
6e61fb
   capacity:
6e61fb
     description:
6e61fb
       - Total task weight for this host. This is a float value. If unset,
6e61fb
         Koji will use the standard capacity for a host (2.0).
6e61fb
       - 'Example: 10.0'
6e61fb
   description:
6e61fb
     description:
6e61fb
       - Human-readable description for this host.
6e61fb
   comment:
6e61fb
     description:
6e61fb
       - Human-readable comment explaining the current state of the host. You
6e61fb
         may write a description here explaining how this host was set up, or
6e61fb
         why this host is currently offline.
6e61fb
requirements:
6e61fb
  - "python >= 2.7"
6e61fb
  - "koji"
6e61fb
'''
6e61fb
6e61fb
EXAMPLES = '''
6e61fb
- name: create a koji host
6e61fb
  hosts: localhost
6e61fb
  tasks:
6e61fb
    - name: Add new builder1 host
6e61fb
      koji_host:
6e61fb
        name: builder1.example.com
6e61fb
        arches: [x86_64]
6e61fb
        state: enabled
6e61fb
        channels:
6e61fb
          - createrepo
6e61fb
          - default
6e61fb
6e61fb
    - name: Add new builder host for OSBS
6e61fb
      koji_host:
6e61fb
        name: containerbuild1.example.com
6e61fb
        arches: [x86_64]
6e61fb
        state: enabled
6e61fb
        channels:
6e61fb
          # This will automatically create the "container" channel
6e61fb
          # if it does not already exist:
6e61fb
          - container
6e61fb
'''
6e61fb
6e61fb
6e61fb
def ensure_channels(session, host_id, host_name, check_mode, desired_channels):
6e61fb
    """
6e61fb
    Ensure that given host belongs to given channels (and only them).
6e61fb
6e61fb
    :param session: Koji client session
6e61fb
    :param int host_id: Koji host ID
6e61fb
    :param int host_name: Koji host name
6e61fb
    :param bool check_mode: don't make any changes
6e61fb
    :param list desired_channels: channels that the host should belong to
6e61fb
    """
6e61fb
    result = {'changed': False, 'stdout_lines': []}
6e61fb
    common_koji.ensure_logged_in(session)
6e61fb
    current_channels = session.listChannels(host_id)
6e61fb
    current_channels = [channel['name'] for channel in current_channels]
6e61fb
    for channel in current_channels:
6e61fb
        if channel not in desired_channels:
6e61fb
            if not check_mode:
6e61fb
                session.removeHostFromChannel(host_name, channel)
6e61fb
            result['stdout_lines'].append('removed host from channel %s' % channel)
6e61fb
            result['changed'] = True
6e61fb
    for channel in desired_channels:
6e61fb
        if channel not in current_channels:
6e61fb
            if not check_mode:
6e61fb
                session.addHostToChannel(host_name, channel, create=True)
6e61fb
            result['stdout_lines'].append('added host to channel %s' % channel)
6e61fb
            result['changed'] = True
6e61fb
    return result
6e61fb
6e61fb
6e61fb
def ensure_host(session, name, check_mode, state, arches, krb_principal,
6e61fb
                channels, **kwargs):
6e61fb
    """
6e61fb
    Ensure that this host is configured in Koji.
6e61fb
6e61fb
    :param session: Koji client session
6e61fb
    :param str name: Koji builder host name
6e61fb
    :param bool check_mode: don't make any changes
6e61fb
    :param str state: "enabled" or "disabled"
6e61fb
    :param list arches: list of arches for this builder.
6e61fb
    :param str krb_principal: custom kerberos principal, or None
6e61fb
    :param list chanels: list of channels this host should belong to.
6e61fb
    :param **kwargs: Pass remaining kwargs directly into Koji's editHost RPC.
6e61fb
    """
6e61fb
    result = {'changed': False, 'stdout_lines': []}
6e61fb
    host = session.getHost(name)
6e61fb
    if not host:
6e61fb
        result['changed'] = True
6e61fb
        result['stdout_lines'].append('created host')
6e61fb
        if check_mode:
6e61fb
            return result
6e61fb
        common_koji.ensure_logged_in(session)
6e61fb
        id_ = session.addHost(name, arches, krb_principal)
6e61fb
        host = session.getHost(id_)
6e61fb
    if state == 'enabled':
6e61fb
        if not host['enabled']:
6e61fb
            result['changed'] = True
6e61fb
            result['stdout_lines'].append('enabled host')
6e61fb
            if not check_mode:
6e61fb
                common_koji.ensure_logged_in(session)
6e61fb
                session.enableHost(name)
6e61fb
    elif state == 'disabled':
6e61fb
        if host['enabled']:
6e61fb
            result['changed'] = True
6e61fb
            result['stdout_lines'].append('disabled host')
6e61fb
            if not check_mode:
6e61fb
                common_koji.ensure_logged_in(session)
6e61fb
                session.disableHost(name)
6e61fb
    edits = {}
6e61fb
    if ' '.join(arches) != host['arches']:
6e61fb
        edits['arches'] = ' '.join(arches)
6e61fb
    for key, value in kwargs.items():
6e61fb
        if value is None:
6e61fb
            continue  # Ansible did not set this parameter.
6e61fb
        if key in host and kwargs[key] != host[key]:
6e61fb
            edits[key] = value
6e61fb
    if edits:
6e61fb
        result['changed'] = True
6e61fb
        for edit in edits.keys():
6e61fb
            result['stdout_lines'].append('edited host %s' % edit)
6e61fb
        if not check_mode:
6e61fb
            common_koji.ensure_logged_in(session)
6e61fb
            session.editHost(name, **edits)
6e61fb
6e61fb
    # Ensure host is member of desired channels.
6e61fb
    if channels not in (None, ''):
6e61fb
        channels_result = ensure_channels(session, host['id'],
6e61fb
                                          name, check_mode, channels)
6e61fb
        if channels_result['changed']:
6e61fb
            result['changed'] = True
6e61fb
        result['stdout_lines'].extend(channels_result['stdout_lines'])
6e61fb
6e61fb
    return result
6e61fb
6e61fb
6e61fb
def run_module():
6e61fb
    module_args = dict(
6e61fb
        koji=dict(type='str', required=False),
6e61fb
        name=dict(type='str', required=True),
6e61fb
        arches=dict(type='list', required=True),
6e61fb
        channels=dict(type='list', required=False, default=None),
6e61fb
        krb_principal=dict(type='str', required=False, default=None),
6e61fb
        capacity=dict(type='float', required=False, default=None),
6e61fb
        description=dict(type='str', required=False, default=None),
6e61fb
        comment=dict(type='str', required=False, default=None),
6e61fb
        state=dict(type='str', choices=[
6e61fb
                   'enabled', 'disabled'], required=False, default='enabled'),
6e61fb
    )
6e61fb
    module = AnsibleModule(
6e61fb
        argument_spec=module_args,
6e61fb
        supports_check_mode=True
6e61fb
    )
6e61fb
6e61fb
    if not common_koji.HAS_KOJI:
6e61fb
        module.fail_json(msg='koji is required for this module')
6e61fb
6e61fb
    check_mode = module.check_mode
6e61fb
    params = module.params
6e61fb
    profile = params['koji']
6e61fb
    name = params['name']
6e61fb
    state = params['state']
6e61fb
6e61fb
    session = common_koji.get_session(profile)
6e61fb
6e61fb
    result = ensure_host(session, name, check_mode, state,
6e61fb
                         arches=params['arches'],
6e61fb
                         channels=params['channels'],
6e61fb
                         krb_principal=params['krb_principal'],
6e61fb
                         capacity=params['capacity'],
6e61fb
                         description=params['description'],
6e61fb
                         comment=params['comment'])
6e61fb
    module.exit_json(**result)
6e61fb
6e61fb
6e61fb
def main():
6e61fb
    run_module()
6e61fb
6e61fb
6e61fb
if __name__ == '__main__':
6e61fb
    main()