def test_handle_event_status_update(self, mock_marathon): app_ids = ['app_1', 'app_2'] m = DeploymentMonitor(mock_marathon, app_ids, '') m._thread = Mock() ev = MarathonEvent({ 'appId': 'app_1', 'taskStatus': 'some_status', 'eventType': 'status_update_event' }) m._handle_event(ev) self.assertFalse(m._deployment_failed) self.assertFalse(m._deployment_succeeded)
def test_handle_event_app_not_in_list(self, mock_marathon): app_ids = ['app_X', 'app_Y'] m = DeploymentMonitor(mock_marathon, app_ids, '') m._thread = Mock() ev = MarathonEvent({ 'appId': 'app_1', 'taskStatus': 'TASK_FAILED', 'eventType': 'status_update_event', 'message': 'somemessage' }) m._handle_event(ev) self.assertFalse(m._deployment_failed) self.assertFalse(m._deployment_succeeded) self.assertFalse(m._stop_event.isSet()) self.assertFalse(m._thread.stop.called) self.assertIsNone(m._failed_event)
def _wait_for_deployment_complete(self, deployment_response, start_timestamp, log_failures=True): """ Waits for deployment to Marathon to complete. We start an instance of DeploymentMonitor that streams events from Marathon endpoint and monitors when apps fail or succeed to deploy. Monitor also logs any app status changes. """ # Get the deploymentId, so we can uniquely identify deployment # we want to monitor deployment_json = deployment_response.json() if 'deploymentId' in deployment_json: deployment_id = deployment_json['deploymentId'] elif 'deployments' in deployment_json: deployment_id = deployment_json['deployments'][0]['id'] else: raise Exception( 'Could not find "deploymentId" in {}'.format(deployment_json)) # Get the affected apps for the deployment that was started # or just return if deployment already completed. get_deployments_response = self.get_deployments().json() a_deployment = [dep for dep in get_deployments_response if dep['id'] == deployment_id] if len(a_deployment) > 0: app_ids = a_deployment[0]['affectedApps'] else: # Nothing to do return deployment_completed = False timeout_exceeded = False processor_catchup = False # Did we already give processor an extra second to finish up or not? processor = DeploymentMonitor(self, app_ids, deployment_id, log_failures) processor.start() while not deployment_completed: if self._wait_time_exceeded(self.deployment_max_wait_time, start_timestamp): timeout_exceeded = True break get_deployments_response = self.get_deployments().json() a_deployment = [dep for dep in get_deployments_response if dep['id'] == deployment_id] if len(a_deployment) == 0: if not processor_catchup: logging.debug('Giving deployment monitor more time to catch-up on events') for _ in range(0, 5): if not processor.deployment_succeeded(): time.sleep(1) # TODO:Check that the group was deployed correctly (instance count, healthcheck) processor_catchup = True continue else: deployment_completed = True break time.sleep(1) processor.stopped = True if timeout_exceeded: raise Exception('Timeout exceeded waiting for deployment to complete') if deployment_completed: logging.info('Deployment ended')
def test_not_none(self, mock_marathon): m = DeploymentMonitor(mock_marathon, [], '') self.assertIsNotNone(m)
def test_is_running_false(self, mock_marathon): m = DeploymentMonitor(mock_marathon, [], '') m._thread = Mock() m.stop() self.assertFalse(m.is_running())
def test_is_running(self, mock_marathon): m = DeploymentMonitor(mock_marathon, [], '') self.assertTrue(m.is_running())
def test_stop_called(self, mock_marathon): m = DeploymentMonitor(mock_marathon, [], '') m._thread = Mock() m.stop() self.assertTrue(m._stop_event.isSet()) self.assertTrue(m._thread.stop.called)
def test_start_called(self, mock_marathon): m = DeploymentMonitor(mock_marathon, [], '') m._thread = Mock() m.start() self.assertTrue(m._thread.start.called) self.assertTrue(m._thread.daemon)