From 2050f00fc51cb5d54149994562ef1d1065cfdf58 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Wed, 9 Sep 2015 09:28:15 +0200 Subject: [PATCH] add new agent task to provision objects to tenants (fixes #8217) First use is to connect it to post_save, post_delete signal on Role model of authentic, to propagate roles to tenants. --- hobo/agent/authentic2/apps.py | 51 +++++++++++++++++++++++++++++++++++++++++++ hobo/agent/common/__init__.py | 25 +++++++++++++++++++++ hobo/agent/worker/celery.py | 8 +++++++ hobo/agent/worker/notify.py | 17 +++++++++++++++ hobo/agent/worker/settings.py | 2 ++ 5 files changed, 103 insertions(+) create mode 100644 hobo/agent/worker/notify.py diff --git a/hobo/agent/authentic2/apps.py b/hobo/agent/authentic2/apps.py index 0996c09..ebbe1c8 100644 --- a/hobo/agent/authentic2/apps.py +++ b/hobo/agent/authentic2/apps.py @@ -1,6 +1,57 @@ from django.apps import AppConfig +from django.db.models import post_save, post_delete + +from django_rbac.utils import get_role_model + +from hobo.agent.common import notify_agents +from authentic2.utils import to_list +from authentic2.saml.models import LibertyProvider + + +@to_list +def get_audience(): + for provider in LibertyProvider.objects.all(): + yield provider.entity_id + + +def notify_roles_post_save(sender, instance, created, **kwargs): + notify_agents({ + '@type': 'provision', + 'audience': get_audience(), + 'objects': [ + { + '@type': 'role', + 'uuid': instance.uuid, + 'name': instance.name, + 'slug': instance.slug, + 'description': instance.description, + } + ] + }) + + +def notify_roles_post_delete(sender, instance, **kwargs): + notify_agents({ + '@type': 'deprovision', + 'audience': get_audience(), + 'objects': [ + { + '@type': 'role', + 'uuid': instance.uuid, + 'name': instance.name, + 'slug': instance.slug, + 'description': instance.description, + } + ] + }) + class Authentic2AgentConfig(AppConfig): name = 'hobo.agent.authentic2' label = 'authentic2_agent' verbose_name = 'Authentic2 Agent' + + def ready(self): + Role = get_role_model() + post_save.connect(notify_roles_post_save, Role) + post_delete.connect(notify_roles_post_delete, Role) diff --git a/hobo/agent/common/__init__.py b/hobo/agent/common/__init__.py index e69de29..5b50cc6 100644 --- a/hobo/agent/common/__init__.py +++ b/hobo/agent/common/__init__.py @@ -0,0 +1,25 @@ +from celery import Celery +from kombu.common import Broadcast + +from django.conf import settings +from django.db import connection + + +def notify_agents(data): + '''Send notifications to all other tenants''' + notification = { + 'tenant': connection.get_tenant().domain_url, + 'data': data, + } + with Celery('hobo', broker=settings.BROKER_URL) as app: + app.conf.update( + CELERY_TASK_SERIALIZER='json', + CELERY_ACCEPT_CONTENT=['json'], + CELERY_RESULT_SERIALIZER='json', + CELERY_QUEUES=(Broadcast('broadcast_tasks'), ) + ) + # see called method in hobo.agent.worker.celery + app.send_task('hobo-notify', + (notification,), + expires=settings.BROKER_TASK_EXPIRES, + queue='broadcast_tasks') diff --git a/hobo/agent/worker/celery.py b/hobo/agent/worker/celery.py index 3db4b0d..3b3b0ad 100644 --- a/hobo/agent/worker/celery.py +++ b/hobo/agent/worker/celery.py @@ -4,6 +4,7 @@ from celery import Celery from kombu.common import Broadcast from . import settings from . import services +from . import notify app = Celery('hobo', broker=settings.BROKER_URL) app.conf.update( @@ -13,6 +14,13 @@ app.conf.update( CELERY_QUEUES=(Broadcast('broadcast_tasks'), ) ) + @app.task(name='hobo-deploy', bind=True) def deploy(self, environment): services.deploy(environment) + + +@app.task(name='hobo-notify', bind=True, acks_late=True) +def hobo_notify(self, data): + # do something with data + notify.notify(data) diff --git a/hobo/agent/worker/notify.py b/hobo/agent/worker/notify.py new file mode 100644 index 0000000..d62d124 --- /dev/null +++ b/hobo/agent/worker/notify.py @@ -0,0 +1,17 @@ +import os.path +import subprocess +import json + +from . import settings + + +def notify(data): + for command in settings.NOTIFY_COMMANDS: + if not os.path.exists(command): + continue + what = command + ' notify -' + cmd_process = subprocess.Popen(what, shell=True, stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + cmd_process.communicate(input=json.dumps(data)) + if cmd_process.returncode != 0: + raise RuntimeError('command "%s" failed' % what) diff --git a/hobo/agent/worker/settings.py b/hobo/agent/worker/settings.py index 7d26df0..c8ba92d 100644 --- a/hobo/agent/worker/settings.py +++ b/hobo/agent/worker/settings.py @@ -24,6 +24,8 @@ PASSERELLE_MANAGE_COMMAND = '/usr/lib/passerelle/manage.py' FARGO_MANAGE_COMMAND = '/usr/bin/fargo-manage' WELCO_MANAGE_COMMAND = '/usr/bin/welco-manage' +NOTIFY_COMMANDS = ['/usr/sbin/wcsctl'] + local_settings_file = os.environ.get('HOBO_AGENT_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')) if os.path.exists(local_settings_file): -- 2.1.4