Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
feudal
feudalBackend
Commits
f123a8cf
Commit
f123a8cf
authored
Dec 15, 2017
by
Lukas Burgey
Browse files
Fix ACKs when no client is connected
parent
00a1f04b
Changes
4
Show whitespace changes
Inline
Side-by-side
django_backend/backend/clientapi/models.py
View file @
f123a8cf
...
...
@@ -21,6 +21,7 @@ def publish_deployment(sender, instance=None, created=False, **kwargs):
instance
.
service
,
message
):
# delivery successful
instance
.
service
.
site
.
client_updated
()
print
(
'
c
lient update
d'
)
print
(
'
C
lient
got
update
for service {}'
.
format
(
instance
.
service
)
)
else
:
print
(
'client update failed'
)
print
(
'Client failed to receive update for service {}'
.
format
(
instance
.
service
))
django_backend/backend/clientapi/pubsub.py
View file @
f123a8cf
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
(
...
...
django_backend/backend/models.py
View file @
f123a8cf
...
...
@@ -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
():
def
service_deployments
(
service
):
if
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
)
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
deployments
=
{
service
.
name
:
service_deployments
(
service
)
for
service
in
self
.
services
.
all
()}
return
services
# 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
)
django_backend/backend/rabbitmq.py
View file @
f123a8cf
...
...
@@ -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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment