def set_at_job_template_id(context: dict, job_template_name: str): with at_settings.runtime_values(**AT_CONFIG): res = at_get_resource('job_template') job_template_info = res.get(name=job_template_name) assert job_template_name in job_template_info['name'], \ f'Job template {job_template_name}: not found in Ansible Tower.\nResponse from server: {job_template_info}.' context['job_template_id'] = job_template_info['id']
def test_http_contradiction_error(self): """Establish that commands can not be ran with verify_ssl set to false and an http connection.""" with settings.runtime_values( host='http://33.33.33.33', verify_ssl=True): with self.assertRaises(exc.TowerCLIError): client.get_prefix()
def assert_at_group_exists_in_inventory(group_id: str): with at_settings.runtime_values(**AT_CONFIG): res = at_get_resource('group') pk = group_id find_group = res.get(pk=pk) assert find_group['id'] == pk, \ f'Group with id: {pk} not found in Ansible Tower. Response from server: {find_group}.'
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)
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 test_basic_launch_with_echo(self): """Establish that we are able to run an ad hoc command and also print that to the command line without errors. """ with client.test_mode as t: t.register_json('/ad_hoc_commands/42/', {'id': 42}, method='GET') t.register_json('/', { 'ad_hoc_commands': '/api/v1/ad_hoc_commands/' }, method='GET') t.register_json( '/ad_hoc_commands/', {'changed': True, 'id': 42, 'inventory': 'foobar', 'credential': 2, 'name': 'ping', 'created': 1234, 'elapsed': 2352, 'status': 'successful', 'module_name': 'command', 'limit': '', }, method='POST' ) result = self.res.launch(inventory="foobar", machine_credential=2) self.assertEqual(result['changed'], True) self.assertEqual(result['id'], 42) f = self.res.as_command()._echo_method(self.res.launch) with mock.patch.object(click, 'secho'): with settings.runtime_values(format='human'): f(inventory="foobar", machine_credential=2)
def delete_ansible_tower_group_credential(feature): """ Cleaning on the AT server after passing tests. Removal: group, credential, inventory. """ provision_feature_list = [ 'Linux server provision with chef and ansible tower', 'Windows server provision with chef and ansible tower' ] if feature.name in provision_feature_list: credentials_name = 'Revizor-windows-cred' if CONF.feature.dist.is_windows else 'Revizor-linux-cred' with at_settings.runtime_values(**at_config): res = at_get_resource('credential') pk = getattr(world, 'at_cred_primary_key_%s' % credentials_name) result = res.delete(pk=pk) assert result['changed'], ( 'Credentials with name %s are not deleted from the AT server' % credentials_name) LOG.error('Credentials: %s with the id: %s were not removed from the AT server' % ( credentials_name, pk)) res = at_get_resource('group') at_group_id = getattr(world, 'at_group_id') result = res.delete(pk=at_group_id) assert result['changed'], ('Group with id: %s is not deleted from the AT server' % at_group_id) LOG.error('Group with id: %s is not deleted from the AT server' % at_group_id) res = at_get_resource('inventory') inventory_id = getattr(world, 'at_inventory_id') result = res.delete(pk=inventory_id) assert result['changed'], ('Inventory with id: %s is not deleted from the AT server' % inventory_id) LOG.error('Inventory with id: %s is not deleted from the AT server' % inventory_id)
def launch_ansible_tower_job(step, job_name, credentials_name, job_result, serv_as): # NOTE: Migrated inventory_id = getattr(world, 'at_inventory_id') pk = getattr(world, 'at_cred_primary_key_%s' % credentials_name) at_python_path = '' if not CONF.feature.dist.is_windows: at_python_path = getattr(world, 'at_python_path') with at_settings.runtime_values(**at_config): res = at_get_resource('job') job_settings = { "credential_id": pk, "extra_credentials": [], "extra_vars": [at_python_path], "inventory": inventory_id } my_job = res.launch(job_template=job_name, monitor=False, wait=True, timeout=None, no_input=True, **job_settings) for _ in range(10): job_info = res.get(pk=my_job['id']) if job_info['status'] not in ['waiting', 'running', 'pending']: break time.sleep(5) else: raise AssertionError('Job #%s has not finished in 50s' % my_job['id']) assert job_info['status'] == job_result, (my_job['id'], job_info['status'])
def check_hostname_exists_on_at_server(step, serv_as, negation): # NOTE: Migrated """ You can search server name by: Public IP or Private IP or Hostname. Check what value is in defaults! If value is Hostname, then hostname = world.get_hostname_by_server_format(server) """ server = getattr(world, serv_as) hostname = server.public_ip with at_settings.runtime_values(**at_config): res = at_get_resource('host') hosts_list = res.list(group=None, host_filter=None) for m in hosts_list['results']: if negation: if hostname not in m['name']: break raise AssertionError( 'Hostname: %s was not removed from Ansible Tower server.' % hostname) elif hostname in m['name']: break else: if len(hosts_list['results']) == 10: raise AssertionError( 'License count of 10 instances has been reached. Number of hosts: %s .' % ( len(hosts_list['results']))) raise AssertionError( 'Hostname: %s not found in Ansible Tower server.' % hostname)
def launch_ansible_tower_job(context: dict, job_name: str, job_result: str): inventory_id = context['at_inventory_id'] credentials_name = context['credentials_name'] pk = context[f'at_cred_primary_key_{credentials_name}'] at_python_path = '' if not CONF.feature.dist.is_windows: at_python_path = context['at_python_path'] with at_settings.runtime_values(**AT_CONFIG): res = at_get_resource('job') job_settings = { "credential_id": pk, "extra_credentials": [], "extra_vars": [at_python_path], "inventory": inventory_id } my_job = res.launch(job_template=job_name, monitor=False, wait=True, timeout=None, no_input=True, **job_settings) for _ in range(10): job_info = res.get(pk=my_job['id']) if job_info['status'] not in ['waiting', 'running', 'pending']: break time.sleep(5) else: raise AssertionError(f"Job #{my_job['id']} has not finished in 50s") assert job_info['status'] == job_result, (my_job['id'], job_info['status'])
def test_color_false(self): """Establish that when the color setting is false, that color data is stripped. """ with settings.runtime_values(color=False): with mock.patch.object(click, 'secho') as click_secho: secho('foo bar baz', fg='green') click_secho.assert_called_once_with('foo bar baz')
def test_echo_id(self): for input_format in [{'id': 5}, {'count': 1, 'results': [{'id': 5}]}]: func = self.command._echo_method(lambda: input_format) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='id'): func() output = secho.mock_calls[-1][1][0] self.assertEqual('5', output)
def test_oauth_bearer_token(self): token = 'Azly3WBiYWeGKfImK25ftpJR1nvn6JABC123' with settings.runtime_values(oauth_token=token): auth = BasicTowerAuth(None, None, client) auth(self.req) assert self.req.headers == { 'Authorization': 'Bearer {}'.format(token) }
def test_not_verbose_mode(self): """Establish that this method does nothing if we are not in verbose mode. """ with settings.runtime_values(verbose=False): with mock.patch.object(click, 'secho') as secho: debug.log('foo bar baz') self.assertEqual(secho.call_count, 0)
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.pop('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)
def create_repo_and_project(token, tower_host, tower_user, tower_pass, cred_id, yml_file, org_name, repo_name): github_client = Github(token) org = github_client.get_organization(org_name) new_repo = org.create_repo(repo_name, repo_name) # Create objects and directories new_repo.create_file( "default/ ", "default file", "", ) new_repo.create_file("task/ ", "task file", "") new_repo.create_file("var/ ", "var file", "") with open(yml_file, "rb") as default_file: encoded_string = default_file.read() new_repo.create_file(yml_file, "yml file ", encoded_string) print("Repo Cretaed!") with settings.runtime_values(username=tower_user, password=tower_pass, host=tower_host, verify_ssl=False): try: org_res = get_resource('organization') cred_res = get_resource('credential') proj_res = get_resource('project') proj_update_resource = get_resource('project_update') org = org_res.get(org_name) cred = cred_res.get(pk=cred_id) scm_url = "https://github.com/{}/{}.git".format( org_name, repo_name) args = { 'name': repo_name, 'desc': repo_name, 'organization': org['id'], 'scm_credential': cred_id, 'scm_branch': 'master', 'scm_type': 'git', 'scm_url': scm_url } proj = proj_res.create(**args) print("Project Created!!") except Exception, e: print('Failed with Error: {} '.format(str(e)))
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)
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 test_color_false(self): """Establish that when the color setting is false, that color data is stripped. """ with settings.runtime_values(color=True): with mock.patch.object(click, 'secho') as click_secho: secho('foo bar baz', fg='green') click_secho.assert_called_once_with('foo bar baz', color='green')
def test_connection_error(self): """Establish that if we get a ConnectionError back from requests, that we deal with it nicely. """ with settings.runtime_values(verbose=False): with mock.patch.object(Session, 'request') as req: req.side_effect = requests.exceptions.ConnectionError with self.assertRaises(exc.ConnectionError): r = client.get('/ping/')
def test_key_and_no_value(self): """Establish that if we are given a key and no value, that the setting's value is printed. """ with settings.runtime_values(password='******'): result = self.runner.invoke(config, ['password']) self.assertEqual(result.exit_code, 0) self.assertEqual(result.output.strip(), 'password: This is the best wine.')
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)
def test_auth_token_unsupported(self): # If the user specifies `use_token=True`, but `/authtoken/` doesn't # exist (in Tower 3.3 and beyond), just fall back to basic auth with client.test_mode as t: with settings.runtime_values(use_token=True): t.register('/authtoken/', json.dumps({}), status_code=404, method='OPTIONS') auth = BasicTowerAuth('alice', 'pass', client) auth(self.req) assert self.req.headers == {'Authorization': 'Basic YWxpY2U6cGFzcw=='}
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. if PY2: outfile = getwriter('utf-8')(StringIO()) else: 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={0} failed, error: {1}'.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)
def setUp(self): class Req(object): def __init__(self): self.headers = {} with settings.runtime_values(use_token=True): self.auth = BasicTowerAuth('alice', 'pass', client) self.req = Req() self.expires = dt.utcnow()
def test_echo_method(self): """Establish that the _echo_method subcommand class works in the way we expect. """ func = self.command._echo_method(lambda: {'foo': 'bar'}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='json'): func() secho.assert_called_once_with(json.dumps({'foo': 'bar'}, indent=2))
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)
def test_echo_method_human_formatted_no_records(self): """Establish that if there are no records sent to the human formatter, that it prints a terse message to that effect. """ func = self.command._echo_method(lambda: {'results': []}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='human'): func() output = secho.mock_calls[-1][1][0] self.assertEqual(output, 'No records found.')
def test_echo_method_human_formatted_changed(self): """Establish that if there is a change and no id is returned, we print a generic OK message. """ func = self.command._echo_method(lambda: {'changed': False}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='human'): func() output = secho.mock_calls[-1][1][0] self.assertEqual(output, 'OK. (changed: false)')
def test_echo_method_changed_true(self): """Establish that the _echo_method subcommand decorator works in the way we expect if we get an changed designation. """ func = self.command._echo_method(lambda: {'changed': True}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='json', color=True): func() answer = json.dumps({'changed': True}, indent=2) secho.assert_called_once_with(answer, fg='yellow')
def test_ignored_fields(self): """Establish that if ignored_fields is returned when launching job, it will be displayed in verbose mode. """ echo_count_with_ignore = 0 echo_count = 0 with client.test_mode as t: standard_registration(t) with settings.runtime_values(verbose=True): with mock.patch.object(click, 'secho') as secho: self.res.launch(job_template=1) echo_count = secho.call_count with client.test_mode as t: standard_registration(t, ignored_fields={'foo': 'bar'}) with settings.runtime_values(verbose=True): with mock.patch.object(click, 'secho') as secho: self.res.launch(job_template=1) echo_count_with_ignore = secho.call_count self.assertEqual(echo_count_with_ignore - echo_count, 2)
def answer(*inner_a, **inner_kw): runtime_settings = { 'host': inner_kw.pop('tower_host', None), 'password': inner_kw.pop('tower_password', None), 'format': inner_kw.pop('format', None), 'username': inner_kw.pop('tower_username', None), 'verbose': inner_kw.pop('verbose', None), } with settings.runtime_values(**runtime_settings): return method(*inner_a, **inner_kw)
def test_failed_suggestion_protocol(self): """Establish that if connection fails and protocol not given, tower-cli suggests that to the user.""" with settings.runtime_values(verbose=False, host='foo.co'): with mock.patch.object(Session, 'request') as req: req.side_effect = requests.exceptions.SSLError with mock.patch.object(click, 'secho') as secho: with self.assertRaises(exc.ConnectionError): client.get('/ping/') self.assertTrue(secho.called)
def test_connection_ssl_error(self): """Establish that if we get a ConnectionError or an SSLError back from requests, that we deal with it nicely. """ for ErrorType in REQUESTS_ERRORS: with settings.runtime_values(verbose=False, host='https://foo.co'): with mock.patch.object(Session, 'request') as req: req.side_effect = ErrorType with self.assertRaises(exc.ConnectionError): client.get('/ping/')
def test_get_user(self): """Assure that super method is called with right parameters""" with mock.patch( 'tower_cli.models.base.ResourceMethods.read') as mock_read: mock_read.return_value = {'results': [copy(example_role_data)]} with settings.runtime_values(format='human'): self.res.get(user=1) mock_read.assert_called_once_with( fail_on_multiple_results=True, fail_on_no_results=True, members__in=1, pk=None)
def test_echo_method_human_formatted_single_result(self): """Establish that a single result sent to the human formatter shows a table with a single row as expected. """ f = self.command._echo_method(lambda: {'id': 1, 'name': 'Durham, NC'}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='human'): f() output = secho.mock_calls[-1][1][0] self.assertIn('1 Durham, NC', output)
def test_extra_newlines(self): """Establish that extra newlines are correctly applied if they are requested. """ s = 'All your base are belong to us.' with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(verbose=True): debug.log(s, nl=3) self.assertEqual(secho.mock_calls[0][1][0], 'All your base are belong to us.\n\n')
def test_failed_suggestion_protocol(self): """Establish that if connection fails and protocol not given, tower-cli suggests that to the user.""" with settings.runtime_values(verbose=False, host='foo.co'): with mock.patch.object(Session, 'request') as req: req.side_effect = requests.exceptions.SSLError with mock.patch.object(click, 'secho') as secho: with self.assertRaises(exc.ConnectionError): client.get('/ping/') secho.assert_called()
def main(): argument_spec = dict( name=dict(required=True), description=dict(), organization=dict(required=True), variables=dict(), kind=dict(choices=['', 'smart'], default=''), host_filter=dict(), state=dict(choices=['present', 'absent'], default='present'), ) module = TowerModule(argument_spec=argument_spec, supports_check_mode=True) name = module.params.get('name') description = module.params.get('description') organization = module.params.get('organization') variables = module.params.get('variables') state = module.params.get('state') kind = module.params.get('kind') host_filter = module.params.get('host_filter') json_output = {'inventory': name, 'state': state} tower_auth = tower_auth_config(module) with settings.runtime_values(**tower_auth): tower_check_mode(module) inventory = tower_cli.get_resource('inventory') try: org_res = tower_cli.get_resource('organization') org = org_res.get(name=organization) if state == 'present': result = inventory.modify(name=name, organization=org['id'], variables=variables, description=description, kind=kind, host_filter=host_filter, create_on_missing=True) json_output['id'] = result['id'] elif state == 'absent': result = inventory.delete(name=name, organization=org['id']) except (exc.NotFound) as excinfo: module.fail_json( msg='Failed to update inventory, organization not found: {0}'. format(excinfo), changed=False) except (exc.ConnectionError, exc.BadRequest, exc.AuthError) as excinfo: module.fail_json( msg='Failed to update inventory: {0}'.format(excinfo), changed=False) json_output['changed'] = result['changed'] module.exit_json(**json_output)
def test_echo_setting(self): """Establish that the `echo_setting` method works in the way that we expect. """ with settings.runtime_values(host='20.12.4.21'): with mock.patch.object(click, 'secho') as secho: _echo_setting('host') self.assertEqual(secho.mock_calls, [ mock.call('host: ', fg='magenta', bold=True, nl=False), mock.call('20.12.4.21', fg='white', bold=True), ])
def test_get_user(self): """Assure that super method is called with right parameters""" with mock.patch( 'tower_cli.models.base.BaseResource.read') as mock_read: mock_read.return_value = {'results': [copy(example_role_data)]} with settings.runtime_values(format='human'): self.res.get(user=1) mock_read.assert_called_once_with(fail_on_multiple_results=True, fail_on_no_results=True, members__in=1, pk=None)
def test_header(self): """Establish that a header echoes the expected string, of correct length. """ s = 'Decided all the things.' with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(verbose=True): debug.log(s, header='decision', fg='blue') self.assertEqual(secho.mock_calls[0][1][0], '*** DECISION: Decided all the things. ' '*****************************************')
def test_echo_method_human_custom_output(self): """Establish that a custom dictionary with no ID is made into a table and printed as expected. """ func = self.command._echo_method(lambda: adict(foo='bar', spam='eggs')) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='human'): func() output = secho.mock_calls[-1][1][0] self.assertIn('foo spam', output) self.assertIn('bar eggs', output)
def test_connection_error_verbose(self): """Establish that if we get a ConnectionError back from requests, that we deal with it nicely, and additionally print the internal error if verbose is True. """ with settings.runtime_values(verbose=True): with mock.patch.object(Session, 'request') as req: req.side_effect = requests.exceptions.ConnectionError with mock.patch.object(debug, 'log') as dlog: with self.assertRaises(exc.ConnectionError): r = client.get('/ping/') self.assertEqual(dlog.call_count, 5)
def test_echo_method_human_pagination_last_page(self): """Establish that pagination works in human formatting, and it prints the way we expect on the final page.. """ func = self.command._echo_method(lambda: {'results': [ {'id': 1, 'name': 'Durham, NC'}, ], 'next': None, 'count': 3, 'previous': 1}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='human'): func() output = secho.mock_calls[-1][1][0] self.assertIn('(Page 2 of 2.)', output)
def test_echo_method_yaml_formatted(self): """Establish that the `_echo_method` properly returns YAML formatting when it gets back a list of objects. """ func = self.command._echo_method(lambda: {'foo': 'bar'}) with mock.patch.object(click, 'secho') as secho: with settings.runtime_values(format='yaml'): func() secho.assert_called_once_with(yaml.safe_dump({'foo': 'bar'}, indent=2, allow_unicode=True, default_flow_style=False))