Example #1
0
    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()
Example #2
0
    def test_resolve_variables(self):
        """Test resolve variables."""
        class TestBlueprint(Blueprint):
            """Test blueprint."""

            VARIABLES = {
                "Param1": {
                    "default": 0,
                    "type": int
                },
                "Param2": {
                    "type": str
                },
            }

        blueprint = TestBlueprint(name="test", context=MagicMock())
        variables = [
            Variable("Param1", 1, 'cfngin'),
            Variable("Param2", "${output other-stack::Output}", 'cfngin'),
            Variable("Param3", 3, 'cfngin'),
        ]

        variables[1]._value._resolve("Test Output")

        blueprint.resolve_variables(variables)
        self.assertEqual(blueprint.resolved_variables["Param1"], 1)
        self.assertEqual(blueprint.resolved_variables["Param2"], "Test Output")
        self.assertIsNone(blueprint.resolved_variables.get("Param3"))
Example #3
0
    def test_get_parameter_values(self):
        """Test get parameter values."""
        class TestBlueprint(Blueprint):
            """Test blueprint."""

            VARIABLES = {
                "Param1": {
                    "type": int
                },
                "Param2": {
                    "type": CFNString
                },
            }

        blueprint = TestBlueprint(name="test", context=MagicMock())
        variables = [
            Variable("Param1", 1, 'cfngin'),
            Variable("Param2", "Value", 'cfngin')
        ]
        blueprint.resolve_variables(variables)
        variables = blueprint.get_variables()
        self.assertEqual(len(variables), 2)
        parameters = blueprint.get_parameter_values()
        self.assertEqual(len(parameters), 1)
        self.assertEqual(parameters["Param2"], "Value")
Example #4
0
    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()
Example #5
0
    def to_json(self, variables=None):
        """Render the blueprint and return the template in json form.

        Args:
            variables (Optional[Dict[str, Any]]):
                Dictionary providing/overriding variable values.

        Returns:
            str: Rhe rendered CFN JSON template.

        """
        variables_to_resolve = []
        if variables:
            for key, value in variables.items():
                variables_to_resolve.append(Variable(key, value, 'cfngin'))
        for k in self.get_parameter_definitions():
            if not variables or k not in variables:
                # The provided value for a CFN parameter has no effect in this
                # context (generating the CFN template), so any string can be
                # provided for its value - just needs to be something
                variables_to_resolve.append(
                    Variable(k, 'unused_value', 'cfngin'))
        self.resolve_variables(variables_to_resolve)

        return self.render_template()[1]
Example #6
0
 def test_dependencies(self, mocker: MockerFixture) -> None:
     """Test dependencies."""
     assert Variable("Param", "val").dependencies == set()
     mocker.patch.object(VariableValue,
                         "parse_obj",
                         return_value=MagicMock(dependencies={"test"}))
     assert Variable("Param", "val").dependencies == {"test"}
Example #7
0
    def test_resolve_variable_allowed_values(self):
        """Test resolve variable allowed values."""
        var_name = "testVar"
        var_def = {"type": str, "allowed_values": ["allowed"]}
        provided_variable = Variable(var_name, "not_allowed", "cfngin")
        blueprint_name = "testBlueprint"
        with self.assertRaises(ValueError):
            resolve_variable(var_name, var_def, provided_variable, blueprint_name)

        provided_variable = Variable(var_name, "allowed", "cfngin")
        value = resolve_variable(var_name, var_def, provided_variable, blueprint_name)
        self.assertEqual(value, "allowed")
