Commit fed72fb7 authored by Lukas Burgey's avatar Lukas Burgey

Refactor the client response handling

parent 1c64600c
......@@ -4,6 +4,5 @@ from . import views
URLPATTERNS = [
url(r'^deployments', views.DeploymentsView.as_view()),
url(r'^config', views.ConfigurationView.as_view()),
url(r'^ack/(?P<state_id>\d+)', views.AckView.as_view()),
url(r'^response', views.ResponseView.as_view()),
]
......@@ -40,64 +40,37 @@ class ConfigurationView(views.APIView):
return Response(response)
class AckView(views.APIView):
authentication_classes = AUTHENTICATION_CLASSES
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.parent.id == int(state_id):
if item.parent.state_target == 'deployed':
item.client_deployed({})
else:
item.client_removed()
return Response({})
LOGGER.info('%s executed the obsolete state#%s', request.user, state_id)
return Response(
data={'error': 'obsolete_state'},
status=500,
)
class ResponseView(views.APIView):
authentication_classes = AUTHENTICATION_CLASSES
def post(self, request):
output = request.data['output']
status = output['status']
state_id = request.data['id']
output = request.data.get('output', {})
state_id = request.data.get('id', None)
# LOGGER.debug('%s responded to state %s:\n%s', request.user, state_id, request.data)
if state_id is None:
err = 'no state id'
LOGGER.error('Error parsing response from %s: %s', request.user, err)
return Response(
data={'error': err},
status=500,
)
# find the corresponding state for this item
state_item = None
for item in request.user.site.state_items.all():
if item.parent.id == int(state_id):
state_item = item
break
if state_item is not None:
if status == 'deployed':
state_item.client_deployed(
credentials=output.get('credentials', {}),
err = state_item.client_response(output)
if err is not None:
LOGGER.error('Error parsing response from %s: %s', request.user, err)
return Response(
data={'error': err},
status=500,
)
return Response({})
elif status == 'removed':
state_item.client_removed()
return Response({})
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,
)
return Response({})
LOGGER.info('%s executed the obsolete state#%s', request.user, state_id)
return Response(
......
......@@ -26,6 +26,8 @@ STATE_CHOICES = (
('deployed', 'Deployed'),
('not_deployed', 'Not Deployed'),
('questionnaire', 'Questionnaire'),
('failed', 'Failed'),
('rejected', 'Rejected'),
)
......@@ -877,31 +879,39 @@ class DeploymentStateItem(models.Model):
self._set_state('deployment_pending')
self.parent.publish_to_client()
# client: deployed
def client_deployed(self, credentials=None):
self.credentials = credentials
self._set_state('deployed')
# returns None on success, or a string describing an error
def client_response(self, output):
status = output.get('status', 'undefined')
if status != 'undefined':
# update values
if status == 'deployed':
self.credentials = output.get('credentials', {})
elif status == 'removed':
self.credentials = credential_default()
self.questionnaire = questionnaire_default()
elif status == 'questionnaire':
self.questionnaire = output.get('questionnaire', {})
elif status == 'rejected':
pass
elif status == 'failed':
pass
else:
return 'unknown state '+status
self._set_state(status)
return None
return 'missing status in output'
# client: removed
def client_removed(self):
# TODO check if all values are reset correctly
self.credentials = credential_default()
self.questionnaire = questionnaire_default()
self._set_state('not_deployed')
# this removal maybe was the last of out ssh key
self.key.try_final_deletion()
# client: questionnaire
def client_questionnaire(self, questionnaire=None):
self.questionnaire = questionnaire
self._set_state('questionnaire')
def msg(self, msg):
return '[DSItem:{}] {}'.format(self, msg)
def _set_state(self, state):
if self.state == 'rejected':
LOGGER.info('refusing to change state of rejected state_item')
self.save()
return
self.state = state
self.save()
LOGGER.debug(self.msg('state: '+self.state))
......
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