Skip to content

Commit

Permalink
Merge f4fbc32 into 61c3676
Browse files Browse the repository at this point in the history
  • Loading branch information
atodorov committed Mar 15, 2020
2 parents 61c3676 + f4fbc32 commit c907143
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 79 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -27,11 +27,11 @@ pylint:
PYTHONPATH=.:$(KIWI_LINT_INCLUDE_PATH) DJANGO_SETTINGS_MODULE="test_project.settings" \
pylint --load-plugins=pylint_django --load-plugins=kiwi_lint \
-d missing-docstring -d duplicate-code -d module-in-directory-without-init \
*.py tcms_tenants/ test_project/
*.py tcms_settings_dir/ tcms_tenants/ test_project/

.PHONY: flake8
flake8:
flake8 *.py tcms_tenants/ test_project/
flake8 *.py tcms_settings_dir/ tcms_tenants/ test_project/

.PHONY: check
check: flake8 pylint test_for_missing_migrations test
39 changes: 7 additions & 32 deletions README.rst
Expand Up @@ -52,39 +52,13 @@ your Python virtualenv where the main Kiwi TCMS instance is hosted::

pip install kiwitcms-tenants

Then make sure the following settings are configured::
then make sure ``KIWI_TENANTS_DOMAIN`` ENV variable is specified !!!
The rest of the settings are installed into ``tcms_settings_dir/multi_tenant.py``
and Kiwi TCMS will pick them up automatically!

DATABASES['default']['ENGINE'] = 'django_tenants.postgresql_backend'
DATABASE_ROUTERS = ['django_tenants.routers.TenantSyncRouter']

# TenantMainMiddleware must be the first in the list
MIDDLEWARE.insert(0, 'django_tenants.middleware.main.TenantMainMiddleware')
MIDDLEWARE.append('tcms_tenants.middleware.BlockUnauthorizedUserMiddleware')

TENANT_MODEL = "tcms_tenants.Tenant"
TENANT_DOMAIN_MODEL = "tcms_tenants.Domain"

# django_tenants must be the first in INSTALLED_APPS
INSTALLED_APPS.insert(0, 'django_tenants')

# list INSTALLED_APPS which will have their own copy for different tenants
TENANT_APPS = [ ... ]

SHARED_APPS = INSTALLED_APPS

# public tenant will be at https://public.tenants.example.org
# Wild card DNS must be configured
KIWI_TENANTS_DOMAIN = 'tenants.example.org'

SESSION_COOKIE_DOMAIN = ".%s" % KIWI_TENANTS_DOMAIN

# attachments storage
DEFAULT_FILE_STORAGE = "tcms_tenants.storage.TenantFileSystemStorage"
MULTITENANT_RELATIVE_MEDIA_ROOT = "tenants/%s"

Check
`test_project/settings.py <https://github.com/kiwitcms/tenants/blob/master/test_project/settings.py>`_
for more examples.
First boot configuration
------------------------

When starting your multi-tenant Kiwi TCMS instance for the first time you also
need to create information about the so called public tenant. That is the
Expand All @@ -101,7 +75,8 @@ default tenant on which your application runs::
--domain-is_primary True

**WARNING:** schema_name `public` is special, the rest is up to you.
`owner_id` is usually the ID of the first superuser in the database.
`owner_id` is usually the ID of the first superuser in the database which means
you must have executed ``createsuperuser`` first!

You can use `create_tenant` afterwards to create other tenants for various teams
or projects. Non-public tenants can also be created via the web interface as well.
Expand Down
4 changes: 4 additions & 0 deletions manage.py
Expand Up @@ -5,6 +5,10 @@
import sys

if __name__ == "__main__":
if os.path.exists("kiwitcms_tenants.egg-info"):
print("ERORR: .egg-info/ directories mess up plugin loading code in devel mode")
sys.exit(1)

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "test_project.settings")

