migrate insights credentials

* A credential is considered an insights credential if a project of
scm_type 'insights' is associated.
* all non-insights Projects that point at an insights credential are
nulled
This commit is contained in:
Chris Meyers 2017-05-26 08:45:35 -04:00
parent 87eea59845
commit 7c0513d5ee
3 changed files with 59 additions and 3 deletions

View File

@ -1,6 +1,7 @@
from awx.main import utils
from awx.main.models import CredentialType
from awx.main.utils.common import encrypt_field, decrypt_field
from django.db.models import Q
DEPRECATED_CRED_KIND = {
@ -48,6 +49,14 @@ def _populate_deprecated_cred_types(cred, kind):
return cred[kind]
def _is_insights_scm(apps, cred):
return apps.get_model('main', 'Credential').objects.filter(id=cred.id, projects__scm_type='insights').exists()
def _disassociate_non_insights_projects(apps, cred):
apps.get_model('main', 'Project').objects.filter(~Q(scm_type='insights') & Q(credential=cred)).update(credential=None)
def migrate_to_v2_credentials(apps, schema_editor):
CredentialType.setup_tower_managed_defaults()
deprecated_cred = _generate_deprecated_cred_types()
@ -64,7 +73,11 @@ def migrate_to_v2_credentials(apps, schema_editor):
data = {}
if getattr(cred, 'vault_password', None):
data['vault_password'] = cred.vault_password
if _is_insights_scm(apps, cred):
data['is_insights'] = True
_disassociate_non_insights_projects(apps, cred)
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)
@ -80,6 +93,8 @@ def migrate_to_v2_credentials(apps, schema_editor):
job.credential = None
job.vault_credential = cred
job.save()
if data.get('is_insights', False):
cred.kind = 'insights'
cred.save()
#
@ -145,3 +160,4 @@ def migrate_job_credentials(apps, schema_editor):
obj.save()
finally:
utils.get_current_apps = orig_current_apps

View File

@ -469,6 +469,8 @@ class CredentialType(CommonModelNameNotUnique):
requirements['kind'] = 'vault'
else:
requirements['kind'] = 'ssh'
elif kind == 'scm' and data.get('is_insights', False):
requirements['kind'] = 'insights'
elif kind in ('net', 'scm'):
requirements['kind'] = kind
elif kind in kind_choices:

View File

@ -8,6 +8,7 @@ from django.apps import apps
from awx.main.models import Credential, CredentialType
from awx.main.migrations._credentialtypes import migrate_to_v2_credentials
from awx.main.utils.common import decrypt_field
from awx.main.migrations._credentialtypes import _disassociate_non_insights_projects
EXAMPLE_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nxyz==\n-----END PRIVATE KEY-----'
@ -15,12 +16,12 @@ EXAMPLE_PRIVATE_KEY = '-----BEGIN PRIVATE KEY-----\nxyz==\n-----END PRIVATE KEY-
@contextmanager
def migrate(credential, kind):
def migrate(credential, kind, is_insights=False):
with mock.patch.object(Credential, 'kind', kind), \
mock.patch.object(Credential, 'objects', mock.Mock(
get=lambda **kw: deepcopy(credential),
all=lambda: [credential]
)):
all=lambda: [credential],
)), mock.patch('awx.main.migrations._credentialtypes._is_insights_scm', return_value=is_insights):
class Apps(apps.__class__):
def get_model(self, app, model):
if model == 'Credential':
@ -307,3 +308,40 @@ def test_azure_rm_migration():
assert decrypt_field(cred, 'secret') == 'some-secret'
assert cred.inputs['tenant'] == 'some-tenant'
assert Credential.objects.count() == 1
@pytest.mark.django_db
def test_insights_migration():
cred = Credential(name='My Credential')
with migrate(cred, 'scm', is_insights=True):
cred.__dict__.update({
'username': 'bob',
'password': 'some-password',
})
assert cred.credential_type.name == 'Insights Basic Auth'
assert cred.inputs['username'] == 'bob'
assert cred.inputs['password'].startswith('$encrypted$')
@pytest.mark.skip(reason="Need some more mocking here or something.")
@pytest.mark.django_db
def test_insights_project_migration():
cred1 = apps.get_model('main', 'Credential').objects.create(name='My Credential')
cred2 = apps.get_model('main', 'Credential').objects.create(name='My Credential')
projA1 = apps.get_model('main', 'Project').objects.create(name='Insights Project A1', scm_type='insights', credential=cred1)
projB1 = apps.get_model('main', 'Project').objects.create(name='Git Project B1', scm_type='git', credential=cred1)
projB2 = apps.get_model('main', 'Project').objects.create(name='Git Project B2', scm_type='git', credential=cred1)
projC1 = apps.get_model('main', 'Project').objects.create(name='Git Project C1', scm_type='git', credential=cred2)
_disassociate_non_insights_projects(apps, cred1)
_disassociate_non_insights_projects(apps, cred2)
assert apps.get_model('main', 'Project').objects.get(pk=projA1).credential is None
assert apps.get_model('main', 'Project').objects.get(pk=projB1).credential is None
assert apps.get_model('main', 'Project').objects.get(pk=projB2).credential is None
assert apps.get_model('main', 'Project').objects.get(pk=projC1).credential == cred2