From cd9dd43be7a6b1cc1c34ec1057d76234e57d3cd6 Mon Sep 17 00:00:00 2001 From: Seth Foster Date: Fri, 19 Jan 2024 15:08:36 -0500 Subject: [PATCH] Make InstanceLink target non-nullable InstanceLink target should not be null. Should be safe to set to null=False, because we have a custom RunPython method to explicitly set target to a proper key. Also, add new test to test_migrations which ensures data integrity after migrating the receptor address model changes. Signed-off-by: Seth Foster --- awx/main/migrations/0189_inbound_hop_nodes.py | 7 +++++ awx/main/models/ha.py | 2 +- awx/main/tests/functional/test_migrations.py | 26 +++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/awx/main/migrations/0189_inbound_hop_nodes.py b/awx/main/migrations/0189_inbound_hop_nodes.py index a01ed31527..d23f8a8663 100644 --- a/awx/main/migrations/0189_inbound_hop_nodes.py +++ b/awx/main/migrations/0189_inbound_hop_nodes.py @@ -134,4 +134,11 @@ class Migration(migrations.Migration): name='peers', field=models.ManyToManyField(related_name='peers_from', through='main.InstanceLink', to='main.receptoraddress'), ), + migrations.AlterField( + model_name='instancelink', + name='target', + field=models.ForeignKey( + help_text='The target receptor address of this peer link.', on_delete=django.db.models.deletion.CASCADE, to='main.receptoraddress' + ), + ), ] diff --git a/awx/main/models/ha.py b/awx/main/models/ha.py index e6e7b0861a..b9c22d355b 100644 --- a/awx/main/models/ha.py +++ b/awx/main/models/ha.py @@ -69,7 +69,7 @@ class InstanceLink(BaseModel): ordering = ("id",) source = models.ForeignKey('Instance', on_delete=models.CASCADE, help_text=_("The source instance of this peer link.")) - target = models.ForeignKey('ReceptorAddress', null=True, on_delete=models.CASCADE, help_text=_("The target receptor address of this peer link.")) + target = models.ForeignKey('ReceptorAddress', on_delete=models.CASCADE, help_text=_("The target receptor address of this peer link.")) class States(models.TextChoices): ADDING = 'adding', _('Adding') diff --git a/awx/main/tests/functional/test_migrations.py b/awx/main/tests/functional/test_migrations.py index cd0889c208..ab877f603f 100644 --- a/awx/main/tests/functional/test_migrations.py +++ b/awx/main/tests/functional/test_migrations.py @@ -42,3 +42,29 @@ class TestMigrationSmoke: final_state = migrator.apply_tested_migration(final_migration) Instance = final_state.apps.get_model('main', 'Instance') assert Instance.objects.filter(hostname='foobar').count() == 1 + + def test_receptor_address(self, migrator): + old_state = migrator.apply_initial_migration(('main', '0188_add_bitbucket_dc_webhook')) + Instance = old_state.apps.get_model('main', 'Instance') + for i in range(3): + Instance.objects.create(hostname=f'foobar{i}', node_type='hop') + foo = Instance.objects.create(hostname='foo', node_type='execution', listener_port=1234) + bar = Instance.objects.create(hostname='bar', node_type='execution', listener_port=None) + bar.peers.add(foo) + + new_state = migrator.apply_tested_migration( + ('main', '0189_inbound_hop_nodes'), + ) + Instance = new_state.apps.get_model('main', 'Instance') + ReceptorAddress = new_state.apps.get_model('main', 'ReceptorAddress') + + # We can now test how our migration worked, new field is there: + assert ReceptorAddress.objects.filter(address='foo', port=1234).count() == 1 + assert not ReceptorAddress.objects.filter(address='bar').exists() + + bar = Instance.objects.get(hostname='bar') + fooaddr = ReceptorAddress.objects.get(address='foo') + + bar_peers = bar.peers.all() + assert len(bar_peers) == 1 + assert fooaddr in bar_peers