Adding OpenStack v3 cred type

This commit is contained in:
AlanCoding
2016-03-16 15:32:05 -04:00
parent c807d5dcf3
commit f4b1de766d
12 changed files with 114 additions and 22 deletions

View File

@@ -1,5 +1,5 @@
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.
CLOUD_PROVIDERS = ('azure', 'ec2', 'gce', 'rax', 'vmware', 'openstack')
CLOUD_PROVIDERS = ('azure', 'ec2', 'gce', 'rax', 'vmware', 'openstack', 'openstack_v3')
SCHEDULEABLE_PROVIDERS = CLOUD_PROVIDERS + ('custom',)

View File

@@ -56,7 +56,7 @@ PERMISSION_TYPE_CHOICES = [
(PERM_JOBTEMPLATE_CREATE, _('Create a Job Template')),
]
CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure', 'openstack', 'custom']
CLOUD_INVENTORY_SOURCES = ['ec2', 'rax', 'vmware', 'gce', 'azure', 'openstack', 'openstack_v3', 'custom']
VERBOSITY_CHOICES = [
(0, '0 (Normal)'),

View File

@@ -34,6 +34,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
('gce', _('Google Compute Engine')),
('azure', _('Microsoft Azure')),
('openstack', _('OpenStack')),
('openstack_v3', _('OpenStack V3')),
]
BECOME_METHOD_CHOICES = [
@@ -210,10 +211,19 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
host = self.host or ''
if not host and self.kind == 'vmware':
raise ValidationError('Host required for VMware credential.')
if not host and self.kind == 'openstack':
if not host and self.kind in ('openstack', 'openstack_v3'):
raise ValidationError('Host required for OpenStack credential.')
return host
def clean_domain(self):
"""For case of Keystone v3 identity service that requires a
`domain`, that a domain is provided.
"""
domain = self.domain or ''
if not domain and self.kind == 'openstack_v3':
raise ValidationError('Domain required for OpenStack with Keystone v3.')
return domain
def clean_username(self):
username = self.username or ''
if not username and self.kind == 'aws':
@@ -223,7 +233,7 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
'credential.')
if not username and self.kind == 'vmware':
raise ValidationError('Username required for VMware credential.')
if not username and self.kind == 'openstack':
if not username and self.kind in ('openstack', 'openstack_v3'):
raise ValidationError('Username required for OpenStack credential.')
return username
@@ -235,13 +245,13 @@ class Credential(PasswordFieldsModel, CommonModelNameNotUnique):
raise ValidationError('API key required for Rackspace credential.')
if not password and self.kind == 'vmware':
raise ValidationError('Password required for VMware credential.')
if not password and self.kind == 'openstack':
if not password and self.kind in ('openstack', 'openstack_v3'):
raise ValidationError('Password or API key required for OpenStack credential.')
return password
def clean_project(self):
project = self.project or ''
if self.kind == 'openstack' and not project:
if self.kind in ('openstack', 'openstack_v3') and not project:
raise ValidationError('Project name required for OpenStack credential.')
return project

View File

@@ -748,6 +748,7 @@ class InventorySourceOptions(BaseModel):
('azure', _('Microsoft Azure')),
('vmware', _('VMware vCenter')),
('openstack', _('OpenStack')),
('openstack_v3', _('OpenStack V3')),
('custom', _('Custom Script')),
]
@@ -976,6 +977,11 @@ class InventorySourceOptions(BaseModel):
"""I don't think openstack has regions"""
return [('all', 'All')]
@classmethod
def get_openstack_v3_region_choices(self):
"""Defer to the behavior of openstack"""
return self.get_openstack_region_choices()
def clean_credential(self):
if not self.source:
return None

View File

