Commit 56172289 authored by Lukas Burgey's avatar Lukas Burgey

Refactor Deployment/Task/Item logic

parent 762f7dd8
......@@ -42,7 +42,7 @@ class DeploymentsSerializer(serializers.Serializer):
class DeploymentStateSerializer(serializers.Serializer):
id = serializers.IntegerField()
action = serializers.CharField()
state_target = serializers.CharField()
user = UserSerializer()
service = ServiceSerializer()
key = backend_serializers.SSHPublicKeySerializer()
......
......@@ -13,12 +13,18 @@ LOGGER = logging.getLogger(__name__)
AUTHENTICATION_CLASSES = (BasicAuthentication, )
# The client fetches pending tasks
class DeploymentsView(generics.ListAPIView):
authentication_classes = AUTHENTICATION_CLASSES
serializer_class = DeploymentStateSerializer
def get_queryset(self):
return self.request.user.site.states
items = self.request.user.site.state_items.filter(
state='deployment_pending',
) | self.request.user.site.state_items.filter(
state='removal_pending',
)
return [item.tasks for item in items]
# the client has to fetch the configuration (like services etc.) here
......@@ -45,8 +51,11 @@ class AckView(views.APIView):
def delete(self, request, state_id=None):
# find the corresponding state for this item
for item in request.user.site.state_items.all():
if item.state.id == int(state_id):
item.success()
if item.parent.id == int(state_id):
if item.parent.state_target == 'deployed':
item.client_deployed()
else:
item.client_removed()
return Response({'ok': True})
# this is no critical
......@@ -62,29 +71,37 @@ class ResponseView(views.APIView):
status = output['status']
state_id = request.data['id']
LOGGER.debug('%s responded to state %s:\n%s', request.user, state_id, request.data)
# LOGGER.debug('%s responded to state %s:\n%s', request.user, state_id, request.data)
# find the corresponding state for this item
state_item = None
for item in request.user.site.state_items.all():
if item.state.id == int(state_id):
if item.parent.id == int(state_id):
state_item = item
if state_item is not None:
if status == 'success':
state_item.success(
credentials=request.data.output.get('credentials', None),
if status == 'deployed':
state_item.client_deployed(
credentials=output.get('credentials', None),
)
return Response({})
elif status == 'fail':
state_item.failed()
elif status == 'removed':
state_item.client_removed()
return Response({})
elif status == 'reject':
state_item.rejected(output['questionnaire'])
elif status == 'questionnaire':
state_item.client_questionnaire(
output['questionnaire'],
)
return Response({})
LOGGER.error("Unrecognized response status from client: %s", status)
return Response(
data={'error': 'unknown status'},
status=500,
)
LOGGER.info('%s executed the obsolete state#%s', request.user, state_id)
return Response(
data={'error': 'obsolete_state'},
......
......@@ -29,7 +29,7 @@ class DeploymentStateItemSerializer(serializers.ModelSerializer):
class Meta:
model = models.DeploymentStateItem
fields = [
'action',
'state_target',
'key',
'service',
'site',
......@@ -45,7 +45,7 @@ class DeploymentStateSerializer(serializers.ModelSerializer):
class Meta:
model = models.DeploymentState
fields = [
'action',
'state_target',
'key',
'service',
'id',
......@@ -56,8 +56,8 @@ class DeploymentSerializer(serializers.Serializer):
service = ServiceSerializer()
ssh_keys = backend_serializers.SSHPublicKeySerializer(many=True)
ssh_keys_to_withdraw = backend_serializers.SSHPublicKeySerializer(many=True)
deploys = DeploymentStateSerializer(many=True)
withdrawals = DeploymentStateSerializer(many=True)
# deploys = DeploymentStateSerializer(many=True)
# removals = DeploymentStateSerializer(many=True)
class Meta:
model = models.Deployment
......
......@@ -121,7 +121,7 @@ class DeploymentView(views.APIView):
if request_type == 'add':
deployment.deploy_key(request_key)
elif request_type == 'remove':
deployment.withdraw_key(request_key)
deployment.remove_key(request_key)
else:
return _api_error_response()
......
This diff is collapsed.
......@@ -111,34 +111,35 @@ class DeploymentTest(TestCase):
key = models.SSHPublicKey.objects.get(name=TEST_NAME)
service = models.Service.objects.get(name=TEST_SERVICE)
deployment = models.Deployment.get_deployment(user, service)
deployment = models.Deployment.get_deployment(
user,
service,
)
self.assertIsNotNone(deployment)
# no states exist yet
self.assertFalse(deployment.deploys.exists())
self.assertFalse(deployment.withdrawals.exists())
models.DeploymentState.construct_deployment_state(
state = models.DeploymentState.get_state(
deployment=deployment,
key=key,
)
self.assertIsNotNone(state)
# one deploy should exist
self.assertTrue(deployment.deploys.exists())
self.assertFalse(deployment.withdrawals.exists())
deployment.deploy_key(key)
models.DeploymentState.construct_withdrawal_state(
deployment=deployment,
key=key,
)
# one withdraw should exist
self.assertFalse(deployment.deploys.exists())
self.assertTrue(deployment.withdrawals.exists())
self.assertFalse(state.target_reached)
# execute deployment
for item in state.state_items.all():
item.client_deployed()
self.assertTrue(state.target_reached)
# start removal
state.remove()
self.assertFalse(state.target_reached)
# "execute" the withdrawals
for state in deployment.withdrawals.all():
for item in state.state_items.all():
item.success()
# execute removals
for item in state.state_items.all():
item.client_removed()
self.assertFalse(deployment.deploys.exists())
self.assertFalse(deployment.withdrawals.exists())
self.assertTrue(state.target_reached)
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