Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clone_tenant #322

Closed
webapp-dev opened this issue Nov 25, 2019 · 3 comments
Closed

clone_tenant #322

webapp-dev opened this issue Nov 25, 2019 · 3 comments

Comments

@webapp-dev
Copy link

webapp-dev commented Nov 25, 2019

I have read the docs and while some management commands are documented clone_tenant is not, no matter what I throw at it, I get errors, but I know it is because I do not know the commands...

python manage,py clone_tenant --clone_from=abc_123456 --clone_to=xyz_12345 --user=145

Above does not work and countless other variations fail, the only valid option I can see in the code is: --clone_from

Also is there a way to call this from within the code?
eg:
from django_tenants.management.commands import clone_tenant
clone_tenant(clone_from, clone_to, user)

This also does not work.... any hints clues or examples would be greatly appreciated.

@webapp-dev
Copy link
Author

webapp-dev commented Nov 25, 2019

I had to bypass the django-tenants clone_tenant function because it kept coming back with errors and I need to move fast I have clients waiting to purchase accounts.

This code is very raw just for testing but it works, obviously, it needs error catching try: except: ... etc but here is the working code to clone a tenant.

Cloning takes seconds Vs Provisioning through the tenant.auto_create_schema = True (default) which can take a long time because it has to apply all of the migrations which can take minutes.

*** Don't forget you need to create the function "clone_tenant" on your Server, I used the version by denishpatel , make sure you are using the right version for your server version. Many thanks to denishpatel. His versions work with django-tenants many others do not.

user = TenantUser.objects.get(email=user_email)    
      
time_string = str(int(time.time()))
schema_name = '{}_{}'.format(sub_domain, time_string)
tenant_domain = '{}.{}'.format(sub_domain, settings.TENANT_USERS_DOMAIN)

#1. Create the tenant but do not create the schema by auto default add the user as the owner and set default fields
tenant = Client(
    slug=sub_domain,
    domain_url=tenant_domain,
    schema_name=schema_name,
    name=bus_name,
    on_trial=True,
    owner=user,
)    
tenant.auto_create_schema = False  # Here is the MAGIC - DO NOT create the schema automatically as we are going to be cloning an existing schema
tenant.save()

#2. Create the domain and link to tenant
domain = Domain(
    tenant=tenant,
    domain=tenant_domain, 
    is_primary=True,
    setup_stage=0,
)
domain.save()

# Add user as a superuser inside the tenant
tenant.add_user(user, is_superuser=True, is_staff=False)

# Get the name of the template schema we are cloning from
clone_from = 'myfabulous_tenant_template'
clone_to = schema_name 

# Create cursor
connection.set_schema_to_public()
cursor = connection.cursor()    

cursor.execute("SELECT clone_schema( %s, %s, TRUE )", [clone_from, clone_to ])
cursor.close()      

@webapp-dev
Copy link
Author

This was the code that kept giving errors in clone_tenant.py within django-tenants:

The error was on the line "clone_schema = CloneSchema(cursor)" and read CloneSchema does not accept arguments. So this will need fixing and maybe add an example to the documentation along with a note about the clone_schema function required for the server.

def store_tenant(self, clone_schema_from, **fields):
    connection.set_schema_to_public()
    cursor = connection.cursor()

    try:
        tenant = get_tenant_model()(**fields)
        tenant.auto_create_schema = False
        tenant.save()

        clone_schema = CloneSchema(cursor)
        clone_schema.clone(clone_schema_from, tenant.schema_name)
        return tenant
    except exceptions.ValidationError as e:
        self.stderr.write("Error: %s" % '; '.join(e.messages))
        return None
    except IntegrityError:
        return None

@foarsitter
Copy link
Contributor

Is this issue perhaps related to: #246?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants