def test_assert_failed_callback_delay_seconds_set(): with pytest.raises(AssertionError): HookClient.assert_failed( HookStatus.FAILED, { "errorCode": HandlerErrorCode.AccessDenied.value, "callbackDelaySeconds": 5, }, )
def hook_client(): endpoint = "https://" patch_sesh = patch("rpdk.core.contract.hook_client.create_sdk_session", autospec=True) patch_creds = patch( "rpdk.core.contract.hook_client.get_temporary_credentials", autospec=True, return_value={}, ) patch_account = patch( "rpdk.core.contract.hook_client.get_account", autospec=True, return_value=ACCOUNT, ) with patch_sesh as mock_create_sesh, patch_creds as mock_creds: with patch_account as mock_account: mock_sesh = mock_create_sesh.return_value mock_sesh.region_name = DEFAULT_REGION client = HookClient(DEFAULT_FUNCTION, endpoint, DEFAULT_REGION, SCHEMA_, EMPTY_OVERRIDE) mock_sesh.client.assert_called_once_with("lambda", endpoint_url=endpoint) mock_creds.assert_called_once_with(mock_sesh, LOWER_CAMEL_CRED_KEYS, None) mock_account.assert_called_once_with(mock_sesh, {}) assert client._function_name == DEFAULT_FUNCTION assert client._schema == SCHEMA_ assert client._configuration_schema == SCHEMA_["typeConfiguration"] assert client._overrides == EMPTY_OVERRIDE assert client.account == ACCOUNT return client
def test_init_sam_cli_client(): patch_sesh = patch("rpdk.core.contract.hook_client.create_sdk_session", autospec=True) patch_creds = patch( "rpdk.core.contract.hook_client.get_temporary_credentials", autospec=True, return_value={}, ) patch_account = patch( "rpdk.core.contract.hook_client.get_account", autospec=True, return_value=ACCOUNT, ) with patch_sesh as mock_create_sesh, patch_creds as mock_creds: with patch_account as mock_account: mock_sesh = mock_create_sesh.return_value mock_sesh.region_name = DEFAULT_REGION client = HookClient(DEFAULT_FUNCTION, DEFAULT_ENDPOINT, DEFAULT_REGION, {}, EMPTY_OVERRIDE) mock_sesh.client.assert_called_once_with("lambda", endpoint_url=DEFAULT_ENDPOINT, use_ssl=False, verify=False, config=ANY) mock_creds.assert_called_once_with(mock_sesh, LOWER_CAMEL_CRED_KEYS, None) mock_account.assert_called_once_with(mock_sesh, {}) assert client.account == ACCOUNT
def test_generate_example(hook_client): hook_target_info = { "AWS::Example::Target": { "TypeName": "AWS::Example::Target", "Schema": { "properties": { "a": { "type": "number", "const": 1 }, "b": { "type": "number", "const": 2 }, }, "readOnlyProperties": ["/properties/b"], }, } } hook_client._target_info = HookClient._setup_target_info(hook_target_info) assert not hook_client._target_info["AWS::Example::Target"].get( "SchemaStrategy") example = hook_client._generate_target_example("AWS::Example::Target") assert example == {"a": 1} assert hook_client._target_info["AWS::Example::Target"]["SchemaStrategy"]
def test_generate_update_example(hook_client): hook_target_info = { "AWS::Example::Target": { "TypeName": "AWS::Example::Target", "Schema": { "properties": { "a": { "type": "number", "const": 1 }, "b": { "type": "number", "const": 2 }, "c": { "type": "number", "const": 3 }, }, "readOnlyProperties": ["/properties/b"], "createOnlyProperties": ["/properties/c"], }, } } hook_client._target_info = HookClient._setup_target_info(hook_target_info) hook_client._overrides = {} assert not hook_client._target_info["AWS::Example::Target"].get( "UpdateSchemaStrategy") model = {"b": 2, "a": 4} example = hook_client._generate_target_update_example( "AWS::Example::Target", model) assert example == {"a": 1, "b": 2} assert hook_client._target_info["AWS::Example::Target"][ "UpdateSchemaStrategy"]
def test_call_docker(): patch_sesh = patch("rpdk.core.contract.hook_client.create_sdk_session", autospec=True) patch_creds = patch( "rpdk.core.contract.hook_client.get_temporary_credentials", autospec=True, return_value={}, ) patch_config = patch( "rpdk.core.contract.hook_client.TypeConfiguration.get_hook_configuration", return_value={}, ) patch_account = patch( "rpdk.core.contract.hook_client.get_account", autospec=True, return_value=ACCOUNT, ) patch_docker = patch("rpdk.core.contract.hook_client.docker", autospec=True) with patch_sesh as mock_create_sesh, patch_docker as mock_docker, patch_creds, patch_config: with patch_account: mock_client = mock_docker.from_env.return_value mock_sesh = mock_create_sesh.return_value mock_sesh.region_name = DEFAULT_REGION hook_client = HookClient( DEFAULT_FUNCTION, "url", DEFAULT_REGION, {}, EMPTY_OVERRIDE, docker_image="docker_image", executable_entrypoint="entrypoint", ) hook_client._type_name = HOOK_TYPE_NAME response_str = ("__CFN_HOOK_START_RESPONSE__" '{"hookStatus": "SUCCESS"}__CFN_HOOK_END_RESPONSE__') mock_client.containers.run.return_value = str.encode(response_str) with patch_creds: status, response = hook_client.call("CREATE_PRE_PROVISION", HOOK_TARGET_TYPE_NAME, {"foo": "bar"}) mock_client.containers.run.assert_called_once() assert status == HookStatus.SUCCESS assert response == {"hookStatus": HookStatus.SUCCESS.value}
def test_assert_failed_returns_error_code(): error_code = HookClient.assert_failed( HookStatus.FAILED, { "errorCode": HandlerErrorCode.AccessDenied.value, "message": "I have failed you", }, ) assert error_code == HandlerErrorCode.AccessDenied
def test_call_docker_executable_entrypoint_null(): TypeConfiguration.TYPE_CONFIGURATION = {} patch_sesh = patch("rpdk.core.contract.hook_client.create_sdk_session", autospec=True) patch_creds = patch( "rpdk.core.contract.hook_client.get_temporary_credentials", autospec=True, return_value={}, ) patch_config = patch( "rpdk.core.contract.hook_client.TypeConfiguration.get_hook_configuration", return_value={}, ) patch_account = patch( "rpdk.core.contract.hook_client.get_account", autospec=True, return_value=ACCOUNT, ) patch_docker = patch("rpdk.core.contract.hook_client.docker", autospec=True) with patch_sesh as mock_create_sesh, patch_docker, patch_creds, patch_config: with patch_account: mock_sesh = mock_create_sesh.return_value mock_sesh.region_name = DEFAULT_REGION hook_client = HookClient( DEFAULT_FUNCTION, "url", DEFAULT_REGION, {}, EMPTY_OVERRIDE, docker_image="docker_image", ) hook_client._type_name = HOOK_TYPE_NAME try: with patch_creds: hook_client.call("CREATE_PRE_PROVISION", HOOK_TARGET_TYPE_NAME, {"foo": "bar"}) except InvalidProjectError: pass TypeConfiguration.TYPE_CONFIGURATION = None
def test_hook_success(hook_client, invocation_point, target, target_model): if HookClient.is_update_invocation_point(invocation_point): raise ValueError( "Invocation point {} not supported for this testing operation".format( invocation_point ) ) _status, response, _error_code = hook_client.call_and_assert( invocation_point, HookStatus.SUCCESS, target, target_model ) return response
def test_hook_handlers_success(hook_client, invocation_point): is_update_hook = HookClient.is_update_invocation_point(invocation_point) for ( _invocation_point, target, target_model, ) in hook_client.generate_request_examples(invocation_point): if is_update_hook: test_update_hook_success( hook_client, invocation_point, target, target_model ) else: test_hook_success(hook_client, invocation_point, target, target_model)
def test_setup_target_info(): hook_target_info = { "AWS::Example::Target": { "TypeName": "AWS::Example::Target", "Schema": TARGET_SCHEMA, } } target_info = HookClient._setup_target_info(hook_target_info) assert target_info["AWS::Example::Target"]["readOnlyProperties"] == { ("properties", "b") } assert target_info["AWS::Example::Target"]["createOnlyProperties"] == { ("properties", "c") }
def test_make_request(hook_type, log_group_name, log_creds): target_model = object() token = object() request = HookClient.make_request( HOOK_TARGET_TYPE_NAME, hook_type, ACCOUNT, "CREATE_PRE_PROVISION", {}, log_group_name, log_creds, token, target_model, "00000001", "RESOURCE", ) expected_request = { "requestData": { "callerCredentials": json.dumps({}), "targetName": HOOK_TARGET_TYPE_NAME, "targetLogicalId": token, "targetModel": target_model, "targetType": "RESOURCE", }, "requestContext": { "callbackContext": None }, "hookTypeName": hook_type, "hookTypeVersion": "00000001", "clientRequestToken": token, "stackId": token, "awsAccountId": ACCOUNT, "actionInvocationPoint": "CREATE_PRE_PROVISION", "hookModel": None, } if log_group_name and log_creds: expected_request["requestData"]["providerCredentials"] = json.dumps( log_creds) expected_request["requestData"][ "providerLogGroupName"] = log_group_name assert request == expected_request
def get_contract_plugin_client(args, project, overrides, inputs): plugin_clients = {} if project.artifact_type == ARTIFACT_TYPE_HOOK: plugin_clients["hook_client"] = HookClient( args.function_name, args.endpoint, args.region, project.schema, overrides, inputs, args.role_arn, args.enforce_timeout, project.type_name, args.log_group_name, args.log_role_arn, executable_entrypoint=project.executable_entrypoint, docker_image=args.docker_image, target_info=project._load_target_info( # pylint: disable=protected-access args.cloudformation_endpoint_url, args.region), ) LOG.debug("Setup plugin for HOOK type") return plugin_clients plugin_clients["resource_client"] = ResourceClient( args.function_name, args.endpoint, args.region, project.schema, overrides, inputs, args.role_arn, args.enforce_timeout, project.type_name, args.log_group_name, args.log_role_arn, executable_entrypoint=project.executable_entrypoint, docker_image=args.docker_image, ) LOG.debug("Setup plugin for RESOURCE type") return plugin_clients
def test_generate_token(): token = HookClient.generate_token() assert isinstance(token, str) assert len(token) == 36
def test_assert_in_progress_callback_delay_seconds_unset(): callback_delay_seconds = HookClient.assert_in_progress( HookStatus.IN_PROGRESS, {"result": None}) assert callback_delay_seconds == 0
def hook_client_inputs(): endpoint = "https://" patch_sesh = patch("rpdk.core.contract.hook_client.create_sdk_session", autospec=True) patch_creds = patch( "rpdk.core.contract.hook_client.get_temporary_credentials", autospec=True, return_value={}, ) patch_account = patch( "rpdk.core.contract.hook_client.get_account", autospec=True, return_value=ACCOUNT, ) with patch_sesh as mock_create_sesh, patch_creds as mock_creds: with patch_account as mock_account: mock_sesh = mock_create_sesh.return_value mock_sesh.region_name = DEFAULT_REGION client = HookClient( DEFAULT_FUNCTION, endpoint, DEFAULT_REGION, SCHEMA_, EMPTY_OVERRIDE, { "CREATE_PRE_PROVISION": { "My::Example::Resource": { "resourceProperties": { "a": 1 } } }, "UPDATE_PRE_PROVISION": { "My::Example::Resource": { "resourceProperties": { "a": 2 }, "previousResourceProperties": { "c": 4 }, } }, "INVALID_DELETE_PRE_PROVISION": { "My::Example::Resource": { "resourceProperties": { "b": 2 } } }, "INVALID": { "My::Example::Resource": { "resourceProperties": { "b": 1 } } }, }, target_info=HOOK_TARGET_INFO, ) mock_sesh.client.assert_called_once_with("lambda", endpoint_url=endpoint) mock_creds.assert_called_once_with(mock_sesh, LOWER_CAMEL_CRED_KEYS, None) mock_account.assert_called_once_with(mock_sesh, {}) assert client._function_name == DEFAULT_FUNCTION assert client._schema == SCHEMA_ assert client._configuration_schema == SCHEMA_["typeConfiguration"] assert client._overrides == EMPTY_OVERRIDE assert client.account == ACCOUNT return client
def test_assert_success_callback_delay_seconds_set(): with pytest.raises(AssertionError): HookClient.assert_success(HookStatus.SUCCESS, {"callbackDelaySeconds": 5})
def test_is_update_invocation_point_true(invoke_point): assert HookClient.is_update_invocation_point(invoke_point)
def test_assert_success_wrong_status(status): with pytest.raises(AssertionError): HookClient.assert_success(status, {})
def test_assert_failed_error_code_invalid(): with pytest.raises(KeyError): HookClient.assert_failed(HookStatus.FAILED, {"errorCode": "XXX"})
def test_assert_failed_error_code_unset(): with pytest.raises(AssertionError): HookClient.assert_failed(HookStatus.FAILED, {})
def test_assert_failed_wrong_status(status): with pytest.raises(AssertionError): HookClient.assert_failed(status, {})
def test_assert_in_progress_result_set(): with pytest.raises(AssertionError): HookClient.assert_in_progress(HookStatus.IN_PROGRESS, {"result": ""})
def test_assert_in_progress_error_code_set(): with pytest.raises(AssertionError): HookClient.assert_in_progress( HookStatus.IN_PROGRESS, {"errorCode": HandlerErrorCode.AccessDenied.value}, )
def test_is_update_invocation_point_false(invoke_point): assert not HookClient.is_update_invocation_point(invoke_point)
def test_assert_in_progress_callback_delay_seconds_set(): callback_delay_seconds = HookClient.assert_in_progress( HookStatus.IN_PROGRESS, {"callbackDelaySeconds": 5}) assert callback_delay_seconds == 5
def test_assert_success_error_code_set(): with pytest.raises(AssertionError): HookClient.assert_success( HookStatus.SUCCESS, {"errorCode": HandlerErrorCode.AccessDenied.value})