Cherry pick Tower credential fixes to stable-2.4 (#36807)

* Fix credentials for Tower API V2

(cherry picked from commit 640749d54f)

* tower cred: implement credential /api/v1/ kind compatability

(cherry picked from commit 9cb4b70e27)

* tower cred: filter user name lookup by the proper key

(cherry picked from commit cd6855275e)

* tower cred: update kind options in documentation

(cherry picked from commit 8a41233202)

* tower cred: support credential kind/type for /api/v1/ and /api/v2/ (#36662)

older versions of Tower (3.1) don't have a concept of CredentialTypes
(this was introduced in Tower 3.2).  This change detects older versions
of pre-3.2 tower-cli that *only* support the deprecated `kind`
attribute.

(cherry picked from commit 641f8b4ef6)

* Add CHANGELOG entry for Ansible Tower module credential fix

* properly detect the absence of credential_type in older tower-cli (#36908)

(cherry picked from commit a82043939b)

* Do not import HAS_TOWER_CLI since it does not exist in stable-2.4

* properly pass /api/v1/ credential fields for older Towers (#36917)

(cherry picked from commit 0e7106b106)
This commit is contained in:
Sam Doran 2018-03-01 15:54:15 -05:00 committed by GitHub
parent 0d57282a1a
commit 47eccd366b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 116 additions and 45 deletions

View file

@ -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>

View file

@ -54,7 +54,7 @@ options:
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.
@ -190,56 +190,89 @@ EXAMPLES = '''
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')
@ -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)