Example #8
0
 def test_j2_to_json(self):
     """Verify jinja2 template parsing."""
     expected_json = json.dumps(
         {
             "AWSTemplateFormatVersion": "2010-09-09",
             "Description": "TestTemplate",
             "Parameters": {
                 "Param1": {
                     "Type": "String"
                 },
                 "Param2": {
                     "Default": "default",
                     "Type": "CommaDelimitedList"
                 },
             },
             "Resources": {
                 "Dummy": {
                     "Type": "AWS::CloudFormation::WaitConditionHandle"
                 }
             },
             "Outputs": {
                 "DummyId": {
                     "Value": "dummy-bar-param1val-foo-1234"
                 }
             },
         },
         sort_keys=True,
         indent=4,
     )
     blueprint = RawTemplateBlueprint(
         name="stack1",
         context=mock_context(
             extra_config_args={
                 "stacks": [{
                     "name": "stack1",
                     "template_path": "unused",
                     "variables": {
                         "Param1": "param1val",
                         "bar": "foo"
                     },
                 }]
             },
             environment={"foo": "bar"},
         ),
         raw_template_path=RAW_J2_TEMPLATE_PATH,
     )
     blueprint.resolve_variables([
         Variable("Param1", "param1val", "cfngin"),
         Variable("bar", "foo", "cfngin"),
     ])
     self.assertEqual(expected_json, blueprint.to_json())
Example #9
0
def test_resolve_variable_allowed_values() -> None:
    """Test resolve_variable."""
    var_name = "testVar"
    var_def: BlueprintVariableTypeDef = {"type": str, "allowed_values": ["allowed"]}
    with pytest.raises(ValueError):
        resolve_variable(
            var_name, var_def, Variable(var_name, "not_allowed", "cfngin"), "test"
        )
    assert (
        resolve_variable(
            var_name, var_def, Variable(var_name, "allowed", "cfngin"), "test"
        )
        == "allowed"
    )
Example #10
0
 def test_resolve_lookups_list_unknown_lookup(self):
     """Test resolve lookups list unknown lookup."""
     with self.assertRaises(UnknownLookupType):
         Variable("MyVar", [
             "${bad_lookup foo}",
             "random string",
         ])
Example #11
0
def test_resolve_variable_provided_not_resolved(mocker: MockerFixture) -> None:
    """Test resolve_variable."""
    mocker.patch("runway.variables.CFNGIN_LOOKUP_HANDLERS", {"mock": Mock()})
    with pytest.raises(UnresolvedBlueprintVariable):
        resolve_variable(
            "name", {"type": str}, Variable("name", "${mock abc}", "cfngin"), "test"
        )
Example #12
0
    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'])
Example #13
0
    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()
Example #14
0
    def test_resolve_variables_lookup_returns_non_string(self):
        """Test resolve variables lookup returns non string."""
        class TestBlueprint(Blueprint):
            """Test blueprint."""

            VARIABLES = {
                "Param1": {
                    "type": list
                },
            }

        def return_list_something(*_args, **_kwargs):
            """Return list something."""
            return ["something"]

        register_lookup_handler("custom", return_list_something)
        blueprint = TestBlueprint(name="test", context=MagicMock())
        variables = [
            Variable("Param1", "${custom non-string-return-val}", 'cfngin')
        ]
        for var in variables:
            var._value.resolve({}, {})

        blueprint.resolve_variables(variables)
        self.assertEqual(blueprint.resolved_variables["Param1"], ["something"])
Example #15
0
    def test_resolve_variables_lookup_returns_troposphere_obj(self):
        """Test resolve variables lookup returns troposphere obj."""
        class TestBlueprint(Blueprint):
            """Test blueprint."""

            VARIABLES = {
                "Param1": {
                    "type": Base64
                },
            }

        def return_obj(*_args, **_kwargs):
            """Return object."""
            return Base64("test")

        register_lookup_handler("custom", return_obj)
        blueprint = TestBlueprint(name="test", context=MagicMock())
        variables = [
            Variable("Param1", "${custom non-string-return-val}", 'cfngin')
        ]
        for var in variables:
            var._value.resolve({}, {})

        blueprint.resolve_variables(variables)
        self.assertEqual(blueprint.resolved_variables["Param1"].data,
                         Base64("test").data)
