Commit f123a8cf authored by Lukas Burgey's avatar Lukas Burgey
Browse files

Fix ACKs when no client is connected

parent 00a1f04b
......@@ -21,6 +21,7 @@ def publish_deployment(sender, instance=None, created=False, **kwargs):
instance.service, message):
# delivery successful
instance.service.site.client_updated()
print('client updated')
print('Client got update for service {}'.format(instance.service))
else:
print('client update failed')
print('Client failed to receive update for service {}'.format(
instance.service))
import pika
from ..rabbitmq import RabbitMQInstance
class PubSubConnection:
......@@ -33,10 +34,18 @@ class PubSubConnection:
def service_routing_key(self, service):
return 'service.' + service.name
def is_client_connected(self, client):
return False
def publish_by_service(self, service, message):
if not RabbitMQInstance().is_client_connected(service.site):
print('Client for service {} is not online'.format(service))
return False
print('Client for service {} is online'.format(service))
self.connect()
print(' [x] Sent {}:{}'.format(
self.service_routing_key(service), message))
print('Sent deployment update for service {}'.format(service))
# True if the client acked the message
delivery_confirmed = self.channel.basic_publish(
......
......@@ -66,35 +66,41 @@ class Site(models.Model):
return self.name
def client_updated(self):
print("Client of site {} got updated".format(self.name))
self.last_fetch = make_aware(datetime.now())
self.save()
def clientapi_get_deployments(self, all=False):
services = {}
for service in self.services.all():
ds = (
service.deployments
# only oidcuser are supposed to have deployments
.filter(user__user_type='oidcuser')
# we do not exclude deployments without ssh_keys, as the
# ssh_keys_to_withdraw still need to be propagated
# .exclude(ssh_keys=None)
)
print(ds)
if not all:
ds = ds.filter(
last_change__gt=self.last_fetch)
def service_deployments(service):
if all:
ds = (
service.deployments
# only oidcuser are supposed to have deployments
.filter(user__user_type='oidcuser')
)
else:
ds = (
service.deployments
# only oidcuser are supposed to have deployments
.filter(user__user_type='oidcuser')
.filter(last_change__gte=self.last_fetch)
)
for deployment in ds:
# TODO replace this optimism with an acknowledgement
deployment.client_updated()
# deployments for this site
services[service.name] = ds
return ds
return services
deployments = {service.name: service_deployments(service)
for service
in self.services.all()}
# TODO we expect the client to get the update here
self.client_updated()
# deployments of the services of this site
return deployments
@receiver(post_save, sender=Site)
......@@ -198,12 +204,18 @@ class Deployment(models.Model):
)
last_change = models.DateTimeField(
auto_now=True
editable=False,
default=make_aware(datetime.utcfromtimestamp(0)),
)
def __str__(self):
return '{}@{}'.format(self.user, self.service)
def changed(self):
print("Deployment {} changed".format(self))
self.last_change = make_aware(datetime.now())
self.save()
def deploy_key(self, key):
# key state: -> (2.5)
self.ssh_keys.add(key)
......@@ -211,6 +223,7 @@ class Deployment(models.Model):
if key in self.ssh_keys_to_withdraw.all():
self.ssh_keys_to_withdraw.remove(key)
self.save()
self.changed()
self.send_change()
def withdraw_key(self, key):
......@@ -220,6 +233,7 @@ class Deployment(models.Model):
# keys which are to be withdrawn by the clients
self.ssh_keys_to_withdraw.add(key)
self.save()
self.changed()
self.send_change()
def client_updated(self):
......@@ -235,5 +249,3 @@ class Deployment(models.Model):
def send_change(self):
deployment_change.send(sender=self.__class__, instance=self)
......@@ -17,10 +17,33 @@ class RabbitMQInstance:
def get_uri(self, path):
return '{}/{}'.format(self.api, path)
def rest_get(self, api_path):
r = requests.get(
self.get_uri(api_path),
auth=self.auth)
r.raise_for_status()
return r.json()
# send a rest call with path and data to the rest interface of
# the rabbitmq instance
def rest_put(self, api_path, data):
r = requests.put(
self.get_uri(api_path),
json=data,
auth=self.auth)
r.raise_for_status()
return r
def rest_del(self, api_path):
r = requests.delete(
self.get_uri(api_path),
auth=self.auth)
r.raise_for_status()
return r
def set_topic_permissions(self, site):
username = site.client.username
set_topic_permission_uri = '{}/topic-permissions/{}/{}/'.format(
self.api,
path = 'topic-permissions/{}/{}/'.format(
self.vhost,
username,
)
......@@ -43,16 +66,12 @@ class RabbitMQInstance:
'read': '^service\.({})$'.format(services),
}
r = requests.put(
set_topic_permission_uri,
json=set_topic_permission_data, auth=self.auth)
r.raise_for_status()
return self.rest_put(path, set_topic_permission_data)
# set permissions for the user
def set_permissions(self, site):
username = site.client.username
set_permission_uri = '{}/permissions/{}/{}/'.format(
self.api,
path = 'permissions/{}/{}/'.format(
self.vhost,
username,
)
......@@ -63,40 +82,26 @@ class RabbitMQInstance:
'read': permission,
}
r = requests.put(
set_permission_uri, json=set_permission_data, auth=self.auth)
r.raise_for_status()
return self.rest_put(path, set_permission_data)
# create user at the rabbitmq instance
def create_user(self, site):
username = site.client.username
user_creation_uri = '{}/users/{}/'.format(
self.api,
username
)
path = 'users/{}/'.format(username)
user_creation_data = {
'password': str(site.client.auth_token.key),
'tags': '',
}
r = requests.put(
user_creation_uri, json=user_creation_data, auth=self.auth)
r.raise_for_status()
return self.rest_put(path, user_creation_data)
# delete user at the rabbitmq instance
def delete_user(self, site):
username = site.client.username
user_creation_uri = self.get_uri('users/{}/'.format(username))
path = 'users/{}/'.format(username)
user_creation_data = {
'password': str(site.client.auth_token.key),
'tags': '',
}
r = requests.delete(
user_creation_uri, json=user_creation_data, auth=self.auth)
r.raise_for_status()
return self.rest_del(path)
# PUBLIC API
......@@ -116,3 +121,10 @@ class RabbitMQInstance:
print('RabbitMQ: deregister: {} / {}'.format(
site.name, site.client.username))
self.delete_user(site)
def is_client_connected(self, site):
connections = self.rest_get("connections/")
client_connections = [c
for c in connections
if c['user'] == site.client.username]
return len(client_connections) > 0
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment