environment: clean old auto variable for internal ips (#65235)

This commit is contained in:
Benjamin Dauvergne 2022-07-01 09:15:35 +02:00
parent 8a9ad4ffa5
commit a5acd7e2b2
2 changed files with 120 additions and 0 deletions

View File

@ -0,0 +1,26 @@
# Generated by Django 2.2.28 on 2022-07-01 07:11
from django.db import migrations
def clean_internal_ips(apps, schema_editor):
Variable = apps.get_model('environment', 'Variable')
for var in Variable.objects.filter(name='SETTING_INTERNAL_IPS', service_pk__isnull=True, auto=True):
if Variable.objects.filter(
name='SETTING_INTERNAL_IPS.extend', service_pk__isnull=True, auto=True
).exists():
var.delete()
else:
var.name = 'SETTING_INTERNAL_IPS.extend'
var.save()
class Migration(migrations.Migration):
dependencies = [
('environment', '0027_allow_long_slug'),
]
operations = [
migrations.RunPython(clean_internal_ips, migrations.RunPython.noop),
]

94
tests/test_migrations.py Normal file
View File

@ -0,0 +1,94 @@
# hobo - portal to configure and deploy applications
# Copyright (C) 2023 Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import pytest
from django.core.management import call_command
from django.db import connection
from django.db.migrations.executor import MigrationExecutor
@pytest.fixture()
def migration(request, transactional_db):
# see https://gist.github.com/asfaltboy/b3e6f9b5d95af8ba2cc46f2ba6eae5e2
"""
This fixture returns a helper object to test Django data migrations.
The fixture returns an object with two methods;
- `before` to initialize db to the state before the migration under test
- `after` to execute the migration and bring db to the state after the migration
The methods return `old_apps` and `new_apps` respectively; these can
be used to initiate the ORM models as in the migrations themselves.
For example:
def test_foo_set_to_bar(migration):
old_apps = migration.before([('my_app', '0001_inital')])
Foo = old_apps.get_model('my_app', 'foo')
Foo.objects.create(bar=False)
assert Foo.objects.count() == 1
assert Foo.objects.filter(bar=False).count() == Foo.objects.count()
# executing migration
new_apps = migration.apply([('my_app', '0002_set_foo_bar')])
Foo = new_apps.get_model('my_app', 'foo')
assert Foo.objects.filter(bar=False).count() == 0
assert Foo.objects.filter(bar=True).count() == Foo.objects.count()
Based on: https://gist.github.com/blueyed/4fb0a807104551f103e6
"""
class Migrator:
def before(self, targets, at_end=True):
"""Specify app and starting migration names as in:
before([('app', '0001_before')]) => app/migrations/0001_before.py
"""
executor = MigrationExecutor(connection)
executor.migrate(targets)
executor.loader.build_graph()
return executor._create_project_state(with_applied_migrations=True).apps
def apply(self, targets):
"""Migrate forwards to the "targets" migration"""
executor = MigrationExecutor(connection)
executor.migrate(targets)
executor.loader.build_graph()
return executor._create_project_state(with_applied_migrations=True).apps
yield Migrator()
call_command('migrate', verbosity=0)
def test_0028_clean_internal_ips_case_delete(transactional_db, migration):
old_apps = migration.before([('environment', '0027_allow_long_slug')])
Variable = old_apps.get_model('environment', 'Variable')
var1 = Variable.objects.create(name='SETTING_INTERNAL_IPS', auto=True, value='["1.1.1.1"]')
var2 = Variable.objects.create(name='SETTING_INTERNAL_IPS.extend', auto=True, value='["2.2.2.2"]')
new_apps = migration.apply([('environment', '0028_clean_internal_ips')])
Variable = new_apps.get_model('environment', 'Variable')
assert Variable.objects.filter(id=var1.id).count() == 0
assert Variable.objects.filter(id=var2.id).count() == 1
def test_0028_clean_internal_ips_case_rename(transactional_db, migration):
old_apps = migration.before([('environment', '0027_allow_long_slug')])
Variable = old_apps.get_model('environment', 'Variable')
var1 = Variable.objects.create(name='SETTING_INTERNAL_IPS', auto=True, value='["1.1.1.1"]')
new_apps = migration.apply([('environment', '0028_clean_internal_ips')])
Variable = new_apps.get_model('environment', 'Variable')
assert Variable.objects.filter(id=var1.id).count() == 1
var1.refresh_from_db()
assert var1.name == 'SETTING_INTERNAL_IPS.extend'