from django.core.management import execute_from_command_line
Expand Down
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -33,8 +33,9 @@ def get_install_requires(path):
url='https://github.com/kiwitcms/tenants/',
license='GPLv3+',
install_requires=get_install_requires('requirements.txt'),
packages=find_packages(exclude=['test_project*', '*.tests']),
include_package_data=True,
packages=find_packages(exclude=['test_project*', '*.tests']),
zip_safe=False,
entry_points={"kiwitcms.plugins": ["kiwitcms_tenants = tcms_tenants"]},
classifiers=[
'Framework :: Django',
Expand Down
1 change: 1 addition & 0 deletions tcms_settings_dir/__init__.py
@@ -0,0 +1 @@
__path__ = __import__('pkgutil').extend_path(__path__, __name__)
58 changes: 58 additions & 0 deletions tcms_settings_dir/multi_tenant.py
@@ -0,0 +1,58 @@
# Copyright (c) 2020 Alexander Todorov <atodorov@MrSenko.com>

# Licensed under the GPL 3.0: https://www.gnu.org/licenses/gpl-3.0.txt
# pylint: disable=undefined-variable
import os


# start multi-tenant settings override
DATABASES['default']['ENGINE'] = 'django_tenants.postgresql_backend' # noqa: F821
DATABASE_ROUTERS = ['django_tenants.routers.TenantSyncRouter', ]


# attachments storage
DEFAULT_FILE_STORAGE = "tcms_tenants.storage.TenantFileSystemStorage"
MULTITENANT_RELATIVE_MEDIA_ROOT = "tenants/%s"


# this always needs to be the first app
if 'django_tenants' not in INSTALLED_APPS: # noqa: F821
INSTALLED_APPS.insert(0, 'django_tenants') # noqa: F821


KIWI_TENANTS_DOMAIN = os.environ.get('KIWI_TENANTS_DOMAIN')


# TenantMainMiddleware always needs to be first
if 'django_tenants.middleware.main.TenantMainMiddleware' not in MIDDLEWARE: # noqa: F821
MIDDLEWARE.insert(0, 'django_tenants.middleware.main.TenantMainMiddleware') # noqa: F821

if 'tcms_tenants.middleware.BlockUnauthorizedUserMiddleware' not in MIDDLEWARE: # noqa: F821
MIDDLEWARE.append('tcms_tenants.middleware.BlockUnauthorizedUserMiddleware') # noqa: F821


TENANT_APPS = [
'django.contrib.sites',

'attachments',
'django_comments',
'modernrpc',
'simple_history',

'tcms.bugs',
'tcms.core.contrib.linkreference',
'tcms.management',
'tcms.testcases.apps.AppConfig',
'tcms.testplans.apps.AppConfig',
'tcms.testruns.apps.AppConfig',
]
TENANT_MODEL = "tcms_tenants.Tenant"
TENANT_DOMAIN_MODEL = "tcms_tenants.Domain"


# share login session between tenants
SESSION_COOKIE_DOMAIN = ".%s" % KIWI_TENANTS_DOMAIN


# everybody can access the main instance
SHARED_APPS = INSTALLED_APPS # noqa: F821
60 changes: 16 additions & 44 deletions test_project/settings.py
Expand Up @@ -9,6 +9,7 @@

# pretend this is a plugin during testing & development
# IT NEEDS TO BE BEFORE the wildcard import below !!!
# .egg-info/ directory will mess up with this
dist = pkg_resources.Distribution(__file__)
entry_point = pkg_resources.EntryPoint.parse('kiwitcms_tenants_devel = tcms_tenants',
dist=dist)
Expand All @@ -20,6 +21,21 @@
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.insert(0, BASE_DIR)

# check for a clean devel environment
if os.path.exists(os.path.join(BASE_DIR, "kiwitcms_tenants.egg-info")):
print("ERORR: .egg-info/ directories mess up plugin loading code in devel mode")
sys.exit(1)

# import the settings which automatically get distributed with this package
multi_tenant_settings = os.path.join(
BASE_DIR, 'tcms_settings_dir', 'multi_tenant.py')

# Kiwi TCMS loads extra settings in the same way using exec()
exec( # pylint: disable=exec-used
open(multi_tenant_settings, "rb").read(),
globals()
)


# these are enabled only for testing purposes
DEBUG = True
Expand All @@ -30,53 +46,9 @@

# start multi-tenant settings override
DATABASES['default'].update({ # noqa: F405 pylint: disable=objects-update-used
'ENGINE': 'django_tenants.postgresql_backend',
'NAME': 'test_project',
'USER': 'kiwi',
'PASSWORD': 'kiwi',
'HOST': 'localhost',
'OPTIONS': {},
})

DATABASE_ROUTERS = [
'django_tenants.routers.TenantSyncRouter',
]

MIDDLEWARE.insert(0, 'django_tenants.middleware.main.TenantMainMiddleware') # noqa: F405
MIDDLEWARE.append('tcms_tenants.middleware.BlockUnauthorizedUserMiddleware') # noqa: F405

TENANT_MODEL = "tcms_tenants.Tenant"
TENANT_DOMAIN_MODEL = "tcms_tenants.Domain"

# this always needs to be the first app
INSTALLED_APPS.insert(0, 'django_tenants') # noqa: F405

TENANT_APPS = [
'django.contrib.sites',

'attachments',
'django_comments',
'modernrpc',
'simple_history',

'tcms.bugs',
'tcms.core.contrib.linkreference',
'tcms.management',
'tcms.testcases.apps.AppConfig',
'tcms.testplans.apps.AppConfig',
'tcms.testruns.apps.AppConfig',
]

# everybody can access the main instance
SHARED_APPS = INSTALLED_APPS # noqa: F405

# Allows serving non-public tenants on a sub-domain
# WARNING: doesn't work well when you have a non-standard port-number
KIWI_TENANTS_DOMAIN = 'tenants.localdomain'

# share login session between tenants
SESSION_COOKIE_DOMAIN = ".%s" % KIWI_TENANTS_DOMAIN

# attachments storage
DEFAULT_FILE_STORAGE = "tcms_tenants.storage.TenantFileSystemStorage"
MULTITENANT_RELATIVE_MEDIA_ROOT = "tenants/%s"

0 comments on commit c907143

Please sign in to comment.