Пример #1
0
    def handle(self, *args, **options):
        super(MigrateSchemasCommand, self).handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        executor = get_executor(codename=self.executor)(self.args, self.options)

        if self.sync_public:
            executor.run_migrations(tenants=[self.PUBLIC_SCHEMA_NAME])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name):
                    raise RuntimeError('Schema "{}" does not exist'.format(
                        self.schema_name))
                else:
                    tenants = [self.schema_name]
            else:
                tenants = get_tenant_model().objects.only(
                    'schema_name').exclude(
                    schema_name=self.PUBLIC_SCHEMA_NAME).values_list(
                    'schema_name', flat=True)

            executor.run_migrations(tenants=tenants)
            tenant_objects = get_tenant_model().objects.filter(schema_name__in=tenants)

            for tenant in tenant_objects:
                if not isinstance(tenant, TenantMixin):
                    continue
                post_schema_migrate.send(sender=TenantMixin, tenant=tenant.serializable_fields())
Пример #2
0
    def handle(self, *args, **options):
        super(MigrateSchemasCommand, self).handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        executor = get_executor(codename=self.executor)(self.args,
                                                        self.options)

        if self.sync_public:
            executor.run_migrations(tenants=[self.PUBLIC_SCHEMA_NAME])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name):
                    raise RuntimeError('Schema "{}" does not exist'.format(
                        self.schema_name))
                else:
                    tenants = [self.schema_name]
            else:
                tenants = get_tenant_model().objects.only(
                    'schema_name').exclude(
                        schema_name=self.PUBLIC_SCHEMA_NAME).values_list(
                            'schema_name', flat=True)

            executor.run_migrations(tenants=tenants)
Пример #3
0
    def handle(self, *args, **options):
        super(MigrateSchemasCommand, self).handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        executor = get_executor(codename=self.executor)(self.args, self.options)

        if self.sync_public:
            executor.run_migrations(tenants=[self.PUBLIC_SCHEMA_NAME])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name):
                    raise RuntimeError('Schema "{}" does not exist'.format(
                        self.schema_name))
                else:
                    tenants = [self.schema_name]
            else:
                tenants = get_tenant_model().objects.only(
                    'schema_name').exclude(
                    schema_name=self.PUBLIC_SCHEMA_NAME).values_list(
                    'schema_name', flat=True)

            executor.run_migrations(tenants=tenants)
Пример #4
0
    def test_tenant_schema_is_created_atomically(self):
        """
        When saving a tenant, it's schema should be created.
        This should work in atomic transactions too.
        """
        executor = get_executor()
        Tenant = get_tenant_model()

        schema_name = 'test'

        @transaction.atomic()
        def atomically_create_tenant():
            t = Tenant(schema_name=schema_name)
            t.save()

            self.created = [t]

        if executor == 'simple':
            atomically_create_tenant()

            self.assertTrue(schema_exists(schema_name))
        elif executor == 'multiprocessing':
            # Unfortunately, it's impossible for the multiprocessing executor
            # to assert atomic transactions when creating a tenant
            with self.assertRaises(transaction.TransactionManagementError):
                atomically_create_tenant()
Пример #5
0
    def test_tenant_schema_is_created_atomically(self):
        """
        When saving a tenant, it's schema should be created.
        This should work in atomic transactions too.
        """
        executor = get_executor()
        Tenant = get_tenant_model()

        schema_name = 'test'

        @transaction.atomic()
        def atomically_create_tenant():
            t = Tenant(schema_name=schema_name)
            t.save()

            self.created = [t]

        if executor == 'simple':
            atomically_create_tenant()

            self.assertTrue(schema_exists(schema_name))
        elif executor == 'multiprocessing':
            # Unfortunately, it's impossible for the multiprocessing executor
            # to assert atomic transactions when creating a tenant
            with self.assertRaises(transaction.TransactionManagementError):
                atomically_create_tenant()
Пример #6
0
    def test_signal_on_migrate_schemas(self):
        """
        Check signals are sent on running of migrate_schemas.
        """
        executor = get_executor()
        tenant = get_tenant_model()(schema_name='test')
        tenant.save()
        domain = get_tenant_domain_model()(tenant=tenant,
                                           domain='something.test.com')
        domain.save()

        # test the signal gets called when running migrate
        with catch_signal(schema_migrated) as handler:
            call_command('migrate_schemas', interactive=False, verbosity=0)

        if executor == 'simple':
            handler.assert_has_calls([
                mock.call(
                    schema_name=get_public_schema_name(),
                    sender=mock.ANY,
                    signal=schema_migrated,
                ),
                mock.call(schema_name='test',
                          sender=mock.ANY,
                          signal=schema_migrated)
            ])
        elif executor == 'multiprocessing':
            # public schema gets migrated in the current process, always
            handler.assert_called_once_with(
                schema_name=get_public_schema_name(),
                sender=mock.ANY,
                signal=schema_migrated,
            )
