1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-31 23:51:09 +03:00

Merge pull request #3257 from ryanpetrello/native_credential_types

define native CredentialType inputs/injectors in code, not in the DB

Reviewed-by: https://github.com/softwarefactory-project-zuul[bot]
This commit is contained in:
softwarefactory-project-zuul[bot] 2019-02-19 17:27:19 +00:00 committed by GitHub
commit 1ece764547
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 611 additions and 664 deletions

View File

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.16 on 2019-02-19 04:27
from __future__ import unicode_literals
from django.db import migrations, models
from awx.main.models import CredentialType
def migrate_to_static_inputs(apps, schema_editor):
CredentialType.setup_tower_managed_defaults()
class Migration(migrations.Migration):
dependencies = [
('main', '0060_v350_update_schedule_uniqueness_constraint'),
]
operations = [
migrations.AddField(
model_name='credentialtype',
name='namespace',
field=models.CharField(default=None, editable=False, max_length=1024, null=True),
),
migrations.RunPython(migrate_to_static_inputs)
]

View File

@ -62,155 +62,40 @@ def _disassociate_non_insights_projects(apps, cred):
def migrate_to_v2_credentials(apps, schema_editor):
CredentialType.setup_tower_managed_defaults()
deprecated_cred = _generate_deprecated_cred_types()
# this monkey-patch is necessary to make the implicit role generation save
# signal use the correct Role model (the version active at this point in
# migration, not the one at HEAD)
orig_current_apps = utils.get_current_apps
try:
utils.get_current_apps = lambda: apps
for cred in apps.get_model('main', 'Credential').objects.all():
job_templates = cred.jobtemplates.all()
jobs = cred.jobs.all()
data = {}
if getattr(cred, 'vault_password', None):
data['vault_password'] = cred.vault_password
if _is_insights_scm(apps, cred):
_disassociate_non_insights_projects(apps, cred)
credential_type = _get_insights_credential_type()
else:
credential_type = _populate_deprecated_cred_types(deprecated_cred, cred.kind) or CredentialType.from_v1_kind(cred.kind, data)
defined_fields = credential_type.defined_fields
cred.credential_type = apps.get_model('main', 'CredentialType').objects.get(pk=credential_type.pk)
for field in defined_fields:
if getattr(cred, field, None):
cred.inputs[field] = getattr(cred, field)
if cred.vault_password:
for jt in job_templates:
jt.credential = None
jt.vault_credential = cred
jt.save()
for job in jobs:
job.credential = None
job.vault_credential = cred
job.save()
if data.get('is_insights', False):
cred.kind = 'insights'
cred.save()
#
# If the credential contains a vault password, create a new
# *additional* credential for the ssh details
#
if cred.vault_password:
# We need to make an ssh credential, too
ssh_type = CredentialType.from_v1_kind('ssh')
new_cred = apps.get_model('main', 'Credential').objects.get(pk=cred.pk)
new_cred.pk = None
new_cred.vault_password = ''
new_cred.credential_type = apps.get_model('main', 'CredentialType').objects.get(pk=ssh_type.pk)
if 'vault_password' in new_cred.inputs:
del new_cred.inputs['vault_password']
# unset these attributes so that new roles are properly created
# at save time
new_cred.read_role = None
new_cred.admin_role = None
new_cred.use_role = None
if any([getattr(cred, field) for field in ssh_type.defined_fields]):
new_cred.save(force_insert=True)
# copy rbac roles
for role_type in ('read_role', 'admin_role', 'use_role'):
for member in getattr(cred, role_type).members.all():
getattr(new_cred, role_type).members.add(member)
for role in getattr(cred, role_type).parents.all():
getattr(new_cred, role_type).parents.add(role)
for jt in job_templates:
jt.credential = new_cred
jt.save()
for job in jobs:
job.credential = new_cred
job.save()
# passwords must be decrypted and re-encrypted, because
# their encryption is based on the Credential's primary key
# (which has changed)
for field in ssh_type.defined_fields:
if field in ssh_type.secret_fields:
value = decrypt_field(cred, field)
if value:
setattr(new_cred, field, value)
new_cred.inputs[field] = encrypt_field(new_cred, field)
setattr(new_cred, field, '')
elif getattr(cred, field):
new_cred.inputs[field] = getattr(cred, field)
new_cred.save()
finally:
utils.get_current_apps = orig_current_apps
# TODO: remove once legacy/EOL'd Towers no longer support this upgrade path
pass
def migrate_job_credentials(apps, schema_editor):
# this monkey-patch is necessary to make the implicit role generation save
# signal use the correct Role model (the version active at this point in
# migration, not the one at HEAD)
orig_current_apps = utils.get_current_apps
try:
utils.get_current_apps = lambda: apps
for type_ in ('Job', 'JobTemplate'):
for obj in apps.get_model('main', type_).objects.all():
if obj.cloud_credential:
obj.extra_credentials.add(obj.cloud_credential)
if obj.network_credential:
obj.extra_credentials.add(obj.network_credential)
obj.save()
finally:
utils.get_current_apps = orig_current_apps
# TODO: remove once legacy/EOL'd Towers no longer support this upgrade path
pass
def add_vault_id_field(apps, schema_editor):
vault_credtype = CredentialType.objects.get(kind='vault')
vault_credtype.inputs = CredentialType.defaults.get('vault')().inputs
vault_credtype.save()
# this is no longer necessary; schemas are defined in code
pass
def remove_vault_id_field(apps, schema_editor):
vault_credtype = CredentialType.objects.get(kind='vault')
idx = 0
for i, input in enumerate(vault_credtype.inputs['fields']):
if input['id'] == 'vault_id':
idx = i
break
vault_credtype.inputs['fields'].pop(idx)
vault_credtype.save()
# this is no longer necessary; schemas are defined in code
pass
def create_rhv_tower_credtype(apps, schema_editor):
CredentialType.setup_tower_managed_defaults()
# this is no longer necessary; schemas are defined in code
pass
def add_tower_verify_field(apps, schema_editor):
tower_credtype = CredentialType.objects.get(
kind='cloud', name='Ansible Tower', managed_by_tower=True
)
tower_credtype.inputs = CredentialType.defaults.get('tower')().inputs
tower_credtype.save()
# this is no longer necessary; schemas are defined in code
pass
def add_azure_cloud_environment_field(apps, schema_editor):
azure_rm_credtype = CredentialType.objects.get(kind='cloud',
name='Microsoft Azure Resource Manager')
azure_rm_credtype.inputs = CredentialType.defaults.get('azure_rm')().inputs
azure_rm_credtype.save()
# this is no longer necessary; schemas are defined in code
pass
def remove_become_methods(apps, schema_editor):
become_credtype = CredentialType.objects.filter(kind='ssh', managed_by_tower=True).first()
become_credtype.inputs = CredentialType.defaults.get('ssh')().inputs
become_credtype.save()
# this is no longer necessary; schemas are defined in code
pass

