From 71cf3198d84081ee9cbaabe839571c1b5984d26a Mon Sep 17 00:00:00 2001 From: AlanCoding Date: Thu, 14 May 2020 14:36:49 -0400 Subject: [PATCH] Add data migration to convert cloudforms scripts to SCM --- .../0115_v400_remove_cloudforms_inventory.py | 6 +++ awx/main/migrations/_inventory_source.py | 38 +++++++++++++++++++ awx/main/tasks.py | 5 ++- .../test_inventory_source_migration.py | 18 +++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/awx/main/migrations/0115_v400_remove_cloudforms_inventory.py b/awx/main/migrations/0115_v400_remove_cloudforms_inventory.py index aa3e08185e..27670e34c2 100644 --- a/awx/main/migrations/0115_v400_remove_cloudforms_inventory.py +++ b/awx/main/migrations/0115_v400_remove_cloudforms_inventory.py @@ -1,6 +1,11 @@ # Generated by Django 2.2.11 on 2020-05-01 13:25 from django.db import migrations, models +from awx.main.migrations._inventory_source import create_scm_script_substitute + + +def convert_cloudforms_to_scm(apps, schema_editor): + create_scm_script_substitute(apps, 'cloudforms') class Migration(migrations.Migration): @@ -10,6 +15,7 @@ class Migration(migrations.Migration): ] operations = [ + migrations.RunPython(convert_cloudforms_to_scm), migrations.AlterField( model_name='inventorysource', name='source', diff --git a/awx/main/migrations/_inventory_source.py b/awx/main/migrations/_inventory_source.py index c532ab33f5..22e5ff0ce3 100644 --- a/awx/main/migrations/_inventory_source.py +++ b/awx/main/migrations/_inventory_source.py @@ -1,5 +1,7 @@ import logging +from uuid import uuid4 + from django.utils.encoding import smart_text from awx.main.utils.common import parse_yaml_or_json @@ -87,3 +89,39 @@ def back_out_new_instance_id(apps, source, new_id): modified_ct, source )) + +def create_scm_script_substitute(apps, source): + """Only applies for cloudforms in practice, but written generally. + Given a source type, this will replace all inventory sources of that type + with SCM inventory sources that source the script from Ansible core + """ + # the revision in the Ansible 2.9 stable branch this project will start out as + # it can still be updated manually later (but staying within 2.9 branch), if desired + ansible_rev = '6f83b9aff42331e15c55a171de0a8b001208c18c' + InventorySource = apps.get_model('main', 'InventorySource') + Project = apps.get_model('main', 'Project') + if not InventorySource.objects.filter(source=source).exists(): + logger.debug('No sources of type {} to migrate'.format(source)) + return + proj_name = 'Replacement project for {} type sources - {}'.format(source, uuid4()) + project = Project( + name=proj_name, + description='Created by migration', + scm_type='git', + scm_url='https://github.com/ansible/ansible.git', + scm_branch='stable-2.9', + scm_revision=ansible_rev + ) + project.save(skip_update=True) + ct = 0 + for inv_src in InventorySource.objects.filter(source=source).iterator(): + inv_src.source = 'scm' + inv_src.source_project = project + inv_src.source_path = 'contrib/inventory/{}.py'.format(source) + inv_src.scm_last_revision = ansible_rev + inv_src.save(update_fields=['source', 'source_project', 'source_path', 'scm_last_revision']) + logger.debug('Changed inventory source {} to scm type'.format(inv_src.pk)) + ct += 1 + if ct: + logger.info('Changed total of {} inventory sources from {} type to scm'.format(ct, source)) + diff --git a/awx/main/tasks.py b/awx/main/tasks.py index 99ff7e9dc4..9fd3753440 100644 --- a/awx/main/tasks.py +++ b/awx/main/tasks.py @@ -2167,7 +2167,10 @@ class RunProjectUpdate(BaseTask): scm_branch = project_update.scm_branch branch_override = bool(scm_branch and project_update.scm_branch != project_update.project.scm_branch) if project_update.job_type == 'run' and (not branch_override): - scm_branch = project_update.project.scm_revision + if project_update.project.scm_revision: + scm_branch = project_update.project.scm_revision + elif not scm_branch: + raise RuntimeError('Could not determine a revision to run from project.') elif not scm_branch: scm_branch = {'hg': 'tip'}.get(project_update.scm_type, 'HEAD') extra_vars.update({ diff --git a/awx/main/tests/functional/test_inventory_source_migration.py b/awx/main/tests/functional/test_inventory_source_migration.py index 739b922322..ecea2f0408 100644 --- a/awx/main/tests/functional/test_inventory_source_migration.py +++ b/awx/main/tests/functional/test_inventory_source_migration.py @@ -5,6 +5,8 @@ from awx.main.migrations import _inventory_source as invsrc from django.apps import apps +from awx.main.models import InventorySource + @pytest.mark.parametrize('vars,id_var,result', [ ({'foo': {'bar': '1234'}}, 'foo.bar', '1234'), @@ -37,3 +39,19 @@ def test_apply_new_instance_id(inventory_source): host2.refresh_from_db() assert host1.instance_id == '' assert host2.instance_id == 'bad_user' + + +@pytest.mark.django_db +def test_replacement_scm_sources(inventory): + inv_source = InventorySource.objects.create( + name='test', + inventory=inventory, + organization=inventory.organization, + source='ec2' + ) + invsrc.create_scm_script_substitute(apps, 'ec2') + inv_source.refresh_from_db() + assert inv_source.source == 'scm' + assert inv_source.source_project + project = inv_source.source_project + assert 'Replacement project for' in project.name