Пример #7
0
    def test_migrate_schemas_order(self):
        """
        Test the migrate schemas is determined by TENANT_MIGRATION_ORDER.
        """
        executor = get_executor()
        if executor.codename != "standard":  # can only test in standard executor
            return

        tenant1 = get_tenant_model().objects.create(schema_name="test")
        tenant2 = get_tenant_model().objects.create(schema_name="xtest")
        get_tenant_domain_model().objects.create(tenant=tenant1,
                                                 domain="something1.test.com")
        get_tenant_domain_model().objects.create(tenant=tenant2,
                                                 domain="something2.test.com")

        # test the signal gets called when running migrate
        with catch_signal(schema_migrated) as handler:
            call_command("migrate_schemas", interactive=False, verbosity=0)

        handler.assert_has_calls([
            mock.call(
                schema_name=get_public_schema_name(),
                sender=mock.ANY,
                signal=schema_migrated,
            ),
            mock.call(schema_name="xtest",
                      sender=mock.ANY,
                      signal=schema_migrated),
            mock.call(schema_name="test",
                      sender=mock.ANY,
                      signal=schema_migrated),
        ])
Пример #8
0
    def handle(self, *args, **options):
        super().handle(*args, **options)
        self.PUBLIC_SCHEMA_NAME = get_public_schema_name()

        if self.sync_public and not self.schema_name:
            self.schema_name = self.PUBLIC_SCHEMA_NAME

        executor = get_executor(codename=self.executor)(self.args,
                                                        self.options)

        if self.sync_public:
            executor.run_migrations(tenants=[self.PUBLIC_SCHEMA_NAME])
        if self.sync_tenant:
            if self.schema_name and self.schema_name != self.PUBLIC_SCHEMA_NAME:
                if not schema_exists(self.schema_name,
                                     self.options.get('database', None)):
                    raise RuntimeError('Schema "{}" does not exist'.format(
                        self.schema_name))
                elif has_multi_type_tenants():
                    type_field_name = get_multi_type_database_field_name()
                    tenants = get_tenant_model().objects.only('schema_name', type_field_name)\
                        .filter(schema_name=self.schema_name)\
                        .values_list('schema_name', type_field_name)
                    executor.run_multi_type_migrations(tenants=tenants)
                else:
                    tenants = [self.schema_name]
                    executor.run_migrations(tenants=tenants)
            else:
                migration_order = get_tenant_migration_order()

                if has_multi_type_tenants():
                    type_field_name = get_multi_type_database_field_name()
                    tenants = get_tenant_model().objects.only('schema_name', type_field_name)\
                        .exclude(schema_name=self.PUBLIC_SCHEMA_NAME)\
                        .values_list('schema_name', type_field_name)

                    if migration_order is not None:
                        tenants = tenants.order_by(*migration_order)

                    executor.run_multi_type_migrations(tenants=tenants)
                else:
                    tenants = get_tenant_model().objects.only(
                        'schema_name').exclude(
                            schema_name=self.PUBLIC_SCHEMA_NAME).values_list(
                                'schema_name', flat=True)

                    if migration_order is not None:
                        tenants = tenants.order_by(*migration_order)

                    executor.run_migrations(tenants=tenants)
Пример #9
0
    def test_signal_on_tenant_create(self):
        """
        Since migrate gets called on creating of a tenant, check
        the signal gets sent.
        """
        executor = get_executor()

        tenant = get_tenant_model()(schema_name='test')
        with catch_signal(schema_migrated) as handler:
            tenant.save()

        if executor == 'simple':
            handler.assert_called_once_with(schema_name='test',
                                            sender=mock.ANY,
                                            signal=schema_migrated)
        elif executor == 'multiprocessing':
            # migrations run in a different process, therefore signal
            # will get sent in a different process as well
            handler.assert_not_called()

        domain = get_tenant_domain_model()(tenant=tenant,
                                           domain='something.test.com')
        domain.save()
        self.created = [domain, tenant]