View File

@ -16,7 +16,7 @@ from awx.main.models.organization import ( # noqa
Organization, Profile, Team, UserSessionMembership
)
from awx.main.models.credential import ( # noqa
Credential, CredentialType, V1Credential, build_safe_env
Credential, CredentialType, ManagedCredentialType, V1Credential, build_safe_env
)
from awx.main.models.projects import Project, ProjectUpdate # noqa
from awx.main.models.inventory import ( # noqa

File diff suppressed because it is too large Load Diff

View File

@ -47,7 +47,7 @@ __all__ = ['get_object_or_400', 'camelcase_to_underscore', 'memoize', 'memoize_d
'wrap_args_with_proot', 'build_proot_temp_dir', 'check_proot_installed', 'model_to_dict',
'model_instance_diff', 'timestamp_apiformat', 'parse_yaml_or_json', 'RequireDebugTrueOrTest',
'has_model_field_prefetched', 'set_environ', 'IllegalArgumentError', 'get_custom_venv_choices', 'get_external_account',
'task_manager_bulk_reschedule', 'schedule_task_manager']
'task_manager_bulk_reschedule', 'schedule_task_manager', 'classproperty']
def get_object_or_400(klass, *args, **kwargs):
@ -1113,3 +1113,17 @@ def get_external_account(user):
getattr(settings, 'TACACSPLUS_HOST', None)) and user.enterprise_auth.all():
account_type = "enterprise"
return account_type
class classproperty:
def __init__(self, fget=None, fset=None, fdel=None, doc=None):
self.fget = fget
self.fset = fset
self.fdel = fdel
if doc is None and fget is not None:
doc = fget.__doc__
self.__doc__ = doc
def __get__(self, instance, ownerclass):
return self.fget(ownerclass)