Example #16
0
    def test_env_vars_config_unresolved(
        self,
        fx_deployments: YamlLoaderDeployment,
        mocker: MockerFixture,
        runway_context: MockRunwayContext,
    ) -> None:
        """Test env_vars_config unresolved."""
        expected = {"key": "val"}
        mocker.patch.object(Deployment, "_Deployment__merge_env_vars",
                            MagicMock(return_value=None))
        mocker.patch.object(
            RunwayDeploymentDefinition,
            "env_vars",
            PropertyMock(side_effect=[
                UnresolvedVariable(
                    Variable("test", "something", variable_type="runway"),
                    MagicMock(),
                ),
                expected,
            ]),
            create=True,
        )
        mocker.patch.object(RunwayDeploymentDefinition,
                            "_env_vars",
                            PropertyMock(),
                            create=True)

        raw_deployment: Dict[str,
                             Any] = cast(Dict[str, Any],
                                         fx_deployments.get("min_required"))
        deployment = RunwayDeploymentDefinition.parse_obj(raw_deployment)
        obj = Deployment(context=runway_context, definition=deployment)

        assert obj.env_vars_config == expected
        obj.definition._env_vars.resolve.assert_called_once()
Example #17
0
 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"
Example #18
0
    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']))
Example #19
0
 def test_variable_replace_lookups_mixed(self):
     """Test variable replace lookups mixed."""
     value = {
         "something": [
             "${output fakeStack::FakeOutput}",
             "other",
         ],
         "here": {
             "other": "${output fakeStack::FakeOutput2}",
             "same": "${output fakeStack::FakeOutput}",
             "mixed": "something:${output fakeStack::FakeOutput3}",
         },
     }
     var = Variable("Param1", value)
     var._value["something"][0]._resolve("resolved")
     var._value["here"]["other"]._resolve("resolved2")
     var._value["here"]["same"]._resolve("resolved")
     var._value["here"]["mixed"][1]._resolve("resolved3")
     self.assertEqual(
         var.value, {
             "something": [
                 "resolved",
                 "other",
             ],
             "here": {
                 "other": "resolved2",
                 "same": "resolved",
                 "mixed": "something:resolved3",
             },
         })
Example #20
0
    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"]))
Example #21
0
    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
Example #22
0
def resolve_troposphere_var(tpe: Any, value: Any, **kwargs: Any) -> Any:
    """Resolve troposphere var."""
    return resolve_variable(
        "name",
        {"type": TroposphereType(tpe, **kwargs)},
        Variable("name", value, "cfngin"),
        "test",
    )
Example #23
0
 def test_init(self, variable_type: VariableTypeLiteralTypeDef) -> None:
     """Test __init__."""
     obj = Variable("Param", "val", variable_type)
     assert obj.name == "Param"
     assert obj.variable_type == variable_type
     assert obj._raw_value == "val"
     assert obj._value.value == "val"
     assert obj._value.variable_type == variable_type
Example #24
0
    def test_value_simple_str(self):
        """Test value for a simple string without lookups."""
        var = Variable('test', 'success')

        self.assertTrue(var.resolved,
                        msg='when no lookup is used, it should '
                        'be automatically marked as resolved')
        self.assertEqual(var.value, 'success')
Example #25
0
 def test_resolve_lookups_list_failed_variable_lookup(self):
     """Test resolve lookups list failed variable lookup."""
     variable = Variable("MyVar", [
         "random string",
         "${output foo::bar}",
         "random string",
     ])
     self.resolve_lookups_with_output_handler_raise_valueerror(variable)
Example #26
0
    def _resolve_troposphere_var(self, tpe, value, **kwargs):
        """Resolve troposphere var."""
        var_name = "testVar"
        var_def = {"type": TroposphereType(tpe, **kwargs)}
        provided_variable = Variable(var_name, value, "cfngin")
        blueprint_name = "testBlueprint"

        return resolve_variable(var_name, var_def, provided_variable, blueprint_name)
Example #27
0
    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'
Example #28
0
    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'
Example #29
0
 def test_create_template_passes(self) -> None:
     """Test create template passes."""
     ctx = CfnginContext()
     blueprint = Repositories("test_repo", ctx)
     blueprint.resolve_variables(
         [Variable("Repositories", ["repo1", "repo2"], "cfngin")])
     blueprint.create_template()
     self.assertRenderedBlueprint(blueprint)
Example #30
0
 def test_create_template_passes(self):
     """Test create template passes."""
     ctx = Context({'namespace': 'test'})
     blueprint = Repositories('test_repo', ctx)
     blueprint.resolve_variables(
         [Variable('Repositories', ["repo1", "repo2"], 'cfngin')])
     blueprint.create_template()
     self.assertRenderedBlueprint(blueprint)