Beispiel #1
1
def extract_inventory_relations(asset, relation_type):
    # Get the API options for the relation
    post_options = get_api_options(relation_type)

    # Get all of the hosts
    try:
        relations = tower_cli.get_resource(relation_type).list(all_pages=True, **{'inventory': asset['id']})
    except TowerCLIError as e:
        raise TowerCLIError("Unable to get {} for {} : {}".format(relation_type, asset['id'], e))

    return_relations = []
    # If there are no results return an empty array
    if 'results' not in relations:
        return return_relations

    name_to_id_map = {}
    for relation in relations['results']:
        # if this relation is controlled by an inventory source we can skip it
        if 'has_inventory_sources' in relation and relation['has_inventory_sources']:
            continue
        name_to_id_map[relation['name']] = relation['id']
        new_relation = {}
        map_node_to_post_options(post_options, relation, new_relation)
        if relation_type == 'inventory_source':
            # If this is an inventory source we also need to resolve the source_project
            if 'source_project' in relation and relation['source_project']:
                try:
                    project = tower_cli.get_resource('project').get(relation['source_project'])
                except TowerCLIError as e:
                    raise TowerCLIError("Unable to get project {} for {} : {}".format(
                        relation['source_project'], relation_type, e
                    ))
                new_relation['source_project'] = project['name']
            if 'source_script' in relation and relation['source_script']:
                try:
                    script = tower_cli.get_resource('inventory_script').get(relation['source_script'])
                except TowerCLIError as e:
                    raise TowerCLIError("Unable to get inventory script {} for {} : {}".format(
                        relation['source_script'], relation_type, e
                    ))
                new_relation['source_script'] = script['name']
            if 'credential' in relation and relation['credential']:
                try:
                    credential = tower_cli.get_resource('credential').get(relation['credential'])
                except TowerCLIError as e:
                    raise TowerCLIError("Unable to get inventory credential {} for {} : {}".format(
                        relation['credential'], relation_type, e
                    ))
                new_relation['credential'] = credential['name']

            # Now get the schedules for this source
            if 'related' in relation and 'schedules' in relation['related']:
                schedule_data = extract_schedules(relation)
                new_relation['schedules'] = schedule_data['items']

        del new_relation['inventory']

        return_relations.append(new_relation)

    return {'items': return_relations, 'existing_name_to_id_map': name_to_id_map}