@@ -706,7 +706,7 @@ class RunJob(BaseTask):
if credential.ssh_key_data not in (None, ''):
private_data[cred_name] = decrypt_field(credential, 'ssh_key_data') or ''
if job.cloud_credential and job.cloud_credential.kind == 'openstack':
if job.cloud_credential and job.cloud_credential.kind in ('openstack', 'openstack_v3'):
credential = job.cloud_credential
openstack_auth = dict(auth_url=credential.host,
username=credential.username,
@@ -798,7 +798,7 @@ class RunJob(BaseTask):
env['VMWARE_USER'] = cloud_cred.username
env['VMWARE_PASSWORD'] = decrypt_field(cloud_cred, 'password')
env['VMWARE_HOST'] = cloud_cred.host
elif cloud_cred and cloud_cred.kind == 'openstack':
elif cloud_cred and cloud_cred.kind in ('openstack', 'openstack_v3'):
env['OS_CLIENT_CONFIG_FILE'] = kwargs.get('private_data_files', {}).get('cloud_credential', '')
# Set environment variables related to scan jobs
@@ -1147,7 +1147,7 @@ class RunInventoryUpdate(BaseTask):
credential = inventory_update.credential
return dict(cloud_credential=decrypt_field(credential, 'ssh_key_data'))
if inventory_update.source == 'openstack':
if inventory_update.source in ('openstack', 'openstack_v3'):
credential = inventory_update.credential
openstack_auth = dict(auth_url=credential.host,
username=credential.username,
@@ -1302,7 +1302,7 @@ class RunInventoryUpdate(BaseTask):
env['GCE_PROJECT'] = passwords.get('source_project', '')
env['GCE_PEM_FILE_PATH'] = cloud_credential
env['GCE_ZONE'] = inventory_update.source_regions
elif inventory_update.source == 'openstack':
elif inventory_update.source in ('openstack', 'openstack_v3'):
env['OS_CLIENT_CONFIG_FILE'] = cloud_credential
elif inventory_update.source == 'file':
# FIXME: Parse source_env to dict, update env.
@@ -1345,6 +1345,11 @@ class RunInventoryUpdate(BaseTask):
# to a shorter variable. :)
src = inventory_update.source
# OpenStack V3 has everything in common with OpenStack aside
# from one extra parameter, so share these resources between them.
if src == 'openstack_v3':
src = 'openstack'
# Get the path to the inventory plugin, and append it to our
# arguments.
plugin_path = self.get_path_to('..', 'plugins', 'inventory',

View File

@@ -2078,13 +2078,13 @@ class InventoryUpdatesTest(BaseTransactionTest):
if not all([api_url, api_user, api_password, api_project, api_domain]):
self.skipTest("No test openstack v3 credentials defined")
self.create_test_license_file()
credential = Credential.objects.create(kind='openstack',
credential = Credential.objects.create(kind='openstack_v3',
host=api_url,
username=api_user,
password=api_password,
project=api_project,
domain=api_domain)
inventory_source = self.update_inventory_source(self.group, source='openstack', credential=credential)
inventory_source = self.update_inventory_source(self.group, source='openstack_v3', credential=credential)
self.check_inventory_source(inventory_source)
self.assertFalse(self.group.all_hosts.filter(instance_id='').exists())
@@ -2132,3 +2132,27 @@ class InventoryCredentialTest(BaseTest):
self.assertIn('password', response)
self.assertIn('host', response)
self.assertIn('project', response)
def test_openstack_v3_create_ok(self):
data = {
'kind': 'openstack_v3',
'name': 'Best credential ever',
'username': 'some_user',
'password': 'some_password',
'project': 'some_project',
'host': 'some_host',
'domain': 'some_domain',
}
self.post(self.url, data=data, expect=201, auth=self.get_super_credentials())
def test_openstack_v3_create_fail_required_fields(self):
data = {
'kind': 'openstack_v3',
'name': 'Best credential ever',
}
response = self.post(self.url, data=data, expect=400, auth=self.get_super_credentials())
self.assertIn('username', response)
self.assertIn('password', response)
self.assertIn('host', response)
self.assertIn('project', response)
self.assertIn('domain', response)