160 lines
7.7 KiB
Python
160 lines
7.7 KiB
Python
from django.contrib.contenttypes.models import ContentType
|
|
from django.utils.timezone import now
|
|
from tenant_schemas.utils import tenant_context
|
|
|
|
from hobo.agent.common.management.commands import hobo_deploy
|
|
from hobo.deploy.signals import notify_agents
|
|
from hobo.environment.models import AVAILABLE_SERVICES, Hobo, Variable
|
|
from hobo.environment.utils import get_or_create_local_hobo
|
|
from hobo.multitenant.middleware import TenantMiddleware, TenantNotFound
|
|
from hobo.profile.models import AttributeDefinition
|
|
|
|
|
|
class Command(hobo_deploy.Command):
|
|
help = 'Deploy multitenant hobo service from hobo'
|
|
early_secondary_exit = False
|
|
|
|
def deploy_specifics(self, hobo_environment, tenant):
|
|
me = [x for x in hobo_environment.get('services') if x.get('this')][0]
|
|
if not me.get('secondary'):
|
|
super().deploy_specifics(hobo_environment, tenant)
|
|
|
|
with tenant_context(tenant):
|
|
services = hobo_environment.get('services')
|
|
|
|
if me.get('secondary'):
|
|
# check we are currently processing the primary hobo, we don't
|
|
# want to create secondary services on every branches.
|
|
if Hobo.objects.filter(secondary=False, local=False).count() == 0:
|
|
return
|
|
is_primary_hobo = True
|
|
# on the primary hobo, notify other primary services, this will
|
|
# get authentic to know about secondary services
|
|
propagate_notify = True
|
|
else:
|
|
is_primary_hobo = False
|
|
propagate_notify = False
|
|
|
|
for service_dict in services:
|
|
if service_dict.get('secondary'):
|
|
continue
|
|
if service_dict.get('base_url') == me['base_url']:
|
|
# URL might have changed, need to update local hobo
|
|
local_hobo = get_or_create_local_hobo()
|
|
if local_hobo and local_hobo.get_base_url_path() != service_dict.get('base_url'):
|
|
local_hobo.change_base_url(service_dict.get('base_url'))
|
|
local_hobo.save()
|
|
continue
|
|
for service_klass in AVAILABLE_SERVICES:
|
|
if service_klass.Extra.service_id == service_dict.get('service-id'):
|
|
break
|
|
else:
|
|
continue
|
|
|
|
if me.get('secondary') and service_dict.get('service-id') == 'hobo':
|
|
continue
|
|
|
|
if service_klass.objects.filter(secondary=False, base_url=service_dict['base_url']).count():
|
|
# make sure a real service is not secondaryed
|
|
continue
|
|
|
|
slug_prefix = '_interco_'
|
|
if is_primary_hobo:
|
|
# this is the primary hobo, receiving a notification
|
|
# because something changed in secondary hobo environment.
|
|
# mark services with ou-label/ou-slug
|
|
secondary_hobo = [
|
|
x for x in services if x['service-id'] == 'hobo' and not x.get('secondary')
|
|
][0]
|
|
slug_prefix = '_%s_' % hobo_environment['variables']['ou-slug']
|
|
|
|
service_slug = '%s%s' % (slug_prefix, service_dict['slug'])
|
|
|
|
service, created = None, False
|
|
for legacy_urls in service_dict.get('legacy_urls', []):
|
|
try:
|
|
service = service_klass.objects.get(base_url=legacy_urls['base_url'], secondary=True)
|
|
service.change_base_url(service_dict['base_url'])
|
|
break
|
|
except service_klass.DoesNotExist:
|
|
pass
|
|
|
|
if not service:
|
|
service, created = service_klass.objects.get_or_create(
|
|
base_url=service_dict['base_url'],
|
|
secondary=True,
|
|
defaults={
|
|
'title': service_dict['title'],
|
|
'slug': service_slug,
|
|
'secret_key': service_dict.get('secret_key'),
|
|
},
|
|
)
|
|
|
|
service.title = service_dict['title']
|
|
service.secret_key = service_dict.get('secret_key')
|
|
service.template_name = service_dict.get('template_name') or ''
|
|
service.slug = service_slug
|
|
service.use_as_idp_for_self = True
|
|
service.last_operational_check_timestamp = now()
|
|
service.last_operational_success_timestamp = service.last_operational_check_timestamp
|
|
service.save()
|
|
|
|
if is_primary_hobo:
|
|
# add variables to mark the service as a different
|
|
# organizational unit
|
|
service_type = ContentType.objects.get_for_model(service_klass)
|
|
variable, created = Variable.objects.get_or_create(
|
|
name='ou-label', auto=True, service_type=service_type, service_pk=service.id
|
|
)
|
|
variable.value = hobo_environment['variables']['ou-label']
|
|
variable.save()
|
|
variable, created = Variable.objects.get_or_create(
|
|
name='ou-slug', auto=True, service_type=service_type, service_pk=service.id
|
|
)
|
|
variable.value = hobo_environment['variables']['ou-slug']
|
|
variable.save()
|
|
|
|
if not is_primary_hobo:
|
|
# this is the secondary hobo, set service slug and label as
|
|
# global variables so they can later be used to identify
|
|
# this "organizational unit".
|
|
variable, created = Variable.objects.get_or_create(
|
|
name='ou-label', auto=True, service_pk=None
|
|
)
|
|
variable.value = me['title']
|
|
variable.save()
|
|
variable, created = Variable.objects.get_or_create(
|
|
name='ou-slug', auto=True, service_pk=None
|
|
)
|
|
variable.value = me['slug']
|
|
variable.save()
|
|
|
|
# and reproduce profile settings from primary
|
|
if 'profile' in hobo_environment:
|
|
seen = []
|
|
changes = False
|
|
for i, field in enumerate(hobo_environment['profile']['fields']):
|
|
attribute, created = AttributeDefinition.objects.get_or_create(
|
|
name=field['name'], defaults={'label': field['label']}
|
|
)
|
|
if created:
|
|
changes = True
|
|
for k, v in field.items():
|
|
if getattr(attribute, k, None) != v:
|
|
setattr(attribute, k, v)
|
|
changes = True
|
|
if attribute.order != (i + 1):
|
|
changes = True
|
|
attribute.order = i + 1
|
|
attribute.save()
|
|
seen.append(attribute.name)
|
|
removed, details_ = AttributeDefinition.objects.exclude(name__in=seen).delete()
|
|
if removed:
|
|
changes = True
|
|
if changes:
|
|
# if there were changes to profile fields, propagate them.
|
|
propagate_notify = True
|
|
|
|
if propagate_notify:
|
|
notify_agents(None)
|