Beispiel #2
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            description=dict(),
            inventory=dict(required=True),
            enabled=dict(type='bool', default=True),
            variables=dict(),
            tower_host=dict(),
            tower_username=dict(),
            tower_password=dict(no_log=True),
            tower_verify_ssl=dict(type='bool', default=True),
            tower_config_file=dict(type='path'),
            state=dict(choices=['present', 'absent'], default='present'),
        ),
        supports_check_mode=True
    )

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    description = module.params.get('description')
    inventory = module.params.get('inventory')
    enabled = module.params.get('enabled')
    state = module.params.get('state')

    variables = module.params.get('variables')
    if variables:
        if variables.startswith('@'):
            filename = os.path.expanduser(variables[1:])
            variables = module.contents_from_file(filename)

    json_output = {'host': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        host = tower_cli.get_resource('host')

        try:
            inv_res = tower_cli.get_resource('inventory')
            inv = inv_res.get(name=inventory)

            if state == 'present':
                result = host.modify(name=name, inventory=inv['id'], enabled=enabled,
                                     variables=variables, description=description, create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = host.delete(name=name, inventory=inv['id'])
        except (exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update host, inventory not found: {0}'.format(excinfo), changed=False)
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            module.fail_json(msg='Failed to update host: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
def main():
    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        job_template=dict(required=True),
        job_type=dict(choices=['run', 'check', 'scan']),
        inventory=dict(),
        credential=dict(),
        limit=dict(),
        tags=dict(type='list'),
        extra_vars=dict(type='list'),
    ))

    module = AnsibleModule(
        argument_spec,
        supports_check_mode=True
    )

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    json_output = {}
    tags = module.params.get('tags')

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        try:
            params = module.params.copy()
            if isinstance(tags, list):
                params['tags'] = ','.join(tags)
            job = tower_cli.get_resource('job')

            lookup_fields = ('job_template', 'inventory', 'credential')
            for field in lookup_fields:
                try:
                    name = params.pop(field)
                    result = tower_cli.get_resource(field).get(name=name)
                    params[field] = result['id']
                except exc.NotFound as excinfo:
                    module.fail_json(msg='Unable to launch job, {0}/{1} was not found: {2}'.format(field, name, excinfo), changed=False)

            result = job.launch(no_input=True, **params)
            json_output['id'] = result['id']
            json_output['status'] = result['status']
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            module.fail_json(msg='Unable to launch job: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #4
0
def main():
    module = AnsibleModule(
        argument_spec=dict(
            name=dict(required=True),
            description=dict(),
            organization=dict(required=True),
            tower_host=dict(),
            tower_username=dict(),
            tower_password=dict(no_log=True),
            tower_verify_ssl=dict(type='bool', default=True),
            tower_config_file=dict(type='path'),
            state=dict(choices=['present', 'absent'], default='present'),
        ),
        supports_check_mode=True
    )

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    description = module.params.get('description')
    organization = module.params.get('organization')
    state = module.params.get('state')

    json_output = {'team': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        team = tower_cli.get_resource('team')

        try:
            org_res = tower_cli.get_resource('organization')
            org = org_res.get(name=organization)

            if state == 'present':
                result = team.modify(name=name, organization=org['id'],
                                     description=description, create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = team.delete(name=name, organization=org['id'])
        except (exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update team, organization not found: {0}'.format(excinfo), changed=False)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update team: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
    def test_create_with_special_fields_new_functional(self):
        """Establish that the correct GET data is used with the new
        method for creating credentials."""
        with client.test_mode as t:
            t.register_json('/credentials/', {'actions': {'POST': {'organization': 'information'}}},
                            method='OPTIONS')
            t.register_json('/credentials/', {'count': 0, 'results': [], 'next': None, 'previous': None},
                            method='GET')
            t.register_json('/credentials/', {'count': 0, 'results': [], 'next': None, 'previous': None},
                            method='GET')
            t.register_json('/credentials/', {'id': 42}, method='POST')

            cred_res = tower_cli.get_resource('credential')
            cred_res.create(name="foobar", user=1, credential_type=1)
            self.assertTrue(cred_res.fields[2].no_lookup)
            self.assertTrue(cred_res.fields[3].no_lookup)

            # Verify request data is correct
            self.assertEqual(len(t.requests), 2)
            self.assertEqual(t.requests[0].method, 'GET')
            self.assertEqual(t.requests[1].method, 'POST')
            self.assertIn('name=foobar', t.requests[0].url)
            # Make sure special fields not used for GET
            self.assertTrue('user' not in t.requests[0].url)
            # Make sure special files are used in actual POST
            self.assertIn('user', t.requests[1].body)
Beispiel #6
0
    def create(self, credential=None, source=None, **kwargs):
        """Create a group and, if necessary, modify the inventory source within
        the group.
        """
        # First, create the group.
        answer = super(Resource, self).create(**kwargs)

        # If the group already exists and we aren't supposed to make changes,
        # then we're done.
        if not kwargs.pop('force_on_exists', False) and not answer['changed']:
            return answer

        # Sanity check: A group was created, but do we need to do anything
        # with the inventory source at all? If no credential or source
        # was specified, then we'd just be updating the inventory source
        # with an effective no-op.
        if not credential and source in ('manual', None):
            return answer

        # Get the inventory source ID ("isid").
        # Inventory sources are not created directly; rather, one was created
        # automatically when the group was created.
        isid = self._get_inventory_source_id(answer)

        # We now have our inventory source ID; modify it according to the
        # provided parameters.
        isrc = get_resource('inventory_source')
        return isrc.modify(isid, credential=credential, source=source,
                                 force_on_exists=True, **kwargs)
Beispiel #7
0
    def modify(self, pk=None, credential=None, source=None, **kwargs):
        """Modify a group and, if necessary, the inventory source within
        the group.
        """
        # First, modify the group.
        answer = super(Resource, self).modify(pk=pk, **kwargs)

        # If the group already exists and we aren't supposed to make changes,
        # then we're done.
        if not kwargs.pop('force_on_exists', True) and not answer['changed']:
            return answer

        # Get the inventory source ID ("isid").
        # Inventory sources are not created directly; rather, one was created
        # automatically when the group was created.
        isid = self._get_inventory_source_id(answer)

        # We now have our inventory source ID; modify it according to the
        # provided parameters.
        #
        # Note: Any fields that were part of the group modification need
        # to be expunged from kwargs before making this call.
        isrc = get_resource('inventory_source')
        for field in self.fields:
            kwargs.pop(field.name, None)
        return isrc.modify(isid, credential=credential, source=source,
                                 force_on_exists=True, **kwargs)
Beispiel #8
0
def update_resources(module, p):
    '''update_resources attempts to fetch any of the resources given
    by name using their unique field (identity)
    '''
    params = p.copy()
    for key in p:
        if key.startswith('tower_'):
            params.pop(key)
    params.pop('state', None)
    identity_map = {
        'user': '******',
        'team': 'name',
        'target_team': 'name',
        'inventory': 'name',
        'job_template': 'name',
        'credential': 'name',
        'organization': 'name',
        'project': 'name',
    }
    for k, v in identity_map.items():
        try:
            if params[k]:
                key = 'team' if k == 'target_team' else k
                result = tower_cli.get_resource(key).get(**{v: params[k]})
                params[k] = result['id']
        except (exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update role, {0} not found: {1}'.format(k, excinfo), changed=False)
    return params
Beispiel #9
0
    def create(self, organization=None, monitor=False, timeout=None,
               *args, **kwargs):
        """Create a new item of resource, with or w/o org.
        This would be a shared class with user, but it needs the ability
        to monitor if the flag is set.
        """
        backup_endpoint = self.endpoint
        if organization:
            debug.log("using alternative endpoint specific to organization",
                      header='details')

            # Get the organization from Tower, will lookup name if needed
            org_resource = get_resource('organization')
            org_data = org_resource.get(organization)
            org_pk = org_data['id']

            self.endpoint = '/organizations/%s%s' % (org_pk, backup_endpoint)
        answer = super(Resource, self).create(*args, **kwargs)
        self.endpoint = backup_endpoint

        # if the monitor flag is set, wait for the SCM to update
        if monitor:
            project_id = answer['id']
            return self.monitor(project_id, timeout=timeout)

        return answer
 def test_create_without_special_fields(self):
     """Establish that a create without user, team, or credential works"""
     with mock.patch(
             'tower_cli.models.base.Resource.create') as mock_create:
         cred_res = tower_cli.get_resource('credential')
         cred_res.create(name="foobar")
         mock_create.assert_called_once_with(name="foobar")
Beispiel #11
0
    def convert(self, value, param, ctx):
        """Return the appropriate interger value. If a non-integer is
        provided, attempt a name-based lookup and return the primary key.
        """
        resource = tower_cli.get_resource(self.resource_name)

        # Ensure that None is passed through without trying to
        # do anything.
        if value is None:
            return None

        # If we were already given an integer, do nothing.
        # This ensures that the convert method is idempotent.
        if isinstance(value, int):
            return value

        # Do we have a string that contains only digits?
        # If so, then convert it to an integer and return it.
        if re.match(r'^[\d]+$', value):
            return int(value)

        # Okay, we have a string. Try to do a name-based lookup on the
        # resource, and return back the ID that we get from that.
        #
        # This has the chance of erroring out, which is fine.
        try:
            debug.log('The %s field is given as a name; '
                      'looking it up.' % param.name, header='details')
            rel = resource.get(**{resource.unique_criterion: value})
        except exc.TowerCLIError as ex:
            raise exc.RelatedError('Could not get %s. %s' %
                                   (self.resource_name, str(ex)))

        # Done! Return the ID.
        return rel['id']
def main():
    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        job_id=dict(type='int', required=True),
        fail_if_not_running=dict(type='bool', default=False),
    ))

    module = AnsibleModule(
        argument_spec=argument_spec,
        supports_check_mode=True,
    )

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    job_id = module.params.get('job_id')
    json_output = {}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        job = tower_cli.get_resource('job')
        params = module.params.copy()

        try:
            result = job.cancel(job_id, **params)
            json_output['id'] = job_id
        except (exc.ConnectionError, exc.BadRequest, exc.TowerCLIError) as excinfo:
            module.fail_json(msg='Unable to cancel job_id/{0}: {1}'.format(job_id, excinfo), changed=False)

    json_output['changed'] = result['changed']
    json_output['status'] = result['status']
    module.exit_json(**json_output)
def main():
    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        name=dict(required=True),
        description=dict(),
        state=dict(choices=['present', 'absent'], default='present'),
    ))

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    description = module.params.get('description')
    state = module.params.get('state')

    json_output = {'organization': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        organization = tower_cli.get_resource('organization')
        try:
            if state == 'present':
                result = organization.modify(name=name, description=description, create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = organization.delete(name=name)
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            module.fail_json(msg='Failed to update the organization: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #14
0
 def __init__(self, data, wfjt, include_id=False):
     ujt_attrs = list(JOB_TYPES.values())
     FK_FIELDS = ujt_attrs + ['inventory', 'credential']
     node_attrs = {}
     attr_names = NODE_STANDARD_FIELDS + ujt_attrs
     if include_id:
         attr_names.append('id')
     for fd in attr_names:
         if fd not in data:
             continue
         if fd in FK_FIELDS and not isinstance(data[fd], int):
             # Node's template was given by name, do lookup
             ujt_res = get_resource(fd)
             ujt_data = ujt_res.get(name=data[fd])
             node_attrs[fd] = ujt_data['id']
         else:
             node_attrs[fd] = data[fd]
     node_attrs['workflow_job_template'] = wfjt
     for ujt_name in ujt_attrs:
         if ujt_name not in node_attrs:
             continue
         if 'unified_job_template' not in node_attrs:
             node_attrs['unified_job_template'] = node_attrs.pop(ujt_name)
         else:
             raise BadRequest(
                 'You should not provide more than one of the attributes'
                 ' job_template, project and inventory_source.'
             )
     self.unified_job_template = node_attrs.get('unified_job_template', None)
     self.node_attrs = node_attrs
     for rel in ['success_nodes', 'failure_nodes', 'always_nodes']:
         setattr(
             self, rel,
             [TreeNode(x, wfjt, include_id=include_id) for x in data.get(rel, data.get(rel[: -6], []))]
         )
Beispiel #15
0
    def create(self, organization=None, monitor=False, timeout=None,
               fail_on_found=False, force_on_exists=False,
               **kwargs):
        """Create a new item of resource, with or w/o org.
        This would be a shared class with user, but it needs the ability
        to monitor if the flag is set.
        """
        # First, run the create method, ignoring the organization given
        answer = super(Resource, self).write(
            create_on_missing=True,
            fail_on_found=fail_on_found, force_on_exists=force_on_exists,
            **kwargs
        )
        project_id = answer['id']

        # If an organization is given, associate it here
        if organization:

            # Get the organization from Tower, will lookup name if needed
            org_resource = get_resource('organization')
            org_data = org_resource.get(organization)
            org_pk = org_data['id']

            debug.log("associating the project with its organization",
                      header='details', nl=1)
            org_resource._assoc('projects', org_pk, project_id)

        # if the monitor flag is set, wait for the SCM to update
        if monitor:
            return self.monitor(project_id, timeout=timeout)

        return answer
def push_data(filename):
    with open(filename, 'r') as f:
        master_dict = yaml.load(f.read())
    for res in res_list_reference:
        if res in master_dict:
            res_mod = tower_cli.get_resource(res)
            for entry in master_dict[res]:
                res_mod.create(**entry)
def main():
    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        name=dict(required=True),
        description=dict(),
        job_type=dict(choices=['run', 'check', 'scan'], required=True),
        inventory=dict(),
        project=dict(required=True),
        playbook=dict(required=True),
        machine_credential=dict(),
        cloud_credential=dict(),
        network_credential=dict(),
        forks=dict(type='int'),
        limit=dict(),
        verbosity=dict(choices=['verbose', 'debug']),
        job_tags=dict(),
        skip_tags=dict(),
        host_config_key=dict(),
        extra_vars_path=dict(type='path', required=False),
        ask_extra_vars=dict(type='bool', default=False),
        ask_limit=dict(type='bool', default=False),
        ask_tags=dict(type='bool', default=False),
        ask_job_type=dict(type='bool', default=False),
        ask_inventory=dict(type='bool', default=False),
        ask_credential=dict(type='bool', default=False),
        become_enabled=dict(type='bool', default=False),
        state=dict(choices=['present', 'absent'], default='present'),
    ))

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    state = module.params.get('state')
    json_output = {'job_template': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        jt = tower_cli.get_resource('job_template')

        params = update_resources(module, module.params)
        params = update_fields(params)
        params['create_on_missing'] = True

        try:
            if state == 'present':
                result = jt.modify(**params)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = jt.delete(**params)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update job template: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #18
0
    def create(self, fail_on_found=False, force_on_exists=False, **kwargs):
        """Create a group and, if necessary, modify the inventory source within
        the group.
        """
        group_fields = [f.name for f in self.fields]
        if kwargs.get('parent', None):
            parent_data = self.set_child_endpoint(parent=kwargs['parent'],
                                                  inventory=kwargs.get(
                                                      'inventory', None))
            kwargs['inventory'] = parent_data['inventory']
            group_fields.append('group')
        elif 'inventory' not in kwargs:
            raise exc.UsageError('To create a group, you must provide a '
                                 'parent inventory or parent group.')

        # Break out the options for the group vs its inventory_source
        is_kwargs = {}
        for field in kwargs.copy():
            if field not in group_fields:
                is_kwargs[field] = kwargs.pop(field)

        # Handle alias for "manual" source
        if is_kwargs.get('source', None) == 'manual':
            is_kwargs.pop('source')

        # First, create the group.
        answer = super(Resource, self).create(fail_on_found=fail_on_found,
                                              force_on_exists=force_on_exists,
                                              **kwargs)

        # If the group already exists and we aren't supposed to make changes,
        # then we're done.
        if not force_on_exists and not answer['changed']:
            return answer

        # Sanity check: A group was created, but do we need to do anything
        # with the inventory source at all? If no credential or source
        # was specified, then we'd just be updating the inventory source
        # with an effective no-op.
        if len(is_kwargs) == 0:
            return answer

        # Get the inventory source ID ("isid").
        # Inventory sources are not created directly; rather, one was created
        # automatically when the group was created.
        isid = self._get_inventory_source_id(answer)

        # We now have our inventory source ID; modify it according to the
        # provided parameters.
        isrc = get_resource('inventory_source')
        is_answer = isrc.write(pk=isid, force_on_exists=True, **is_kwargs)

        # If either the inventory_source or the group objects were modified
        # then refelect this in the output to avoid confusing the user.
        if is_answer['changed']:
            answer['changed'] = True
        return answer
def main():
    argument_spec = dict(
        name=dict(required=True),
        description=dict(required=False),
        kind=dict(required=False, choices=KIND_CHOICES.keys()),
        inputs=dict(type='dict', required=False),
        injectors=dict(type='dict', required=False),
        state=dict(choices=['present', 'absent'], default='present'),
    )

    module = TowerModule(
        argument_spec=argument_spec,
        supports_check_mode=False
    )

    name = module.params.get('name')
    kind = module.params.get('kind')
    state = module.params.get('state')

    json_output = {'credential_type': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        credential_type_res = tower_cli.get_resource('credential_type')

        params = {}
        params['name'] = name
        params['kind'] = kind
        params['managed_by_tower'] = False

        if module.params.get('description'):
            params['description'] = module.params.get('description')

        if module.params.get('inputs'):
            params['inputs'] = module.params.get('inputs')

        if module.params.get('injectors'):
            params['injectors'] = module.params.get('injectors')

        try:
            if state == 'present':
                params['create_on_missing'] = True
                result = credential_type_res.modify(**params)
                json_output['id'] = result['id']
            elif state == 'absent':
                params['fail_on_missing'] = False
                result = credential_type_res.delete(**params)

        except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
            module.fail_json(
                msg='Failed to update credential type: {0}'.format(excinfo),
                changed=False
            )

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #20
0
 def _get_schema(self, wfjt_id):
     """
     Returns a dictionary that represents the node network of the
     workflow job template
     """
     node_res = get_resource('node')
     node_results = node_res.list(workflow_job_template=wfjt_id,
                                  all_pages=True)['results']
     return self._workflow_node_structure(node_results)
Beispiel #21
0
 def _get_schema(self, wfjt_id):
     """
     Returns a dictionary that represents the node network of the
     workflow job template
     """
     node_res = get_resource('node')
     node_results = node_res.list(workflow_job_template=wfjt_id,
                                  all_pages=True)['results']
     return self._workflow_node_structure(node_results)
 def test_create_with_special_fields_old(self):
     """Establish that creating with special fields passes through as-is
     if the API does not support this use mode."""
     with client.test_mode as t:
         t.register_json('/credentials/', {'actions': {'POST': {}}}, method='OPTIONS')
         with mock.patch('tower_cli.models.base.Resource.create') as mock_create:
             cred_res = tower_cli.get_resource('credential')
             cred_res.create(name="foobar", organization="Foo Ops")
             mock_create.assert_called_once_with(name="foobar", organization="Foo Ops")
Beispiel #23
0
    def create(self, fail_on_found=False, force_on_exists=False, **kwargs):
        """Create a group and, if necessary, modify the inventory source within
        the group.
        """
        group_fields = [f.name for f in self.fields]
        if kwargs.get('parent', None):
            parent_data = self.set_child_endpoint(
                parent=kwargs['parent'],
                inventory=kwargs.get('inventory', None))
            kwargs['inventory'] = parent_data['inventory']
            group_fields.append('group')
        elif 'inventory' not in kwargs:
            raise exc.UsageError('To create a group, you must provide a '
                                 'parent inventory or parent group.')

        # Break out the options for the group vs its inventory_source
        is_kwargs = {}
        for field in kwargs.copy():
            if field not in group_fields:
                is_kwargs[field] = kwargs.pop(field)

        # Handle alias for "manual" source
        if is_kwargs.get('source', None) == 'manual':
            is_kwargs.pop('source')

        # First, create the group.
        answer = super(Resource, self).create(
            fail_on_found=fail_on_found, force_on_exists=force_on_exists,
            **kwargs)

        # If the group already exists and we aren't supposed to make changes,
        # then we're done.
        if not force_on_exists and not answer['changed']:
            return answer

        # Sanity check: A group was created, but do we need to do anything
        # with the inventory source at all? If no credential or source
        # was specified, then we'd just be updating the inventory source
        # with an effective no-op.
        if len(is_kwargs) == 0:
            return answer

        # Get the inventory source ID ("isid").
        # Inventory sources are not created directly; rather, one was created
        # automatically when the group was created.
        isid = self._get_inventory_source_id(answer)

        # We now have our inventory source ID; modify it according to the
        # provided parameters.
        isrc = get_resource('inventory_source')
        is_answer = isrc.write(pk=isid, force_on_exists=True, **is_kwargs)

        # If either the inventory_source or the group objects were modified
        # then refelect this in the output to avoid confusing the user.
        if is_answer['changed']:
            answer['changed'] = True
        return answer
Beispiel #24
0
def main():

    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        name=dict(required=True),
        description=dict(),
        organization=dict(required=True),
        state=dict(choices=['present', 'absent'], default='present'),
    ))

    module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    description = module.params.get('description')
    organization = module.params.get('organization')
    state = module.params.get('state')

    json_output = {'team': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        team = tower_cli.get_resource('team')

        try:
            org_res = tower_cli.get_resource('organization')
            org = org_res.get(name=organization)

            if state == 'present':
                result = team.modify(name=name, organization=org['id'],
                                     description=description, create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = team.delete(name=name, organization=org['id'])
        except (exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update team, organization not found: {0}'.format(excinfo), changed=False)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update team: {0}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #25
0
def main():
    module = AnsibleModule(argument_spec=dict(
        name=dict(required=True),
        description=dict(),
        job_type=dict(choices=['run', 'check', 'scan'], required=True),
        inventory=dict(),
        project=dict(required=True),
        playbook=dict(required=True),
        machine_credential=dict(),
        cloud_credential=dict(),
        network_credential=dict(),
        forks=dict(type='int'),
        limit=dict(),
        verbosity=dict(choices=['verbose', 'debug']),
        job_tags=dict(),
        skip_tags=dict(),
        extra_vars=dict(type='list', required=False),
        ask_extra_vars=dict(type='bool', default=False),
        ask_limit=dict(type='bool', default=False),
        ask_tags=dict(type='bool', default=False),
        ask_job_type=dict(type='bool', default=False),
        ask_inventory=dict(type='bool', default=False),
        ask_credential=dict(type='bool', default=False),
        become_enabled=dict(type='bool', default=False),
        config_file=dict(),
        state=dict(choices=['present', 'absent'], default='present'),
    ),
                           supports_check_mode=False)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    name = module.params.get('name')
    state = module.params.get('state')

    json_output = {'job_template': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        jt = tower_cli.get_resource('job_template')

        params = update_fields(module.params)
        params = update_resources(module, params)
        params['create_on_missing'] = True

        try:
            if state == 'present':
                result = jt.modify(**params)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = jt.delete(**params)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound) as excinfo:
            module.fail_json(msg='{}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #26
0
def main():
    argument_spec = dict(
        job_id=dict(type='int', required=True),
        timeout=dict(type='int'),
        min_interval=dict(type='float', default=1),
        max_interval=dict(type='float', default=30),
    )

    module = TowerModule(argument_spec, supports_check_mode=True)

    json_output = {}
    fail_json = None

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        job = tower_cli.get_resource('job')
        params = module.params.copy()

        # tower-cli gets very noisy when monitoring.
        # We pass in our our outfile to suppress the out during our monitor call.
        outfile = StringIO()
        params['outfile'] = outfile

        job_id = params.get('job_id')
        try:
            result = job.monitor(job_id, **params)
        except exc.Timeout:
            result = job.status(job_id)
            result['id'] = job_id
            json_output['msg'] = 'Timeout waiting for job to finish.'
            json_output['timeout'] = True
        except exc.NotFound as excinfo:
            fail_json = dict(
                msg='Unable to wait, no job_id {0} found: {1}'.format(
                    job_id, excinfo),
                changed=False)
        except exc.JobFailure as excinfo:
            fail_json = dict(
                msg='Job with id={} failed, error: {}'.format(job_id, excinfo))
            fail_json['success'] = False
            result = job.get(job_id)
            for k in ('id', 'status', 'elapsed', 'started', 'finished'):
                fail_json[k] = result.get(k)
        except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo:
            fail_json = dict(msg='Unable to wait for job: {0}'.format(excinfo),
                             changed=False)

    if fail_json is not None:
        module.fail_json(**fail_json)

    json_output['success'] = True
    for k in ('id', 'status', 'elapsed', 'started', 'finished'):
        json_output[k] = result.get(k)

    module.exit_json(**json_output)
Beispiel #27
0
def main():
    module = AnsibleModule(argument_spec=dict(
        username=dict(required=True),
        first_name=dict(),
        last_name=dict(),
        password=dict(no_log=True),
        email=dict(required=True),
        superuser=dict(type='bool', default=False),
        auditor=dict(type='bool', default=False),
        tower_host=dict(),
        tower_username=dict(),
        tower_password=dict(no_log=True),
        tower_verify_ssl=dict(type='bool', default=True),
        tower_config_file=dict(type='path'),
        state=dict(choices=['present', 'absent'], default='present'),
    ),
                           supports_check_mode=True)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    username = module.params.get('username')
    first_name = module.params.get('first_name')
    last_name = module.params.get('last_name')
    password = module.params.get('password')
    email = module.params.get('email')
    superuser = module.params.get('superuser')
    auditor = module.params.get('auditor')
    state = module.params.get('state')

    json_output = {'username': username, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        user = tower_cli.get_resource('user')
        try:
            if state == 'present':
                result = user.modify(username=username,
                                     first_name=first_name,
                                     last_name=last_name,
                                     email=email,
                                     password=password,
                                     is_superuser=superuser,
                                     is_auditor=auditor,
                                     create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = user.delete(username=username)
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            module.fail_json(
                msg='Failed to update the user: {0}'.format(excinfo),
                changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #28
0
def main():
    argument_spec = dict(
        name=dict(required=True),
        organization=dict(required=True),
        state=dict(choices=['present', 'absent'], default='present'),
    )

    module = TowerModule(argument_spec=argument_spec, supports_check_mode=True)

    name = module.params.get('name')
    organization = module.params.get('organization')
    state = module.params.get('state')

    json_output = {'label': name, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        label = tower_cli.get_resource('label')

        try:
            org_res = tower_cli.get_resource('organization')
            org = org_res.get(name=organization)

            if state == 'present':
                result = label.modify(name=name,
                                      organization=org['id'],
                                      create_on_missing=True)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = label.delete(name=name, organization=org['id'])
        except (exc.NotFound) as excinfo:
            module.fail_json(
                msg='Failed to update label, organization not found: {0}'.
                format(excinfo),
                changed=False)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound,
                exc.AuthError) as excinfo:
            module.fail_json(msg='Failed to update label: {0}'.format(excinfo),
                             changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #29
0
def get_content(res_name):
    res = get_resource(res_name)
    content = OrderedDict()
    for field in res.fields:
        for attr in ATTR_TO_SHOW:
            content.setdefault(attr, [])
            attr_val = getattr(field, attr, 'N/A')
            attr_val = convert_to_str(field, attr, attr_val)
            content[attr].append(attr_val)
    return content
Beispiel #30
0
    def sync(self, group, monitor=False, wait=False, timeout=None, **kwargs):
        """Update the given group's inventory source."""

        isrc = get_resource('inventory_source')
        isid = self._get_inventory_source_id(group, kwargs)
        return isrc.update(isid,
                           monitor=monitor,
                           timeout=timeout,
                           wait=wait,
                           **kwargs)
Beispiel #31
0
def associate_host_to_group(name, groups, host, inv, json_output):
    group_obj = tower_cli.get_resource('group')
    host_res = host.get(inventory=inv['id'], name=name)
    for group in groups:
        group_res = group_obj.get(inventory=inv['id'], name=group.strip())
        changed = host.associate(host=host_res['id'], group=group_res['id'])
        if changed['changed'] is True:
            json_output['group_added'] = group.strip()
            return True
    return False
Beispiel #32
0
def get_content(res_name):
    res = get_resource(res_name)
    content = OrderedDict()
    for field in res.fields:
        for attr in ATTR_TO_SHOW:
            content.setdefault(attr, [])
            attr_val = getattr(field, attr, 'N/A')
            attr_val = convert_to_str(field, attr, attr_val)
            content[attr].append(attr_val)
    return content
def pull_data():
    master_dict = {}
    for res in res_list_reference:
        res_mod = tower_cli.get_resource(res)
        res_response = res_mod.list(all_pages=True)
        standard_fields = res_fields[res] + res_extras[res].keys()
        master_dict[res] = []
        for entry in res_response:
            item_dict = {}
            for field in standard_fields:
                if field in res_list_reference:
                    target_mod = tower_cli.get_resource(field)
                    target_entry = target_mod.get(int(entry[field]))
                    item_dict[field] = target_entry['name']
                elif entry[field] == '$encrypted$':
                    pass
                else:
                    item_dict[field] = entry[field]
            master_dict[res].append(item_dict)
    print yaml.dump(master_dict, default_flow_style=False)
 def test_create_with_special_fields_new(self):
     """Establish that creating with special fields uses special no_lookup
     tool if given special fields and the API supports that use case."""
     with client.test_mode as t:
         t.register_json('/credentials/', {'actions': {'POST': {'organization': 'information'}}},
                         method='OPTIONS')
         with mock.patch('tower_cli.models.base.Resource.create') as mock_create:
             cred_res = tower_cli.get_resource('credential')
             cred_res.create(name="foobar", organization="Foo Ops")
             mock_create.assert_called_once_with(name="foobar", organization="Foo Ops")
             self.assertTrue(cred_res.fields[2].no_lookup)
 def list_resource_commands(self):
     """Returns a list of multi-commands for each resource type.
     """
     resource_path = os.path.abspath(
         os.path.join(os.path.dirname(__file__), os.pardir, 'resources'))
     answer = set([])
     for _, name, _ in pkgutil.iter_modules([resource_path]):
         res = tower_cli.get_resource(name)
         if not getattr(res, 'internal', False):
             answer.add(name)
     return sorted(answer)
Beispiel #36
0
def pull_data():
    master_dict = {}
    for res in res_list_reference:
        res_mod = tower_cli.get_resource(res)
        res_response = res_mod.list(all_pages=True)
        standard_fields = res_fields[res] + res_extras[res].keys()
        master_dict[res] = []
        for entry in res_response:
            item_dict = {}
            for field in standard_fields:
                if field in res_list_reference:
                    target_mod = tower_cli.get_resource(field)
                    target_entry = target_mod.get(int(entry[field]))
                    item_dict[field] = target_entry['name']
                elif entry[field] == '$encrypted$':
                    pass
                else:
                    item_dict[field] = entry[field]
            master_dict[res].append(item_dict)
    print yaml.dump(master_dict, default_flow_style=False)
Beispiel #37
0
def main():
    module = AnsibleModule(argument_spec=dict(
        job_template=dict(required=True),
        job_type=dict(choices=['run', 'check', 'scan']),
        inventory=dict(),
        credential=dict(),
        limit=dict(),
        tags=dict(),
        extra_vars=dict(type='list', required=False),
        config_file=dict(),
    ),
                           supports_check_mode=False)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    json_output = {}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        try:
            params = module.params.copy()
            job = tower_cli.get_resource('job')

            try:
                jt_name = params.pop('job_template')
                jt = tower_cli.get_resource('job_template').get(name=jt_name)
            except exc.NotFound as excinfo:
                module.fail_json(msg='{} job_template: {}'.format(
                    excinfo, jt_name),
                                 changed=False)

            result = job.launch(jt['id'], no_input=True, **params)
            json_output['id'] = result['id']
            json_output['status'] = result['status']
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            module.fail_json(msg='{}'.format(excinfo), changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #38
0
    def create(self,
               organization=None,
               monitor=False,
               wait=False,
               timeout=None,
               fail_on_found=False,
               force_on_exists=False,
               **kwargs):
        """Create a new item of resource, with or w/o org.
        This would be a shared class with user, but it needs the ability
        to monitor if the flag is set.
        """
        if 'job_timeout' in kwargs and 'timeout' not in kwargs:
            kwargs['timeout'] = kwargs.pop('job_timeout')

        post_associate = False
        if organization:
            # Processing the organization flag depends on version
            debug.log('Checking Organization Relationship.', header='details')
            r = client.options('/projects/')
            if 'organization' in r.json()['actions']['POST']:
                kwargs['organization'] = organization
            else:
                post_associate = True

        # First, run the create method, ignoring the organization given
        answer = super(Resource, self).write(create_on_missing=True,
                                             fail_on_found=fail_on_found,
                                             force_on_exists=force_on_exists,
                                             **kwargs)
        project_id = answer['id']

        # If an organization is given, associate it here
        if post_associate:

            # Get the organization from Tower, will lookup name if needed
            org_resource = get_resource('organization')
            org_data = org_resource.get(organization)
            org_pk = org_data['id']

            debug.log("associating the project with its organization",
                      header='details',
                      nl=1)
            org_resource._assoc('projects', org_pk, project_id)

        # if the monitor flag is set, wait for the SCM to update
        if monitor and answer.get('changed', False):
            return self.monitor(pk=None, parent_pk=project_id, timeout=timeout)
        elif wait and answer.get('changed', False):
            return self.wait(pk=None, parent_pk=project_id, timeout=timeout)

        return answer
Beispiel #39
0
def main():
    argument_spec = tower_argument_spec()
    argument_spec.update(dict(
        job_id=dict(type='int', required=True),
        timeout=dict(type='int'),
        min_interval=dict(type='float', default=1),
        max_interval=dict(type='float', default=30),
    ))

    module = AnsibleModule(
        argument_spec,
        supports_check_mode=True
    )

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    json_output = {}
    fail_json = None

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        job = tower_cli.get_resource('job')
        params = module.params.copy()

        # tower-cli gets very noisy when monitoring.
        # We pass in our our outfile to suppress the out during our monitor call.
        outfile = StringIO()
        params['outfile'] = outfile

        job_id = params.get('job_id')
        try:
            result = job.monitor(job_id, **params)
        except exc.Timeout as excinfo:
            result = job.status(job_id)
            result['id'] = job_id
            json_output['msg'] = 'Timeout waiting for job to finish.'
            json_output['timeout'] = True
        except exc.NotFound as excinfo:
            fail_json = dict(msg='Unable to wait, no job_id {0} found: {1}'.format(job_id, excinfo), changed=False)
        except (exc.ConnectionError, exc.BadRequest) as excinfo:
            fail_json = dict(msg='Unable to wait for job: {0}'.format(excinfo), changed=False)

    if fail_json is not None:
        module.fail_json(**fail_json)

    json_output['success'] = True
    for k in ('id', 'status', 'elapsed', 'started', 'finished'):
        json_output[k] = result.get(k)

    module.exit_json(**json_output)
Beispiel #40
0
def get_resource_id(kind, name):
    """
    Attempts to find a <kind> resource named <name> and return it's id.
    """
    try:
        resource = tower_cli.get_resource(kind)
        item = resource.get(name=name)
        return item['id']
    except (exc.NotFound) as excinfo:
        module.fail_json(
            msg="Could not update schedule, {0} not found: {1}".format(
                kind, name),
            changed=False)
Beispiel #41
0
    def create(self, fail_on_found=False, force_on_exists=False, **kwargs):
        """Create a new label.

        There are two types of label creation: isolatedly creating a new label and creating a new label under
        a job template. Here the two types are discriminated by whether to provide --job-template option.

        Fields in the resource's `identity` tuple are used for a lookup; if a match is found, then no-op (unless
        `force_on_exists` is set) but do not fail (unless `fail_on_found` is set).

        =====API DOCS=====
        Create a label.

        :param job_template: Primary key or name of the job template for the created label to associate to.
        :type job_template: str
        :param fail_on_found: Flag that if set, the operation fails if an object matching the unique criteria
                              already exists.
        :type fail_on_found: bool
        :param force_on_exists: Flag that if set, then if a match is found on unique fields, other fields will
                                be updated to the provided values.; If unset, a match causes the request to be
                                a no-op.
        :type force_on_exists: bool
        :param `**kwargs`: Keyword arguments which, all together, will be used as POST body to create the
                           resource object.
        :returns: A dictionary combining the JSON output of the created resource, as well as two extra fields:
                  "changed", a flag indicating if the resource is created successfully; "id", an integer which
                  is the primary key of the created object.
        :rtype: dict
        :raises tower_cli.exceptions.TowerCLIError: When the label already exists and ``fail_on_found`` flag is on.

        =====API DOCS=====
        """
        jt_id = kwargs.pop('job_template', None)
        old_endpoint = self.endpoint
        if jt_id is not None:
            jt = get_resource('job_template')
            jt.get(pk=jt_id)
            try:
                label_id = self.get(name=kwargs.get('name', None), organization=kwargs.get('organization', None))['id']
            except exc.NotFound:
                pass
            else:
                if fail_on_found:
                    raise exc.TowerCLIError('Label already exists and fail-on-found is switched on. Please use'
                                            ' "associate_label" method of job_template instead.')
                else:
                    debug.log('Label already exists, associating with job template.', header='details')
                    return jt.associate_label(job_template=jt_id, label=label_id)
            self.endpoint = '/job_templates/%d/labels/' % jt_id
        result = super(Resource, self).create(fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs)
        self.endpoint = old_endpoint
        return result
Beispiel #42
0
def main():

    argument_spec = tower_argument_spec()
    argument_spec.update(
        dict(
            user=dict(),
            team=dict(),
            role=dict(choices=[
                "admin", "read", "member", "execute", "adhoc", "update", "use",
                "auditor"
            ]),
            target_team=dict(),
            inventory=dict(),
            job_template=dict(),
            credential=dict(),
            organization=dict(),
            project=dict(),
            state=dict(choices=['present', 'absent'], default='present'),
        ))

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    if not HAS_TOWER_CLI:
        module.fail_json(msg='ansible-tower-cli required for this module')

    role_type = module.params.pop('role')
    state = module.params.get('state')

    json_output = {'role': role_type, 'state': state}

    tower_auth = tower_auth_config(module)
    with settings.runtime_values(**tower_auth):
        tower_check_mode(module)
        role = tower_cli.get_resource('role')

        params = update_resources(module, module.params)
        params['type'] = role_type

        try:
            if state == 'present':
                result = role.grant(**params)
                json_output['id'] = result['id']
            elif state == 'absent':
                result = role.revoke(**params)
        except (exc.ConnectionError, exc.BadRequest, exc.NotFound) as excinfo:
            module.fail_json(msg='Failed to update role: {0}'.format(excinfo),
                             changed=False)

    json_output['changed'] = result['changed']
    module.exit_json(**json_output)
Beispiel #43
0
    def create(self, fail_on_found=False, force_on_exists=False, **kwargs):
        """Create a new label.

        There are two types of label creation: isolatedly creating a new label and creating a new label under
        a job template. Here the two types are discriminated by whether to provide --job-template option.

        Fields in the resource's `identity` tuple are used for a lookup; if a match is found, then no-op (unless
        `force_on_exists` is set) but do not fail (unless `fail_on_found` is set).

        =====API DOCS=====
        Create a label.

        :param job_template: Primary key or name of the job template for the created label to associate to.
        :type job_template: str
        :param fail_on_found: Flag that if set, the operation fails if an object matching the unique criteria
                              already exists.
        :type fail_on_found: bool
        :param force_on_exists: Flag that if set, then if a match is found on unique fields, other fields will
                                be updated to the provided values.; If unset, a match causes the request to be
                                a no-op.
        :type force_on_exists: bool
        :param `**kwargs`: Keyword arguments which, all together, will be used as POST body to create the
                           resource object.
        :returns: A dictionary combining the JSON output of the created resource, as well as two extra fields:
                  "changed", a flag indicating if the resource is created successfully; "id", an integer which
                  is the primary key of the created object.
        :rtype: dict
        :raises tower_cli.exceptions.TowerCLIError: When the label already exists and ``fail_on_found`` flag is on.

        =====API DOCS=====
        """
        jt_id = kwargs.pop('job_template', None)
        old_endpoint = self.endpoint
        if jt_id is not None:
            jt = get_resource('job_template')
            jt.get(pk=jt_id)
            try:
                label_id = self.get(name=kwargs.get('name', None), organization=kwargs.get('organization', None))['id']
            except exc.NotFound:
                pass
            else:
                if fail_on_found:
                    raise exc.TowerCLIError('Label already exists and fail-on-found is switched on. Please use'
                                            ' "associate_label" method of job_template instead.')
                else:
                    debug.log('Label already exists, associating with job template.', header='details')
                    return jt.associate_label(job_template=jt_id, label=label_id)
            self.endpoint = '/job_templates/%d/labels/' % jt_id
        result = super(Resource, self).create(fail_on_found=fail_on_found, force_on_exists=force_on_exists, **kwargs)
        self.endpoint = old_endpoint
        return result
Beispiel #44
0
def get_job_template(template="Network-Validate-Traffic",
                     host_name='127.0.0.1',
                     user_name='admin',
                     pass_word='admin'):
    with conf.settings.runtime_values(host=host_name,
                                      username=user_name,
                                      password=pass_word,
                                      verify_ssl=False):
        res = get_resource('job_template')
        result = res.list(all_pages=True)
    job_templates = result.get('results')
    for job_template in job_templates:
        if job_template.get('name').lower() == template.lower():
            return job_template.get('url')
 def test_sync(self):
     """Establish that the sync method correctly forwards to the
     inventory source method, after getting the inventory source ID.
     """
     isrc = tower_cli.get_resource('inventory_source')
     with mock.patch.object(type(isrc), 'sync') as isrc_sync:
         with client.test_mode as t:
             t.register_json('/groups/1/', {
                 'id': 1, 'name': 'foo', 'inventory': 1,
                 'related': {'inventory_source': '/inventory_sources/42/'},
             }, method='GET')
             self.gr.sync(1)
             isrc_sync.assert_called_once_with(42)
             self.assertEqual(len(t.requests), 1)
 def test_create_with_special_fields_old(self):
     """Establish that creating with special fields passes through as-is
     if the API does not support this use mode."""
     with client.test_mode as t:
         t.register_json('/credentials/', {'actions': {
             'POST': {}
         }},
                         method='OPTIONS')
         with mock.patch(
                 'tower_cli.models.base.Resource.create') as mock_create:
             cred_res = tower_cli.get_resource('credential')
             cred_res.create(name="foobar", organization="Foo Ops")
             mock_create.assert_called_once_with(name="foobar",
                                                 organization="Foo Ops")
Beispiel #47
0
 def list_commands(self, ctx):
     """Return a list of commands present in the commands and resources
     folders, but not subcommands.
     """
     answer = set()
     for filename in os.listdir('%s/%s/' %
                                (tower_cli.whereami, 'resources')):
         if filename.endswith('.py') and not filename.startswith('_'):
             res = tower_cli.get_resource(filename[:-3])
             if not getattr(res, 'internal', False):
                 answer.add(filename[:-3])
     for cmd_name in misc.__all__:
         answer.add(cmd_name)
     return sorted(answer)
Beispiel #48
0
def credential_type_for_v1_kind(params, module):
    credential_type_res = tower_cli.get_resource('credential_type')
    kind = params.pop('kind')
    arguments = {'managed_by_tower': True}
    if kind == 'ssh':
        if params.get('vault_password'):
            arguments['kind'] = 'vault'
        else:
            arguments['kind'] = 'ssh'
    elif kind in ('net', 'scm', 'insights', 'vault'):
        arguments['kind'] = kind
    elif kind in KIND_CHOICES:
        arguments.update(dict(kind='cloud', name=KIND_CHOICES[kind]))
    return credential_type_res.get(**arguments)
Beispiel #49
0
 def list_resource_commands(self):
     """Returns a list of multi-commands for each resource type.
     """
     resource_path = os.path.abspath(os.path.join(
         os.path.dirname(__file__),
         os.pardir,
         'resources'
     ))
     answer = set([])
     for _, name, _ in pkgutil.iter_modules([resource_path]):
         res = tower_cli.get_resource(name)
         if not getattr(res, 'internal', False):
             answer.add(name)
     return sorted(answer)
Beispiel #50
0
 def test_type_name(self):
     """Establish that custom types are equipped with __name__ field and the
     upstream click.Choice's issue of having no __name__ field is properly
     dealt with.
     """
     names = [
         'ad_hoc', 'credential', 'group', 'host', 'inventory',
         'inventory_source', 'job', 'job_template', 'organization',
         'project', 'team', 'user'
     ]
     for res_name in names:
         res = get_resource(res_name)
         self.assertEqual(type(res.fields), type([]))
         self.assertEqual(str(res.fields).startswith('[<Field:'), True)
def process(task_vars):
    with session(task_vars['tower_server'], task_vars['username'], task_vars['password']):
        job = get_resource('job')

        try:
            k_vars = {}
            if task_vars['inventory']:
                result = get_resource_id(get_resource('inventory'), task_vars['inventory'])
                print("* set inventory : {0}->{1}".format(task_vars['inventory'], result))
                k_vars['inventory'] = result

            if task_vars['credential']:
                result = get_resource_id(get_resource('credential'), task_vars['credential'])
                print("* set credentials : {0}->{1}".format(task_vars['credential'], result))
                k_vars['credential'] = result

            if task_vars['extraVars2']:
                vars_ = str(task_vars['extraVars2'])
                print("* set extra_vars : {0}".format(vars_))
                # TODO: manage taskPasswordToken && taskPassword (turn hidden in waiting for...)
                k_vars['extra_vars'] = [vars_]

            print("\n")
            print("```")  # started markdown code block
            res = job.launch(job_template=task_vars['jobTemplate'], monitor=task_vars['waitTillComplete'], **k_vars)

        finally:
            print("```")
            print("\n")  # end markdown code block

        globals()['jobId'] = res['id']
        globals()['jobStatus'] = res['status']

        print("* [Job %s Link](%s/#/jobs/%s)" % (res['id'], task_vars['tower_server']['url'], res['id']))

        if task_vars['stopOnFailure'] and not res['status'] == 'successful':
            raise Exception("Failed with status %s" % res['status'])
Beispiel #52
0
    def convert(self, value, param, ctx):
        """Return the appropriate integer value. If a non-integer is
        provided, attempt a name-based lookup and return the primary key.
        """
        resource = tower_cli.get_resource(self.resource_name)

        # Ensure that None is passed through without trying to
        # do anything.
        if value is None:
            return None

        # If we were already given an integer, do nothing.
        # This ensures that the convert method is idempotent.
        if isinstance(value, int):
            return value

        # Do we have a string that contains only digits?
        # If so, then convert it to an integer and return it.
        if re.match(r'^[\d]+$', value):
            return int(value)

        # Special case to allow disassociations
        if value == 'null':
            return value

        # Okay, we have a string. Try to do a name-based lookup on the
        # resource, and return back the ID that we get from that.
        #
        # This has the chance of erroring out, which is fine.
        try:
            debug.log('The %s field is given as a name; '
                      'looking it up.' % param.name, header='details')
            lookup_data = {resource.identity[-1]: value}
            rel = resource.get(**lookup_data)
        except exc.MultipleResults:
            raise exc.MultipleRelatedError(
                'Cannot look up {0} exclusively by name, because multiple {0} '
                'objects exist with that name.\n'
                'Please send an ID. You can get the ID for the {0} you want '
                'with:\n'
                '  tower-cli {0} list --name "{1}"'.format(self.resource_name,
                                                           value),
            )
        except exc.TowerCLIError as ex:
            raise exc.RelatedError('Could not get %s. %s' %
                                   (self.resource_name, str(ex)))

        # Done! Return the ID.
        return rel['id']
Beispiel #53
0
    def convert(self, value, param, ctx):
        """Return the appropriate integer value. If a non-integer is
        provided, attempt a name-based lookup and return the primary key.
        """
        resource = tower_cli.get_resource(self.resource_name)

        # Ensure that None is passed through without trying to
        # do anything.
        if value is None:
            return None

        # If we were already given an integer, do nothing.
        # This ensures that the convert method is idempotent.
        if isinstance(value, int):
            return value

        # Do we have a string that contains only digits?
        # If so, then convert it to an integer and return it.
        if re.match(r'^[\d]+$', value):
            return int(value)

        # Special case to allow disassociations
        if value == 'null':
            return value

        # Okay, we have a string. Try to do a name-based lookup on the
        # resource, and return back the ID that we get from that.
        #
        # This has the chance of erroring out, which is fine.
        try:
            debug.log('The %s field is given as a name; '
                      'looking it up.' % param.name,
                      header='details')
            lookup_data = {resource.identity[-1]: value}
            rel = resource.get(**lookup_data)
        except exc.MultipleResults as ex:
            raise exc.MultipleRelatedError(
                'Cannot look up {0} exclusively by name, because multiple {0} '
                'objects exist with that name.\n'
                'Please send an ID. You can get the ID for the {0} you want '
                'with:\n'
                '  tower-cli {0} list --name "{1}"'.format(
                    self.resource_name, value), )
        except exc.TowerCLIError as ex:
            raise exc.RelatedError('Could not get %s. %s' %
                                   (self.resource_name, str(ex)))

        # Done! Return the ID.
        return rel['id']
Beispiel #54
0
def get_api_options(asset_type):
    if asset_type not in API_POST_OPTIONS:
        endpoint = tower_cli.get_resource(asset_type).endpoint
        response = client.options(endpoint)
        return_json = response.json()
        if "actions" not in return_json or "POST" not in return_json["actions"]:
            # Maybe we want to do a debug.log here
            debug.log("WARNING: Asset type {} has no API POST options no pre-checks can be performed".format(
                asset_type
            ))
            API_POST_OPTIONS[asset_type] = None
        else:
            API_POST_OPTIONS[asset_type] = return_json["actions"]["POST"]

    return API_POST_OPTIONS[asset_type]
 def test_sync(self):
     """Establish that the sync method correctly forwards to the
     inventory source method, after getting the inventory source ID.
     """
     isrc = tower_cli.get_resource("inventory_source")
     with mock.patch.object(type(isrc), "update") as isrc_sync:
         with client.test_mode as t:
             t.register_json(
                 "/groups/1/",
                 {"id": 1, "name": "foo", "inventory": 1, "related": {"inventory_source": "/inventory_sources/42/"}},
                 method="GET",
             )
             self.gr.sync(1)
             isrc_sync.assert_called_once_with(42, monitor=False, timeout=None)
             self.assertEqual(len(t.requests), 1)
Beispiel #56
0
class TowerInventoryHost(TowerResource):
    res = tower_cli.get_resource('host')

    @classmethod
    def create(cls, **entries):
        """
        Create inventory host
        """
        return cls(**cls.res.create(**entries))

    def add_to_group(self, group_id):
        """
        Associate host to group
        """
        self.res.associate(self.id, group_id)
Beispiel #57
0
 def test_sync(self):
     """Establish that the sync method correctly forwards to the
     inventory source method, after getting the inventory source ID.
     """
     isrc = tower_cli.get_resource('inventory_source')
     with mock.patch.object(type(isrc), 'update') as isrc_sync:
         with client.test_mode as t:
             t.register_json('/groups/1/', {
                 'id': 1, 'name': 'foo', 'inventory': 1,
                 'related': {'inventory_source': '/inventory_sources/42/'},
             }, method='GET')
             self.gr.sync(1)
             isrc_sync.assert_called_once_with(42, monitor=False,
                                                   timeout=None)
             self.assertEqual(len(t.requests), 1)
Beispiel #58
0
def get_api_options(asset_type):
    if asset_type not in API_POST_OPTIONS:
        endpoint = tower_cli.get_resource(asset_type).endpoint
        response = client.options(endpoint)
        return_json = response.json()
        if "actions" not in return_json or "POST" not in return_json["actions"]:
            # Maybe we want to do a debug.log here
            debug.log(
                "WARNING: Asset type {} has no API POST options no pre-checks can be performed"
                .format(asset_type))
            API_POST_OPTIONS[asset_type] = None
        else:
            API_POST_OPTIONS[asset_type] = return_json["actions"]["POST"]

    return API_POST_OPTIONS[asset_type]
Beispiel #59
0
    def create(self, fail_on_found=False, force_on_exists=False, **kwargs):
        """Create a notification template.

        All required configuration-related fields (required according to
        notification_type) must be provided.

        There are two types of notification template creation: isolatedly
        creating a new notification template and creating a new notification
        template under a job template. Here the two types are discriminated by
        whether to provide --job-template option. --status option controls
        more specific, job-run-status-related association.

        Fields in the resource's `identity` tuple are used for a lookup;
        if a match is found, then no-op (unless `force_on_exists` is set) but
        do not fail (unless `fail_on_found` is set).
        """
        config_item = self._separate(kwargs)
        jt_id = kwargs.pop('job_template', None)
        status = kwargs.pop('status', 'any')
        old_endpoint = self.endpoint
        if jt_id is not None:
            jt = get_resource('job_template')
            jt.get(pk=jt_id)
            try:
                nt_id = self.get(**copy.deepcopy(kwargs))['id']
            except exc.NotFound:
                pass
            else:
                if fail_on_found:
                    raise exc.TowerCLIError('Notification template already '
                                            'exists and fail-on-found is '
                                            'switched on. Please use'
                                            ' "associate_notification" method'
                                            ' of job_template instead.')
                else:
                    debug.log(
                        'Notification template already exists, '
                        'associating with job template.',
                        header='details')
                    return jt.associate_notification(jt_id,
                                                     nt_id,
                                                     status=status)
            self.endpoint = '/job_templates/%d/notification_templates_%s/' %\
                            (jt_id, status)
        self._configuration(kwargs, config_item)
        result = super(Resource, self).create(**kwargs)
        self.endpoint = old_endpoint
        return result