Skip to content

Commit f44de6e

Browse files
Closes #181: Introduce a configuration parameter to define the default schema name (#254)
1 parent bf099cf commit f44de6e

File tree

7 files changed

+26
-11
lines changed

7 files changed

+26
-11
lines changed

docs/configuration.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ exempt_models = (
2828

2929
---
3030

31+
## `main_schema`
32+
33+
Default: `"public"`
34+
35+
The name of the main (primary) PostgreSQL schema. (Use the `\dn` command in the PostgreSQL CLI to list all schemas.)
36+
37+
---
38+
3139
## `max_working_branches`
3240

3341
Default: None
@@ -46,7 +54,7 @@ The maximum total number of branches that can exist simultaneously, including me
4654

4755
## `schema_prefix`
4856

49-
Default: `branch_`
57+
Default: `"branch_"`
5058

5159
The string to prefix to the unique branch ID when provisioning the PostgreSQL schema for a branch. Per [the PostgreSQL documentation](https://www.postgresql.org/docs/16/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS), this string must begin with a letter or underscore.
5260

netbox_branching/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ class AppConfig(PluginConfig):
2828
# Models from other plugins which should be excluded from branching support
2929
'exempt_models': [],
3030

31+
# The name of the main schema
32+
'main_schema': 'public',
33+
3134
# This string is prefixed to the name of each new branch schema during provisioning
3235
'schema_prefix': 'branch_',
3336

netbox_branching/constants.py

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# Name of the main (non-branch) PostgreSQL schema
2-
MAIN_SCHEMA = 'public'
3-
41
# HTTP cookie
52
COOKIE_NAME = 'active_branch'
63

netbox_branching/database.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,5 @@ def db_for_write(self, model, **hints):
3737
return self._get_db(model, **hints)
3838

3939
def allow_relation(self, obj1, obj2, **hints):
40-
# Permit relations from the branch schema to the main (public) schema
40+
# Permit relations from the branch schema to the main schema
4141
return True

netbox_branching/models/branches.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ def provision(self, user):
540540
"""
541541
logger = logging.getLogger('netbox_branching.branch.provision')
542542
logger.info(f'Provisioning branch {self} ({self.schema_name})')
543+
main_schema = get_plugin_config('netbox_branching', 'main_schema')
543544

544545
# Emit pre-provision signal
545546
pre_provision.send(sender=self.__class__, branch=self, user=user)
@@ -572,21 +573,21 @@ def provision(self, user):
572573
# Create an empty copy of the global change log. Share the ID sequence from the main table to avoid
573574
# reusing change record IDs.
574575
table = ObjectChange_._meta.db_table
575-
main_table = f'public.{table}'
576+
main_table = f'{main_schema}.{table}'
576577
schema_table = f'{schema}.{table}'
577578
logger.debug(f'Creating table {schema_table}')
578579
cursor.execute(
579580
f"CREATE TABLE {schema_table} ( LIKE {main_table} INCLUDING INDEXES )"
580581
)
581582
# Set the default value for the ID column to the sequence associated with the source table
582-
sequence_name = f'public.{table}_id_seq'
583+
sequence_name = f'{main_schema}.{table}_id_seq'
583584
cursor.execute(
584585
f"ALTER TABLE {schema_table} ALTER COLUMN id SET DEFAULT nextval(%s)", [sequence_name]
585586
)
586587

587588
# Replicate relevant tables from the main schema
588589
for table in get_tables_to_replicate():
589-
main_table = f'public.{table}'
590+
main_table = f'{main_schema}.{table}'
590591
schema_table = f'{schema}.{table}'
591592
logger.debug(f'Creating table {schema_table}')
592593
# Create the table in the new schema

netbox_branching/tests/test_branches.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
from django.test import TransactionTestCase, override_settings
77
from django.utils import timezone
88

9+
from netbox.plugins import get_plugin_config
910
from netbox_branching.choices import BranchStatusChoices
10-
from netbox_branching.constants import MAIN_SCHEMA
1111
from netbox_branching.models import Branch
1212
from netbox_branching.utilities import get_tables_to_replicate
1313
from .utils import fetchall, fetchone
@@ -21,6 +21,7 @@ def test_create_branch(self):
2121
branch.save(provision=False)
2222
branch.provision(user=None)
2323

24+
main_schema = get_plugin_config('netbox_branching', 'main_schema')
2425
tables_to_replicate = get_tables_to_replicate()
2526

2627
with connection.cursor() as cursor:
@@ -44,7 +45,7 @@ def test_create_branch(self):
4445

4546
# Check that object counts match the main schema for each table
4647
for table_name in tables_to_replicate:
47-
cursor.execute(f"SELECT COUNT(id) FROM {MAIN_SCHEMA}.{table_name}")
48+
cursor.execute(f"SELECT COUNT(id) FROM {main_schema}.{table_name}")
4849
main_count = fetchone(cursor).count
4950
cursor.execute(f"SELECT COUNT(id) FROM {branch.schema_name}.{table_name}")
5051
branch_count = fetchone(cursor).count

netbox_branching/utilities.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from collections import defaultdict
44
from contextlib import contextmanager, nullcontext
55
from dataclasses import dataclass
6+
from functools import cached_property
67

78
from django.contrib import messages
89
from django.db.models import ForeignKey, ManyToManyField
@@ -39,14 +40,18 @@ class DynamicSchemaDict(dict):
3940
Behaves like a normal dictionary, except for keys beginning with "schema_". Any lookup for
4041
"schema_*" will return the default configuration extended to include the search_path option.
4142
"""
43+
@cached_property
44+
def main_schema(self):
45+
return get_plugin_config('netbox_branching', 'main_schema')
46+
4247
def __getitem__(self, item):
4348
if type(item) is str and item.startswith('schema_'):
4449
if schema := item.removeprefix('schema_'):
4550
default_config = super().__getitem__('default')
4651
return {
4752
**default_config,
4853
'OPTIONS': {
49-
'options': f'-c search_path={schema},public'
54+
'options': f'-c search_path={schema},{self.main_schema}'
5055
}
5156
}
5257
return super().__getitem__(item)

0 commit comments

Comments
 (0)