Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry pick Tower credential fixes to stable-2.4 #36807

Merged
merged 9 commits into from
Mar 1, 2018
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ Ansible Changes By Release
https://github.com/ansible/ansible/pull/36124
* fix debug output
https://github.com/ansible/ansible/pull/36307
* Fix credentials for Ansible Tower modules to work with v1 and v2 of the API
(https://github.com/ansible/ansible/pull/36587)
(https://github.com/ansible/ansible/pull/36662)


<a id="2.4.3"></a>

Expand Down
157 changes: 112 additions & 45 deletions lib/ansible/modules/web_infrastructure/ansible_tower/tower_credential.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
description:
- Type of credential being added.
required: True
choices: ["ssh", "net", "scm", "aws", "rax", "vmware", "satellite6", "cloudforms", "gce", "azure", "azure_rm", "openstack"]
choices: ["ssh", "vault", "net", "scm", "aws", "vmware", "satellite6", "cloudforms", "gce", "azure_rm", "openstack", "rhv", "insights", "tower"]
host:
description:
- Host for this credential.
Expand Down Expand Up @@ -190,56 +190,89 @@
tower_config_file: "~/tower_cli.cfg"
'''

import os

from ansible.module_utils.ansible_tower import tower_argument_spec, tower_auth_config, tower_check_mode

try:
import os
import tower_cli
import tower_cli.utils.exceptions as exc

from tower_cli.conf import settings
from ansible.module_utils.ansible_tower import tower_auth_config, tower_check_mode

HAS_TOWER_CLI = True
except ImportError:
HAS_TOWER_CLI = False


KIND_CHOICES = {
'ssh': 'Machine',
'vault': 'Ansible Vault',
'net': 'Network',
'scm': 'Source Control',
'aws': 'Amazon Web Services',
'vmware': 'VMware vCenter',
'satellite6': 'Red Hat Satellite 6',
'cloudforms': 'Red Hat CloudForms',
'gce': 'Google Compute Engine',
'azure_rm': 'Microsoft Azure Resource Manager',
'openstack': 'OpenStack',
'rhv': 'Red Hat Virtualization',
'insights': 'Insights',
'tower': 'Ansible Tower',
}


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)


def main():
module = AnsibleModule(
argument_spec=dict(
name=dict(required=True),
user=dict(),
team=dict(),
kind=dict(required=True,
choices=["ssh", "net", "scm", "aws", "rax", "vmware", "satellite6",
"cloudforms", "gce", "azure", "azure_rm", "openstack"]),
host=dict(),
username=dict(),
password=dict(no_log=True),
ssh_key_data=dict(no_log=True),
ssh_key_unlock=dict(no_log=True),
authorize=dict(type='bool', default=False),
authorize_password=dict(no_log=True),
client=dict(),
secret=dict(),
tenant=dict(),
subscription=dict(),
domain=dict(),
become_method=dict(),
become_username=dict(),
become_password=dict(no_log=True),
vault_password=dict(no_log=True),
description=dict(),
organization=dict(required=True),
project=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
)

argument_spec = tower_argument_spec()
argument_spec.update(dict(
name=dict(required=True),
user=dict(),
team=dict(),
kind=dict(required=True,
choices=KIND_CHOICES.keys()),
host=dict(),
username=dict(),
password=dict(no_log=True),
ssh_key_data=dict(no_log=True, type='path'),
ssh_key_unlock=dict(no_log=True),
authorize=dict(type='bool', default=False),
authorize_password=dict(no_log=True),
client=dict(),
secret=dict(),
tenant=dict(),
subscription=dict(),
domain=dict(),
become_method=dict(),
become_username=dict(),
become_password=dict(no_log=True),
vault_password=dict(no_log=True),
description=dict(),
organization=dict(required=True),
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')
Expand All @@ -255,23 +288,57 @@ def main():
tower_check_mode(module)
credential = tower_cli.get_resource('credential')
try:
params = module.params.copy()
params = {}
params['create_on_missing'] = True
params['name'] = name

if organization:
org_res = tower_cli.get_resource('organization')
org = org_res.get(name=organization)
params['organization'] = org['id']

if params['ssh_key_data']:
filename = params['ssh_key_data']
filename = os.path.expanduser(filename)
try:
tower_cli.get_resource('credential_type')
except (ImportError, AttributeError):
# /api/v1/ backwards compat
# older versions of tower-cli don't *have* a credential_type
# resource
params['kind'] = module.params['kind']
else:
credential_type = credential_type_for_v1_kind(module.params, module)
params['credential_type'] = credential_type['id']

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

if module.params.get('user'):
user_res = tower_cli.get_resource('user')
user = user_res.get(username=module.params.get('user'))
params['user'] = user['id']

if module.params.get('team'):
team_res = tower_cli.get_resource('team')
team = team_res.get(name=module.params.get('team'))
params['team'] = team['id']

if module.params.get('ssh_key_data'):
filename = module.params.get('ssh_key_data')
if not os.path.exists(filename):
module.fail_json(msg='file not found: %s' % filename)
if os.path.isdir(filename):
module.fail_json(msg='attempted to read contents of directory: %s' % filename)
with open(filename, 'rb') as f:
params['ssh_key_data'] = f.read()
module.params['ssh_key_data'] = f.read()

for key in ('authorize', 'authorize_password', 'client', 'secret',
'tenant', 'subscription', 'domain', 'become_method',
'become_username', 'become_password', 'vault_password',
'project', 'host', 'username', 'password',
'ssh_key_data', 'ssh_key_unlock'):
if 'kind' in params:
params[key] = module.params.get(key)
elif module.params.get(key):
params.setdefault('inputs', {})[key] = module.params.get(key)

if state == 'present':
result = credential.modify(**params)
Expand Down