Commit c307f65b authored by Lukas Burgey's avatar Lukas Burgey

Make deployment by vo work again

parent f20e7cfc
...@@ -2,15 +2,69 @@ ...@@ -2,15 +2,69 @@
# pylint: disable=abstract-method # pylint: disable=abstract-method
from rest_framework import serializers from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer
from .. import OIDCConfig from .. import OIDCConfig
from ..vo import VO, Group, Entitlement, EntitlementNameSpace
class OIDCConfigSerializer(serializers.ModelSerializer): class OIDCConfigSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = OIDCConfig model = OIDCConfig
fields = ['name', 'id'] fields = (
'name',
'id',
)
class AuthInfoSerializer(serializers.Serializer): class AuthInfoSerializer(serializers.Serializer):
idps = OIDCConfigSerializer(many=True) idps = OIDCConfigSerializer(many=True)
default = serializers.IntegerField() default = serializers.IntegerField()
class EntitlementNameSpaceSerializer(serializers.ModelSerializer):
class Meta:
model = EntitlementNameSpace
fields = (
'name',
)
# polymorphic serializer
VO_FIELDS = (
'id',
'name',
'pretty_name',
'description',
)
class AbstractVOSerializer(serializers.ModelSerializer):
class Meta:
model = VO
fields = VO_FIELDS
class GroupSerializer(serializers.ModelSerializer):
class Meta:
model = Group
fields = VO_FIELDS
class EntitlementSerializer(serializers.ModelSerializer):
name_space = EntitlementNameSpaceSerializer()
class Meta:
model = Entitlement
fields = VO_FIELDS + (
'name_space',
'group_authority',
)
class VOSerializer(PolymorphicSerializer):
model_serializer_mapping = {
VO: AbstractVOSerializer,
Group: GroupSerializer,
Entitlement: EntitlementSerializer,
}
...@@ -13,10 +13,7 @@ class EntitlementNameSpaceSerializer(serializers.ModelSerializer): ...@@ -13,10 +13,7 @@ class EntitlementNameSpaceSerializer(serializers.ModelSerializer):
# polymorphic serializer # polymorphic serializer
VO_FIELDS = ( VO_FIELDS = (
'id',
'name', 'name',
'pretty_name',
'description',
) )
......
...@@ -6,7 +6,7 @@ from django.db import models ...@@ -6,7 +6,7 @@ from django.db import models
# these imports are exports! # these imports are exports!
from ..auth.v1.models.vo import VO from ..auth.v1.models.vo import VO
from .brokers import RabbitMQInstance from .brokers import RabbitMQInstance
from .users import User from .users import User, SSHPublicKey
LOGGER = getLogger(__name__) LOGGER = getLogger(__name__)
...@@ -36,10 +36,9 @@ class Site(models.Model): ...@@ -36,10 +36,9 @@ class Site(models.Model):
blank=True, blank=True,
) )
# tasks is what we send to the clients. the are the serialization of a deployment
@property @property
def pending_tasks(self): def pending_deployments(self):
tasks = {} deployments = {}
# ignores orphaned deployment states # ignores orphaned deployment states
dep_states = [ dep_states = [
...@@ -50,11 +49,11 @@ class Site(models.Model): ...@@ -50,11 +49,11 @@ class Site(models.Model):
) and state.parent is not None ) and state.parent is not None
] ]
# make the tasks unique here # make the deployments unique here
for item in dep_states: for item in dep_states:
tasks[item.parent.id] = item.parent deployments[item.parent.id] = item.parent
return tasks.values() return deployments.values()
def __str__(self): def __str__(self):
return self.name return self.name
......
...@@ -152,6 +152,14 @@ class RabbitMQInstance(SingletonModel): ...@@ -152,6 +152,14 @@ class RabbitMQInstance(SingletonModel):
def initialize(self): def initialize(self):
self._connection self._connection
def publish(self, deployment, msg):
self._publish(
deployment.broker_exchange,
deployment.routing_key,
msg,
)
def publish_by_service(self, service, msg): def publish_by_service(self, service, msg):
self._publish( self._publish(
'services', 'services',
......
...@@ -48,6 +48,19 @@ def credential_default(): ...@@ -48,6 +48,19 @@ def credential_default():
return {} return {}
def get_deployment(user, vo=None, service=None):
if vo is not None and service is not None:
raise ValueError('Cannot create deployment for both vo and service')
if vo is not None:
return VODeployment.get_deployment(user, vo)
if service is not None:
return ServiceDeployment.get_deployment(user, service)
raise ValueError('Need vo or service to create deployment')
class Deployment(PolymorphicModel): class Deployment(PolymorphicModel):
user = models.ForeignKey( user = models.ForeignKey(
User, User,
...@@ -91,14 +104,14 @@ class Deployment(PolymorphicModel): ...@@ -91,14 +104,14 @@ class Deployment(PolymorphicModel):
return self.state_target == self.state return self.state_target == self.state
def _set_target(self, target): def _set_target(self, target):
LOGGER.debug(self.msg('Target changed to '+target))
self.state_target = target self.state_target = target
for credential_state in CredentialState.objects.filter( for credential_state in CredentialState.objects.filter(
target__parent=self, target__parent=self,
): ):
credential_state.set_target(target) credential_state.set_target(target)
LOGGER.debug(self.msg('Target changed to '+target))
self.save() self.save()
def user_deploy(self): def user_deploy(self):
...@@ -129,26 +142,23 @@ class Deployment(PolymorphicModel): ...@@ -129,26 +142,23 @@ class Deployment(PolymorphicModel):
self.publish() self.publish()
def publish_to_client(self): def publish_to_client(self):
# avoiding circular dependencies here from .serializers import clients
# from .serializers.clients import DeploymentSerializer data = clients.DeploymentSerializer(self).data
# data = DeploymentSerializer(self).data msg = dumps(data)
# msg = dumps(data)
# # backend.RabbitMQInstance.load().publish_by_vo( RabbitMQInstance.load().publish(
# self.vo, self,
# msg, msg,
# ) )
pass
# sends a state update via RabbitMQ / STOMP to the users webpage instance # sends a state update via RabbitMQ / STOMP to the users webpage instance
def publish_to_user(self): def publish_to_user(self):
if self.user is None: if self.user is None:
return return
# avoiding circular dependencies here from . import serializers
from .serializers.webpage import DeploymentSerializer
msg = dumps({ msg = dumps({
'deployment': DeploymentSerializer(self).data, 'deployment': serializers.DeploymentSerializer(self).data,
}) })
RabbitMQInstance.load().publish_to_user( RabbitMQInstance.load().publish_to_user(
self.user, self.user,
...@@ -180,14 +190,21 @@ class VODeployment(Deployment): ...@@ -180,14 +190,21 @@ class VODeployment(Deployment):
def services(self): def services(self):
return self.vo.services.all() return self.vo.services.all()
@property
def broker_exchange(self):
return self.vo.broker_exchange
@property
def routing_key(self):
return self.vo.name
def create_state_items(self): def create_state_items(self):
for service in self.services: for service in self.services:
LOGGER.debug('create_state_items: creating DeploymentState for service %s at site %s', service, service.site)
DeploymentState.get_state_item( DeploymentState.get_state_item(
parent=self, self,
user=self.user, self.user,
site=service.site, service.site,
service=service, service,
) )
@classmethod @classmethod
...@@ -210,15 +227,16 @@ class VODeployment(Deployment): ...@@ -210,15 +227,16 @@ class VODeployment(Deployment):
deployment.save() deployment.save()
deployment.create_state_items() deployment.create_state_items()
LOGGER.debug(deployment.msg('created')) LOGGER.debug(deployment.msg('Created'))
return deployment return deployment
def service_added(self, service): def service_added(self, service):
LOGGER.debug(self.msg('Adding service {}'.format(service))) LOGGER.debug(self.msg('Adding service {}'.format(service)))
item = DeploymentState.get_state_item( item = DeploymentState.get_state_item(
parent=self, self,
site=service.site, self.user,
service=service, service.site,
service,
) )
if self.state_target == 'deployed': if self.state_target == 'deployed':
item.user_deploy() item.user_deploy()
...@@ -230,17 +248,6 @@ class VODeployment(Deployment): ...@@ -230,17 +248,6 @@ class VODeployment(Deployment):
def msg(self, msg): def msg(self, msg):
return '{} - {}'.format(self, msg) return '{} - {}'.format(self, msg)
def _set_target(self, target):
self.state_target = target
for credential_state in CredentialState.objects.filter(
target__parent=self,
):
credential_state.set_target(target)
LOGGER.debug(self.msg('Target changed to '+target))
self.save()
def __str__(self): def __str__(self):
return 'VO-Dep: ({}:{})#{}'.format( return 'VO-Dep: ({}:{})#{}'.format(
self.vo, self.vo,
...@@ -256,13 +263,21 @@ class ServiceDeployment(Deployment): ...@@ -256,13 +263,21 @@ class ServiceDeployment(Deployment):
on_delete=models.CASCADE, on_delete=models.CASCADE,
) )
@property
def broker_exchange(self):
return 'services'
@property
def routing_key(self):
return self.service.name
def create_state_item(self): def create_state_item(self):
LOGGER.debug('create_state_item: creating DeploymentState for service %s at site %s', self.service, self.service.site) LOGGER.debug('create_state_item: creating DeploymentState for service %s at site %s', self.service, self.service.site)
DeploymentState.get_state_item( DeploymentState.get_state_item(
parent=self, self,
user=self.user, self.user,
site=self.service.site, self.service.site,
service=self.service, self.service,
) )
@classmethod @classmethod
...@@ -272,7 +287,7 @@ class ServiceDeployment(Deployment): ...@@ -272,7 +287,7 @@ class ServiceDeployment(Deployment):
user=user, user=user,
service=service, service=service,
) )
deployment.create_state_items() deployment.create_state_item()
return deployment return deployment
...@@ -285,37 +300,12 @@ class ServiceDeployment(Deployment): ...@@ -285,37 +300,12 @@ class ServiceDeployment(Deployment):
deployment.save() deployment.save()
deployment.create_state_item() deployment.create_state_item()
LOGGER.debug(deployment.msg('created')) LOGGER.debug(deployment.msg('Created'))
return deployment return deployment
def service_added(self, service):
LOGGER.debug(self.msg('Adding service {}'.format(service)))
item = DeploymentState.get_state_item(
parent=self,
site=service.site,
service=service,
)
if self.state_target == 'deployed':
item.user_deploy()
def service_removed(self, service):
LOGGER.debug(self.msg('Removing service {}'.format(service)))
LOGGER.debug('TODO implement service removal')
def msg(self, msg): def msg(self, msg):
return '{} - {}'.format(self, msg) return '{} - {}'.format(self, msg)
def _set_target(self, target):
self.state_target = target
for credential_state in CredentialState.objects.filter(
target__parent=self,
):
credential_state.set_target(target)
LOGGER.debug(self.msg('Target changed to '+target))
self.save()
def __str__(self): def __str__(self):
return 'Service-Dep: ({}:{})#{}'.format( return 'Service-Dep: ({}:{})#{}'.format(
self.service, self.service,
...@@ -405,15 +395,8 @@ class DeploymentState(models.Model): ...@@ -405,15 +395,8 @@ class DeploymentState(models.Model):
def user_credentials(self): def user_credentials(self):
return self.user.credentials return self.user.credentials
@property
def vo(self):
if self.parent is not None:
return self.parent.vo
else:
raise self.parentless
@classmethod @classmethod
def get_state_item(cls, parent=None, user=None, site=None, service=None): def get_state_item(cls, parent, user, site, service):
try: try:
item = cls.objects.get( item = cls.objects.get(
parent=parent, parent=parent,
...@@ -432,7 +415,7 @@ class DeploymentState(models.Model): ...@@ -432,7 +415,7 @@ class DeploymentState(models.Model):
) )
item.save() item.save()
LOGGER.debug('get_state_item: created %s', item) LOGGER.debug(item.msg('Created'))
return item return item
# starts tracking this the credential for this item # starts tracking this the credential for this item
......
...@@ -2,15 +2,12 @@ ...@@ -2,15 +2,12 @@
from rest_framework import serializers from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer from rest_polymorphic.serializers import PolymorphicSerializer
from feudal.backend.auth.v1.models.serializers.vo import VOSerializer from feudal.backend.auth.v1.models.serializers import VOSerializer
from ...models import Site, Service from ...models import Site, Service
from ..users import User, SSHPublicKey from ..users import User, SSHPublicKey
from ..deployments import CredentialState, DeploymentState, Deployment, VODeployment, ServiceDeployment from ..deployments import CredentialState, DeploymentState, Deployment, VODeployment, ServiceDeployment
# export
from .clients import RabbitMQInstanceSerializer
class SSHPublicKeySerializer(serializers.ModelSerializer): class SSHPublicKeySerializer(serializers.ModelSerializer):
class Meta: class Meta:
...@@ -31,23 +28,6 @@ class SSHPublicKeyRefSerializer(serializers.ModelSerializer): ...@@ -31,23 +28,6 @@ class SSHPublicKeyRefSerializer(serializers.ModelSerializer):
] ]
class CredentialSerializer(serializers.ModelSerializer):
class Meta:
model = SSHPublicKey
fields = [
'id',
'name',
'value',
]
CREDENTIAL_SERIALIZER = serializers.DictField(
child=serializers.ListField(
child=CredentialSerializer()
)
)
class CredentialStateSerializer(serializers.ModelSerializer): class CredentialStateSerializer(serializers.ModelSerializer):
credential = SSHPublicKeyRefSerializer() credential = SSHPublicKeyRefSerializer()
...@@ -61,7 +41,6 @@ class CredentialStateSerializer(serializers.ModelSerializer): ...@@ -61,7 +41,6 @@ class CredentialStateSerializer(serializers.ModelSerializer):
] ]
class SiteSerializer(serializers.ModelSerializer): class SiteSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Site model = Site
...@@ -88,7 +67,6 @@ class DeploymentStateSerializer(serializers.ModelSerializer): ...@@ -88,7 +67,6 @@ class DeploymentStateSerializer(serializers.ModelSerializer):
site = SiteSerializer() site = SiteSerializer()
questionnaire = serializers.JSONField() questionnaire = serializers.JSONField()
credentials = serializers.JSONField() credentials = serializers.JSONField()
vo = VOSerializer()
credential_states = CredentialStateSerializer(many=True) credential_states = CredentialStateSerializer(many=True)
class Meta: class Meta:
...@@ -100,7 +78,6 @@ class DeploymentStateSerializer(serializers.ModelSerializer): ...@@ -100,7 +78,6 @@ class DeploymentStateSerializer(serializers.ModelSerializer):
'questionnaire', 'questionnaire',
'credentials', 'credentials',
'service', 'service',
'vo',
'message', 'message',
'credential_states', 'credential_states',
'is_credential_pending', 'is_credential_pending',
...@@ -109,16 +86,13 @@ class DeploymentStateSerializer(serializers.ModelSerializer): ...@@ -109,16 +86,13 @@ class DeploymentStateSerializer(serializers.ModelSerializer):
DEPLOYMENT_FIELDS = ( DEPLOYMENT_FIELDS = (
'id',
'state_target', 'state_target',
'id', 'id',
'state_items', 'state_items',
'credentials',
) )
class AbstractDeploymentSerializer(serializers.ModelSerializer): class AbstractDeploymentSerializer(serializers.ModelSerializer):
credentials = CredentialSerializer
state_items = DeploymentStateSerializer(many=True) state_items = DeploymentStateSerializer(many=True)
class Meta: class Meta:
...@@ -127,6 +101,10 @@ class AbstractDeploymentSerializer(serializers.ModelSerializer): ...@@ -127,6 +101,10 @@ class AbstractDeploymentSerializer(serializers.ModelSerializer):
class VODeploymentSerializer(serializers.ModelSerializer): class VODeploymentSerializer(serializers.ModelSerializer):
state_items = DeploymentStateSerializer(many=True)
vo = VOSerializer()
services = ServiceSerializer(many=True)
class Meta: class Meta:
model = VODeployment model = VODeployment
fields = DEPLOYMENT_FIELDS + ( fields = DEPLOYMENT_FIELDS + (
...@@ -136,7 +114,8 @@ class VODeploymentSerializer(serializers.ModelSerializer): ...@@ -136,7 +114,8 @@ class VODeploymentSerializer(serializers.ModelSerializer):
class ServiceDeploymentSerializer(serializers.ModelSerializer): class ServiceDeploymentSerializer(serializers.ModelSerializer):
state_items = DeploymentStateSerializer(many=True)
service = ServiceSerializer()
class Meta: class Meta:
model = ServiceDeployment model = ServiceDeployment
fields = DEPLOYMENT_FIELDS + ( fields = DEPLOYMENT_FIELDS + (
...@@ -160,16 +139,15 @@ class UserSerializer(serializers.ModelSerializer): ...@@ -160,16 +139,15 @@ class UserSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = User model = User
fields = [ fields = [
'profile_name',
'vos',
'id', 'id',
'profile_name',
'ssh_keys', 'ssh_keys',
'userinfo', 'userinfo',
'vos',
] ]
class UserStateSerializer(serializers.ModelSerializer): class UserStateSerializer(serializers.ModelSerializer):
vos = VOSerializer(many=True) vos = VOSerializer(many=True)
ssh_keys = SSHPublicKeySerializer(many=True) ssh_keys = SSHPublicKeySerializer(many=True)
deployments = DeploymentSerializer(many=True) deployments = DeploymentSerializer(many=True)
...@@ -179,10 +157,15 @@ class UserStateSerializer(serializers.ModelSerializer): ...@@ -179,10 +157,15 @@ class UserStateSerializer(serializers.ModelSerializer):
model = User model = User
fields = [ fields = [
'deployments', 'deployments',
'profile_name',
'vos',
'id', 'id',
'profile_name',
'services',
'ssh_keys', 'ssh_keys',
'userinfo', 'userinfo',
'services', 'vos',
] ]
class StateSerializer(serializers.Serializer):
error = serializers.CharField(allow_blank=True, required=False)
user = UserStateSerializer()
...@@ -3,36 +3,100 @@ ...@@ -3,36 +3,100 @@
from django_mysql.models import JSONField from django_mysql.models import JSONField
from rest_framework import serializers from rest_framework import serializers
from rest_polymorphic.serializers import PolymorphicSerializer
from feudal.backend.auth.v1.models.serializers.vo import VOSerializer from feudal.backend.auth.v1.models.serializers.clients import VOSerializer
from ... import models from .. import Service, SSHPublicKey, User, RabbitMQInstance, deployments
class ServiceSerializer(serializers.ModelSerializer): class ServiceSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = models.Service model = Service
fields = [ fields = [
'name', 'name',
] ]
class CredentialSerializer(serializers.ModelSerializer):
class Meta:
model = SSHPublicKey
fields = [
'id',
'name',