def test_view_manifest(self, url_root): """ Viewing the manifest of an existant group returns whatever the implementation's `view_manifest()` method returns, in string format """ manifest = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'scalingPolicies': { "5": policy_examples()[0] }, 'id': 'one' } self.mock_group.view_manifest.return_value = defer.succeed(manifest) response_body = self.assert_status_code(200, method="GET") resp = json.loads(response_body) validate(resp, rest_schemas.create_and_manifest_response) expected_policy = policy_examples()[0] expected_policy.update({ "id": "5", "links": [ { "href": "/v1.0/11111/groups/one/policies/5/", "rel": "self" }, ] }) expected = { 'group': { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'scalingPolicies': [expected_policy], "id": "one", "links": [{ "href": "/v1.0/11111/groups/one/", "rel": "self" }] } } self.assertEqual(resp, expected) self.mock_store.get_scaling_group.assert_called_once_with( mock.ANY, '11111', 'one') self.mock_group.view_manifest.assert_called_once_with()
def test_create_group_normalizes_launch_config_null_server_metadata(self): """ If the user passes in null for server metadata in the launch config, create group first normalizes it before calling the model """ config = config_examples()[0] launch = launch_examples()[0] launch['args']['server']['metadata'] = None expected_launch = launch_examples()[0] expected_launch['args']['server'].pop('metadata', None) rval = { 'groupConfiguration': config, 'launchConfiguration': expected_launch, 'id': '1', 'state': GroupState('11111', '2', '', {}, {}, None, {}, False), 'scalingPolicies': [] } self.mock_store.create_scaling_group.return_value = defer.succeed(rval) self.assert_status_code( 201, None, 'POST', json.dumps({ 'groupConfiguration': config, 'launchConfiguration': launch }), '/v1.0/11111/groups/1/') self.mock_store.create_scaling_group.assert_called_once_with( mock.ANY, mock.ANY, mock.ANY, expected_launch, None)
def test_create_group_propagates_modify_state_errors(self): """ If there is an error when modify state is called, even if the group creation succeeds, a 500 is returned. """ self.mock_group.modify_state.side_effect = AssertionError config = config_examples()[0] launch = launch_examples()[0] self.mock_store.create_scaling_group.return_value = defer.succeed({ 'groupConfiguration': config, 'launchConfiguration': launch, 'scalingPolicies': {}, 'id': '1' }) self.assert_status_code(500, None, 'POST', body=json.dumps({ 'groupConfiguration': config, 'launchConfiguration': launch })) self.flushLoggedErrors(AssertionError)
def test_view_manifest(self): """ Viewing the manifest of an existant group returns whatever the implementation's `view_manifest()` method returns, in string format """ manifest = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'id': 'one', 'state': GroupState('11111', '1', '', {}, {}, None, {}, False), 'scalingPolicies': [dict(id="5", **policy_examples()[0])] } self.mock_group.view_manifest.return_value = defer.succeed(manifest) response_body = self.assert_status_code(200, method="GET") resp = json.loads(response_body) validate(resp, rest_schemas.create_and_manifest_response) expected_policy = policy_examples()[0] expected_policy.update({ "id": "5", "links": [ {"href": "/v1.0/11111/groups/one/policies/5/", "rel": "self"}, ] }) expected = { 'group': { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'scalingPolicies': [expected_policy], "id": "one", "links": [ {"href": "/v1.0/11111/groups/one/", "rel": "self"} ], 'scalingPolicies_links': [ {"href": "/v1.0/11111/groups/one/policies/", "rel": "policies"} ], 'state': manifest['state'] } } self.assertEqual(resp, expected) self.mock_store.get_scaling_group.assert_called_once_with( mock.ANY, '11111', 'one') self.mock_group.view_manifest.assert_called_once_with(False)
def test_group_create_many_policies(self): """ Tries to create a scaling group """ self._test_successful_create({ 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'scalingPolicies': policy_examples() })
def test_group_create_no_scaling_policies(self): """ Tries to create a scaling group, but if no scaling policy is provided the the interface is called with None in place of scaling policies """ self._test_successful_create({ 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], })
def test_group_create_one_policy(self): """ Tries to create a scaling group """ self._test_successful_create({ 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'scalingPolicies': [policy_examples()[0]] })
def test_create_invalid_launch_config(self): """ Invalid launch configuration raises 400 """ self.supervisor.validate_launch_config.return_value = defer.fail( InvalidLaunchConfiguration('meh')) request_body = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0] } self.assert_status_code(400, method='POST', body=json.dumps(request_body)) self.flushLoggedErrors()
def test_create_unknown_error_is_500(self): """ If an unexpected exception is raised, endpoint returns a 500. """ error = DummyException('what') request_body = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0] } self.mock_store.create_scaling_group.return_value = defer.fail(error) self.assert_status_code(500, method="POST", body=json.dumps(request_body)) self.flushLoggedErrors()
def test_create_invalid_server_metadata_in_launch_config(self): """ Invalid launch configuration raises 400 """ launch = launch_examples()[0] launch['args']['server']['metadata'] = "invalid" request_body = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch } self.assert_status_code(400, method='POST', body=json.dumps(request_body)) self.flushLoggedErrors()
def test_launch_config_modify_bad_schema_400(self): """ Checks that an update with PUT data with the wrong schema fails with a 400 """ invalids = (config_examples()[0], {"type": "launch_server", "args": {}}) for request_body in invalids: self.mock_group.update_launch_config.return_value = None response_body = self.assert_status_code( 400, method='PUT', body=json.dumps(request_body)) resp = json.loads(response_body) self.assertEqual(resp['error']['type'], 'ValidationError') self.assertFalse(self.mock_group.update_launch_config.called) self.flushLoggedErrors(ValidationError)
def test_launch_config_modify_bad_schema_400(self): """ Checks that an update with PUT data with the wrong schema fails with a 400 """ invalids = (config_examples()[0], { "type": "launch_server", "args": {} }) for request_body in invalids: self.mock_group.update_launch_config.return_value = None response_body = self.assert_status_code( 400, method='PUT', body=json.dumps(request_body)) resp = json.loads(response_body) self.assertEqual(resp['type'], 'ValidationError') self.assertFalse(self.mock_group.update_launch_config.called) self.flushLoggedErrors(ValidationError)
def test_group_create_calls_obey_config_changes(self): """ If the group creation succeeds, ``obey_config_change`` is called with the updated log, transaction id, config, group, and state """ config = config_examples()[0] expected_config = config.copy() expected_config.setdefault('maxEntities', 25) expected_config.setdefault('metadata', {}) manifest = { 'groupConfiguration': expected_config, 'launchConfiguration': launch_examples()[0], } self.mock_store.create_scaling_group.return_value = defer.succeed(manifest) self._test_successful_create(manifest) self.mock_group.modify_state.assert_called_once_with(mock.ANY) self.mock_controller.obey_config_change.assert_called_once_with( mock.ANY, "transaction-id", expected_config, self.mock_group, self.mock_state)
def test_group_create_calls_obey_config_changes(self): """ If the group creation succeeds, ``obey_config_change`` is called with the updated log, transaction id, config, group, and state """ config = config_examples()[0] expected_config = config.copy() expected_config.setdefault('maxEntities', 25) expected_config.setdefault('metadata', {}) manifest = { 'groupConfiguration': expected_config, 'launchConfiguration': launch_examples()[0], } self.mock_store.create_scaling_group.return_value = defer.succeed( manifest) self._test_successful_create(manifest) self.mock_group.modify_state.assert_called_once_with(mock.ANY) self.mock_controller.obey_config_change.assert_called_once_with( mock.ANY, "transaction-id", expected_config, self.mock_group, self.mock_state)
# ----- schemas for group creation create_group_request = { "type": "object", "description": "Schema of the JSON used to create a scaling group.", "properties": { "groupConfiguration": config, "launchConfiguration": launch_config, "scalingPolicies": create_policies_request }, "additionalProperties": False } create_group_request_examples = [ { "groupConfiguration": config_examples()[0], "launchConfiguration": launch_server_config_examples()[0] }, { "groupConfiguration": config_examples()[0], "launchConfiguration": launch_server_config_examples()[0], "scalingPolicies": [policy_examples()[0]] }, { "groupConfiguration": config_examples()[1], "launchConfiguration": launch_server_config_examples()[1], "scalingPolicies": policy_examples()[1:3] } ] # the response from creating a group and the response for viewing the manifest
def test_view_manifest_with_webhooks(self): """ `view_manifest` gives webhooks information in policies if query args contains ?webhooks=true """ manifest = { 'groupConfiguration': config_examples()[0], 'launchConfiguration': launch_examples()[0], 'id': 'one', 'state': GroupState('11111', '1', '', {}, {}, None, {}, False), 'scalingPolicies': [dict(id="5", **policy_examples()[0]), dict(id="6", **policy_examples()[1])] } webhooks = [ [ { 'id': '3', 'name': 'three', 'metadata': {}, 'capability': {"version": "1", 'hash': 'xxx'} }, { 'id': '4', 'name': 'four', 'metadata': {}, 'capability': {"version": "1", 'hash': 'yyy'} } ], [ { 'id': '5', 'name': 'five', 'metadata': {}, 'capability': {"version": "1", 'hash': 'xxx'} }, { 'id': '6', 'name': 'six', 'metadata': {}, 'capability': {"version": "1", 'hash': 'yyy'} } ] ] webhooks_internal_links = [ [[{"href": '/v1.0/11111/groups/one/policies/5/webhooks/3/', "rel": "self"}, {"href": '/v1.0/execute/1/xxx/', "rel": "capability"}], [{"href": '/v1.0/11111/groups/one/policies/5/webhooks/4/', "rel": "self"}, {"href": '/v1.0/execute/1/yyy/', "rel": "capability"}]], [[{"href": '/v1.0/11111/groups/one/policies/6/webhooks/5/', "rel": "self"}, {"href": '/v1.0/execute/1/xxx/', "rel": "capability"}], [{"href": '/v1.0/11111/groups/one/policies/6/webhooks/6/', "rel": "self"}, {"href": '/v1.0/execute/1/yyy/', "rel": "capability"}]] ] webhooks_links = [ [{'href': '/v1.0/11111/groups/one/policies/5/webhooks/', 'rel': 'webhooks'}], [{'href': '/v1.0/11111/groups/one/policies/6/webhooks/', 'rel': 'webhooks'}] ] manifest['scalingPolicies'][0]['webhooks'] = webhooks[0] manifest['scalingPolicies'][1]['webhooks'] = webhooks[1] self.mock_group.view_manifest.return_value = defer.succeed(manifest) response_body = self.assert_status_code( 200, endpoint="{0}?webhooks=true".format(self.endpoint), method="GET") resp = json.loads(response_body) validate(resp, rest_schemas.create_and_manifest_response) exp_policies = deepcopy(manifest['scalingPolicies']) for i in [0, 1]: exp_policies[i]['webhooks'] = deepcopy(webhooks[i]) for j, webhook in enumerate(exp_policies[i]['webhooks']): exp_policies[i]['webhooks'][j]['links'] = webhooks_internal_links[i][j] exp_policies[i]['webhooks_links'] = webhooks_links[i] self.assertEqual(resp['group']['scalingPolicies'], exp_policies)