def test_basic(self, cfngin_context, runway_context): """Test resolution of a basic lookup.""" name = '/test/param' value = 'test value' cfngin_stubber = cfngin_context.add_stubber('ssm') runway_stubber = runway_context.add_stubber('ssm') cfngin_var = Variable('test_var', '${ssm %s}' % name, variable_type='cfngin') runway_var = Variable('test_var', '${ssm %s}' % name, variable_type='runway') for stubber in [cfngin_stubber, runway_stubber]: stubber.add_response('get_parameter', get_parameter_response(name, value), get_parameter_request(name)) with cfngin_stubber as cfn_stub, runway_stubber as rw_stub: cfngin_var.resolve(context=cfngin_context) assert cfngin_var.value == value runway_var.resolve(context=runway_context) assert runway_var.value == value cfn_stub.assert_no_pending_responses() rw_stub.assert_no_pending_responses()
def test_default(self, runway_context): """Test resolution of a default value.""" name = "/test/param" value = "test value" stubber = runway_context.add_stubber("ssm") var = Variable( "test_var", "${ssm /test/invalid::load=json, default=${ssm %s}}" % name, variable_type="runway", ) stubber.add_response( "get_parameter", get_parameter_response(name, value), get_parameter_request(name), ) stubber.add_client_error( "get_parameter", "ParameterNotFound", expected_params=get_parameter_request("/test/invalid"), ) with stubber as stub: var.resolve(context=runway_context) assert var.value == value stub.assert_no_pending_responses()
def test_value_lookup_to_dict(self): """Variable lookups should be resolvable to a dict value.""" var = Variable('test', '${env dict_val}', 'runway') var.resolve(CONTEXT) # need to use data prop to compare the MutableMap contents self.assertEqual(var.value.data, VALUE['dict_val'])
def test_value_complex_str(self): """Multiple lookups should be usable within a single string.""" var = Variable("test", "the ${env what} was ${env test}ful", "runway") var.resolve(CONTEXT) self.assertEqual( var.value, "the {} was {}ful".format(VALUE["what"], VALUE["test"]))
def test_value_complex_str(self): """Multiple lookups should be usable within a single string.""" var = Variable('test', 'the ${env what} was ${env test}ful', 'runway') var.resolve(CONTEXT) self.assertEqual( var.value, 'the {} was {}ful'.format(VALUE['what'], VALUE['test']))
def test_simple_lookup(self) -> None: """Test simple lookup.""" var = Variable("Param1", "${test query}") assert isinstance(var._value, VariableValueLookup) var.resolve(MagicMock(), MagicMock()) assert var.resolved is True assert var.value == "resolved"
def test_basic(self, cfngin_context, runway_context): """Test resolution of a basic lookup.""" name = "/test/param" value = "test value" cfngin_stubber = cfngin_context.add_stubber("ssm") runway_stubber = runway_context.add_stubber("ssm") cfngin_var = Variable("test_var", "${ssm %s}" % name, variable_type="cfngin") runway_var = Variable("test_var", "${ssm %s}" % name, variable_type="runway") for stubber in [cfngin_stubber, runway_stubber]: stubber.add_response( "get_parameter", get_parameter_response(name, value), get_parameter_request(name), ) with cfngin_stubber as cfn_stub, runway_stubber as rw_stub: cfngin_var.resolve(context=cfngin_context) assert cfngin_var.value == value runway_var.resolve(context=runway_context) assert runway_var.value == value cfn_stub.assert_no_pending_responses() rw_stub.assert_no_pending_responses()
def test_loaded_value(self, runway_context: MockRunwayContext) -> None: """Test resolution of a JSON value.""" name = "/test/param" raw_value = { "nested": { "bool": True, "nest_key": "nested_val" }, "test_key": "test_val", } stubber = runway_context.add_stubber("ssm") parsers = ["json", "yaml"] tests = [ { "lookup": "${{ssm {name}::load={parser}}}", "expected": raw_value }, { "lookup": "${{ssm {name}::load={parser},transform=str,indent=2}}", "expected": json.dumps(json.dumps(raw_value, indent=2)), }, { "lookup": "${{ssm {name}::load={parser},get=nested}}", "expected": raw_value["nested"], }, { "lookup": "${{ssm {name}::load={parser},get=nested.bool,transform=str}}", "expected": json.dumps("True"), }, ] for parser in parsers: for test in tests: var = Variable( "test_var.{}".format(parser), test["lookup"].format(name=name, parser=parser), # type: ignore variable_type="runway", ) if parser == "json": dumped_value = json.dumps(raw_value) elif parser == "yaml": dumped_value = yaml.dump(raw_value) else: raise ValueError stubber.add_response( "get_parameter", get_parameter_response(name, dumped_value), get_parameter_request(name), ) with stubber as stub: var.resolve(context=runway_context) assert var.value == test["expected"] stub.assert_no_pending_responses()
def test_legacy_valid_hook_data(self, cfngin_context): """Test valid hook data.""" cfngin_context.set_hook_data('fake_hook', {'result': 'good'}) variable = Variable('test', "${hook_data fake_hook::result}", variable_type='cfngin') with pytest.warns(DeprecationWarning): variable.resolve(cfngin_context) assert variable.value == 'good'
def test_multiple_lookup_string(self, mocker: MockerFixture) -> None: """Test multiple lookup string.""" var = Variable("Param1", "url://${test query0}@${test query1}") assert isinstance(var._value, VariableValueConcatenation) mocker.patch.object(MockLookupHandler, "side_effect", ["resolved0", "resolved1"]) var.resolve(MagicMock(), MagicMock()) assert var.resolved is True assert var.value == "url://resolved0@resolved1"
def test_legacy_valid_hook_data(self, cfngin_context): """Test valid hook data.""" cfngin_context.set_hook_data("fake_hook", {"result": "good"}) variable = Variable("test", "${hook_data fake_hook::result}", variable_type="cfngin") with pytest.warns(DeprecationWarning): variable.resolve(cfngin_context) assert variable.value == "good"
def test_resolve_variable_provided_resolved(self): """Test resolve variable provided resolved.""" var_name = "testVar" var_def = {"type": str} provided_variable = Variable(var_name, "${mock 1}", "cfngin") provided_variable.resolve(context=MagicMock(), provider=MagicMock()) blueprint_name = "testBlueprint" value = resolve_variable(var_name, var_def, provided_variable, blueprint_name) self.assertEqual(value, "1")
def test_value_simple_str_lookup(self): """Test value for simple str lookup.""" var = Variable('test', '${env test}', 'runway') self.assertFalse(var.resolved) var.resolve(CONTEXT) self.assertTrue(var.resolved) self.assertEqual(var.value, VALUE['test'])
def test_value_simple_str_lookup(self): """Test value for simple str lookup.""" var = Variable("test", "${env test}", "runway") self.assertFalse(var.resolved) var.resolve(CONTEXT) self.assertTrue(var.resolved) self.assertEqual(var.value, VALUE["test"])
def test_legacy_bad_value_hook_data(self, cfngin_context): """Test bad value hook data.""" variable = Variable('test', "${hook_data fake_hook::bad_key}", variable_type='cfngin') with pytest.raises(FailedVariableLookup) as err, \ pytest.warns(DeprecationWarning): variable.resolve(cfngin_context) assert 'ValueError' in str(err.value)
def test_not_found(self, cfngin_context): """Test value not found and no default.""" variable = Variable('test', '${hook_data fake_hook.bad.result}', variable_type='cfngin') with pytest.raises(FailedVariableLookup) as err: variable.resolve(cfngin_context) assert 'ValueError' in str(err.value) assert 'Could not find a value for "fake_hook.bad.result"' in str( err.value)
def test_legacy_invalid_hook_data(self, cfngin_context): """Test invalid hook data.""" cfngin_context.set_hook_data("fake_hook", {"result": "good"}) variable = Variable("test", "${hook_data fake_hook::bad_key}", variable_type="cfngin") with pytest.raises(FailedVariableLookup) as err, pytest.warns( DeprecationWarning): variable.resolve(cfngin_context) assert "ValueError" in str(err.value)
def test_legacy_invalid_hook_data(self, cfngin_context): """Test invalid hook data.""" cfngin_context.set_hook_data('fake_hook', {'result': 'good'}) variable = Variable('test', "${hook_data fake_hook::bad_key}", variable_type='cfngin') with pytest.raises(FailedVariableLookup) as err, \ pytest.warns(DeprecationWarning): variable.resolve(cfngin_context) assert 'ValueError' in str(err.value)
def test_not_found(self, cfngin_context: MockCFNginContext) -> None: """Test value not found and no default.""" variable = Variable("test", "${hook_data fake_hook.bad.result}", variable_type="cfngin") with pytest.raises(FailedVariableLookup) as err: variable.resolve(cfngin_context) assert str(err.value) == ( f'Could not resolve lookup "{variable._raw_value}" for variable "{variable.name}"' ) assert "Could not find a value for" in str(err.value.__cause__)
def test_resolve_failed(self, mocker: MockerFixture) -> None: """Test resolve FailedLookup.""" context = MagicMock() provider = MagicMock() obj = Variable("Param", "val") lookup_error = FailedLookup("something", KeyError("cause")) # type: ignore mocker.patch.object(obj._value, "resolve", side_effect=lookup_error) with pytest.raises(FailedVariableLookup) as excinfo: obj.resolve(context, provider, kwarg="something") assert excinfo.value.cause == lookup_error assert excinfo.value.variable == obj
def test_multiple_lookup_dict(self, mocker: MockerFixture) -> None: """Test multiple lookup dict.""" mocker.patch.object(MockLookupHandler, "side_effect", ["resolved0", "resolved1"]) value = { "something": "${test query0}", "other": "${test query1}", } var = Variable("Param1", value) assert isinstance(var._value, VariableValueDict) var.resolve(MagicMock(), MagicMock()) assert var.value == {"something": "resolved0", "other": "resolved1"}
def test_not_found(self, runway_context): """Test raises ParameterNotFound.""" name = '/test/param' stubber = runway_context.add_stubber('ssm') var = Variable('test_var', '${ssm %s}' % name, variable_type='runway') stubber.add_client_error('get_parameter', 'ParameterNotFound', expected_params=get_parameter_request(name)) with stubber as stub, pytest.raises(FailedVariableLookup) as err: var.resolve(context=runway_context) assert 'ParameterNotFound' in str(err.value) stub.assert_no_pending_responses()
def test_variable_resolve_simple_lookup(self): """Test variable resolve simple lookup.""" stack = Stack(definition=generate_definition("vpc", 1), context=self.context) stack.set_outputs({ "FakeOutput": "resolved", "FakeOutput2": "resolved2", }) self.context.get_stack.return_value = stack var = Variable("Param1", "${output fakeStack::FakeOutput}") var.resolve(self.context, self.provider) self.assertTrue(var.resolved) self.assertEqual(var.value, "resolved")
def test_loaded_value(self, runway_context): """Test resolution of a JSON value.""" name = '/test/param' raw_value = { 'nested': { 'bool': True, 'nest_key': 'nested_val' }, 'test_key': 'test_val' } stubber = runway_context.add_stubber('ssm') parsers = ['json', 'yaml'] tests = [{ 'lookup': '${{ssm {name}::load={parser}}}', 'expected': raw_value }, { 'lookup': '${{ssm {name}::load={parser},transform=str,indent=2}}', 'expected': json.dumps(json.dumps(raw_value, indent=2)) }, { 'lookup': '${{ssm {name}::load={parser},get=nested}}', 'expected': raw_value['nested'] }, { 'lookup': '${{ssm {name}::load={parser},get=nested.bool,transform=str}}', 'expected': json.dumps('True') }] for parser in parsers: for test in tests: var = Variable('test_var.{}'.format(parser), test['lookup'].format(name=name, parser=parser), variable_type='runway') if parser == 'json': dumped_value = json.dumps(raw_value) elif parser == 'yaml': dumped_value = yaml.dump(raw_value) else: raise ValueError stubber.add_response( 'get_parameter', get_parameter_response(name, dumped_value), get_parameter_request(name)) with stubber as stub: var.resolve(context=runway_context) assert var.value == test['expected'] stub.assert_no_pending_responses()
def test_handle(self, cfngin_context): """Test handle with simple usage.""" cfngin_context.set_hook_data("fake_hook", {"nested": { "result": "good" }}) var_top = Variable("test", "${hook_data fake_hook}", variable_type="cfngin") var_nested = Variable("test", "${hook_data fake_hook.nested.result}", variable_type="cfngin") var_top.resolve(cfngin_context) var_nested.resolve(cfngin_context) assert var_top.value == {"nested": {"result": "good"}} assert var_nested.value == "good"
def test_not_found(self, runway_context): """Test raises ParameterNotFound.""" name = "/test/param" stubber = runway_context.add_stubber("ssm") var = Variable("test_var", "${ssm %s}" % name, variable_type="runway") stubber.add_client_error( "get_parameter", "ParameterNotFound", expected_params=get_parameter_request(name), ) with stubber as stub, pytest.raises(FailedVariableLookup) as err: var.resolve(context=runway_context) assert "ParameterNotFound" in str(err.value) stub.assert_no_pending_responses()
def test_different_region(self, runway_context): """Test Lookup in region other than that set in Context.""" name = '/test/param' value = 'test value' stubber = runway_context.add_stubber('ssm', region='us-west-2') var = Variable('test_var', '${ssm %s::region=us-west-2}' % name, variable_type='runway') stubber.add_response('get_parameter', get_parameter_response(name, value), get_parameter_request(name)) with stubber as stub: var.resolve(context=runway_context) assert var.value == value stub.assert_no_pending_responses()
def test_handle(self, cfngin_context): """Test handle with simple usage.""" cfngin_context.set_hook_data('fake_hook', {'nested': { 'result': 'good' }}) var_top = Variable('test', '${hook_data fake_hook}', variable_type='cfngin') var_nested = Variable('test', '${hook_data fake_hook.nested.result}', variable_type='cfngin') var_top.resolve(cfngin_context) var_nested.resolve(cfngin_context) assert var_top.value == {'nested': {'result': 'good'}} assert var_nested.value == 'good'
def test_default(self, cfngin_context): """Test handle with a default value.""" cfngin_context.set_hook_data('fake_hook', {'nested': { 'result': 'good' }}) var_top = Variable('test', '${hook_data bad_hook::default=something}', variable_type='cfngin') var_nested = Variable('test', '${hook_data fake_hook.bad.' 'result::default=something,load=json,get=key}', variable_type='cfngin') var_top.resolve(cfngin_context) var_nested.resolve(cfngin_context) assert var_top.value == 'something' assert var_nested.value == 'something'
def test_troposphere(self, cfngin_context): """Test with troposphere object like returned from lambda hook.""" bucket = 'test-bucket' s3_key = 'lambda_functions/my_function' cfngin_context.set_hook_data( 'lambda', {'my_function': Code(S3Bucket=bucket, S3Key=s3_key)}) var_bucket = Variable('test', '${hook_data lambda.my_function::' 'load=troposphere,get=S3Bucket}', variable_type='cfngin') var_key = Variable('test', '${hook_data lambda.my_function::get=S3Key}', variable_type='cfngin') var_bucket.resolve(cfngin_context) var_key.resolve(cfngin_context) assert var_bucket.value == bucket assert var_key.value == s3_key