def test_alias_default_hosted_zone_id(self): blueprint = DNSRecords( 'test_route53_alias_default_hosted_zone_id', self.ctx ) blueprint.resolve_variables( [ Variable( "RecordSets", [ { "Name": "host.testdomain.com.", "Type": "A", "AliasTarget": { "DNSName": "original-gangster-host.testdomain.com.", # noqa }, }, ] ), Variable("HostedZoneId", "fake_zone_id"), ] ) record_sets = blueprint.create_template() self.assertEqual( record_sets[0].AliasTarget.HostedZoneId, "fake_zone_id" )
def test_resolve_variables(self): class TestBlueprint(Blueprint): VARIABLES = { "Param1": { "default": 0, "type": int }, "Param2": { "type": str }, } blueprint = TestBlueprint(name="test", context=MagicMock()) variables = [ Variable("Param1", 1), Variable("Param2", "${other-stack::Output}"), Variable("Param3", 3), ] resolved_lookups = { mock_lookup("other-stack::Output"): "Test Output", } for var in variables: var.replace(resolved_lookups) 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"))
def test_resolve_variables(self): class TestBlueprint(Blueprint): VARIABLES = { "Param1": { "default": 0, "type": int }, "Param2": { "type": str }, } blueprint = TestBlueprint(name="test", context=MagicMock()) variables = [ Variable("Param1", 1), Variable("Param2", "${output other-stack::Output}"), Variable("Param3", 3), ] 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"))
def test_create_template_hosted_zone_name(self): blueprint = DNSRecords('route53_dnsrecords_zone_name', self.ctx) blueprint.resolve_variables( [ Variable( "RecordSets", [ { "Name": "host.testdomain.com.", "Type": "A", "ResourceRecords": ["10.0.0.1"], }, { "Name": "host2.testdomain.com.", "Type": "A", "ResourceRecords": ["10.0.0.2"], "Comment": "This is host2's record. : )", }, { "Name": "host3.testdomain.com.", "Type": "A", "ResourceRecords": ["10.0.0.3"], "Comment": "This record is present but disabled.", "Enabled": False, }, ] ), Variable("HostedZoneName", "testdomain.com"), Variable("Comment", "test-testdomain-com"), ] ) record_sets = blueprint.create_template() self.assertEqual(2, len(record_sets)) self.assertRenderedBlueprint(blueprint)
def json(blueprint, userdata_dict=None, function_dict=None): """Turn a stacker blueprint into CloudFormation JSON.""" if userdata_dict is None: userdata_dict = {} if function_dict is None: function_dict = {} # Check the blueprint for CFN parameters in its variables, and define bogus # values for those parameters so the template can be generated. # Easiest check to find variables that are CFN parameters (and not native # python types) seems to be looking for the 'parameter_type' attribute test_variables = [] for key, value in blueprint.defined_variables().iteritems(): if hasattr(value['type'], 'parameter_type'): test_variables.append(Variable(key, 'dummy_value')) # Populate the userdata via the file lookup for userdata in userdata_dict.iteritems(): parameterized_b64 = parameterized_codec(open(userdata[1], 'r').read(), True) # base64 test_variables.append(Variable(userdata[0], parameterized_b64)) # Populate the lambda functions via the file lookup for function in function_dict.iteritems(): parameterized = parameterized_codec(open(function[1], 'r').read(), False) # base64 test_variables.append(Variable(function[0], parameterized)) blueprint.resolve_variables(test_variables) print blueprint.render_template()[1]
def test_kms_key_attributes_is_deprecated(self): blueprint = Key('kms_key_attributes_deprecated', self.ctx) blueprint.resolve_variables([ Variable("KeyAlias", "c-test-key"), Variable("Attributes", {"Description": "c KMS test-key."}), ]) with self.assertRaises(DeprecationWarning): blueprint.create_template()
def test_kms_key_alias_not_in_keyalias(self): blueprint = Key('kms_key_b', self.ctx) blueprint.resolve_variables([ Variable("KeyAlias", "b-test-key"), Variable("Properties", {"Description": "b KMS test-key."}), ]) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def update_var_dict(provided_var_dict, params_to_add): """Return a dictionary to add to resolve_variables()'s variable_dict.""" additional_vars = {} for param_to_add in params_to_add: if param_to_add['var_name'] in provided_var_dict: for key, value in provided_var_dict[ param_to_add['var_name']].value.iteritems(): # noqa pylint: disable=C0301 if isinstance(value, (dict, OrderedDict)): additional_vars[key] = Variable(key, dict(value)['Value']) else: additional_vars[key] = Variable(key, value) return additional_vars
def test_get_variables(self): class TestBlueprint(Blueprint): VARIABLES = { "Param1": {"type": int}, "Param2": {"type": str}, } blueprint = TestBlueprint(name="test", context=MagicMock()) variables = [Variable("Param1", 1), Variable("Param2", "Test Output")] blueprint.resolve_variables(variables) variables = blueprint.get_variables() self.assertEqual(variables["Param1"], 1) self.assertEqual(variables["Param2"], "Test Output")
def test_resolve_variable_allowed_values(self): var_name = "testVar" var_def = {"type": str, "allowed_values": ["allowed"]} provided_variable = Variable(var_name, "not_allowed") blueprint_name = "testBlueprint" with self.assertRaises(ValueError): resolve_variable(var_name, var_def, provided_variable, blueprint_name) provided_variable = Variable(var_name, "allowed") value = resolve_variable(var_name, var_def, provided_variable, blueprint_name) self.assertEqual(value, "allowed")
def test_create_template(self): blueprint = Function('test_aws_lambda_Function', self.ctx) blueprint.resolve_variables( [ Variable( "Code", Code(S3Bucket="test_bucket", S3Key="code_key") ), Variable("Description", "Test function."), Variable("Environment", {"TEST_NAME": "test_value"}), Variable("Runtime", "python2.7"), ] ) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_get_parameter_values(self): class TestBlueprint(Blueprint): VARIABLES = { "Param1": {"type": int}, "Param2": {"type": CFNString}, } blueprint = TestBlueprint(name="test", context=MagicMock()) variables = [Variable("Param1", 1), Variable("Param2", "Value")] blueprint.resolve_variables(variables) variables = blueprint.get_variables() self.assertEqual(len(variables), 2) parameters = blueprint.get_parameter_values() self.assertEqual(len(parameters.keys()), 1) self.assertEqual(parameters["Param2"], "Value")
def test_variable_replace_lookups_mixed(self): value = { "something": [ "${output fakeStack::FakeOutput}", "other", ], "here": { "other": "${output fakeStack::FakeOutput2}", "same": "${output fakeStack::FakeOutput}", "mixed": "something:${output fakeStack::FakeOutput3}", }, } var = Variable("Param1", value) self.assertEqual(len(var.lookups), 3) resolved_lookups = { mock_lookup("fakeStack::FakeOutput", "output"): "resolved", mock_lookup("fakeStack::FakeOutput2", "output"): "resolved2", mock_lookup("fakeStack::FakeOutput3", "output"): "resolved3", } var.replace(resolved_lookups) self.assertEqual( var.value, { "something": [ "resolved", "other", ], "here": { "other": "resolved2", "same": "resolved", "mixed": "something:resolved3", }, })
def test_variable_replace_lookups_mixed(self): 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", }, })
def test_kms_key_without_properties(self): blueprint = Key('kms_key_c', self.ctx) blueprint.resolve_variables([ Variable("KeyAlias", "alias/c-test-key"), ]) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_variable_resolve_simple_lookup(self): var = Variable("Param1", "${output fakeStack::FakeOutput}") self.assertEqual(len(var.lookups), 1) self.provider.get_output.return_value = "resolved" var.resolve(self.context, self.provider) self.assertTrue(var.resolved) self.assertEqual(var.value, "resolved")
def test_variable_resolve_nested_lookup(self): stack = Stack(definition=generate_definition("vpc", 1), context=self.context) stack.set_outputs({ "FakeOutput": "resolved", "FakeOutput2": "resolved2", }) def mock_handler(value, context, provider, **kwargs): return "looked up: {}".format(value) register_lookup_handler("lookup", mock_handler) self.context.get_stack.return_value = stack var = Variable( "Param1", "${lookup ${lookup ${output fakeStack::FakeOutput}}}", ) self.assertEqual( len(var.lookups), 1, "should only parse out the first complete lookup first", ) var.resolve(self.context, self.provider) self.assertTrue(var.resolved) self.assertEqual(var.value, "looked up: looked up: resolved")
def test_create_template(self): blueprint = FunctionScheduler('test_aws_lambda_FunctionScheduler', self.ctx) blueprint.resolve_variables([ Variable( "CloudwatchEventsRule", { "MyTestFuncSchedule": { "Description": "The AWS Lambda schedule for " "my-powerful-test-function", "ScheduleExpression": "rate(15 minutes)", "State": "ENABLED", "Targets": [ { "Id": "my-powerful-test-function", "Arn": "arn:aws:lambda:us-east-1:01234:" "function:my-Function-162L1234" }, ], } }) ]) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_create_template(self): blueprint = SubscriptionFilters( 'test_cloudwatch_logs_subscription_filters', self.ctx ) blueprint.resolve_variables( [ Variable( "SubscriptionFilters", { "Filter1": { "DestinationArn": GetAtt("KinesisStream1", "Arn"), "FilterPattern": "{$.userIdentity.type = Root}", "LogGroupName": Ref("LogGroup1"), }, "Filter2": { "DestinationArn": GetAtt("KinesisStream2", "Arn"), "FilterPattern": "{$.userIdentity.type = Root}", "LogGroupName": Ref("LogGroup2"), }, } ) ] ) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_create_template(self): blueprint = ElasticFileSystem('test_efs_ElasticFileSystem', self.ctx) variables = EFS_VARIABLES blueprint.resolve_variables( [Variable(k, v) for k, v in variables.items()]) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_variable_resolve_default_lookup_empty(self): var = Variable("Param1", "${default fakeStack::}") self.assertEqual(len(var.lookups), 1) var.resolve(self.context, self.provider) self.assertTrue(var.resolved) self.assertEqual(var.value, "") self.assertEqual(len(var.lookups), 0)
def test_create_template(self): blueprint = GenericResourceCreator( 'test_generic_GenericResourceCreator', self.ctx) blueprint.resolve_variables([ Variable('Class', 'ec2.Volume'), Variable('Output', 'VolumeId'), Variable( 'Properties', { 'VolumeType': 'gp2', 'Size': '600', 'Encrypted': 'true', 'AvailabilityZone': 'us-east-1b', }), ]) blueprint.create_template() self.assertRenderedBlueprint(blueprint)
def test_resolve_lookups_list_unknown_lookup(self): with self.assertRaises(UnknownLookupType): Variable( "MyVar", [ "${bad_lookup foo}", "random string", ] )
def test_resolve_lookups_list_failed_variable_lookup(self): variable = Variable( "MyVar", [ "random string", "${output foo::bar}", "random string", ] ) self.resolve_lookups_with_output_handler_raise_valueerror(variable)
def test_error_when_specify_both_hosted_zone_id_and_name(self): blueprint = DNSRecords('route53_both_hosted_zone_id_and_name_error', self.ctx) blueprint.resolve_variables([ Variable("RecordSets", [ { "Name": "host.testdomain.com.", "Type": "A", "ResourceRecords": ["10.0.0.1"], }, ]), Variable("HostedZoneId", "fake_zone_id"), Variable("HostedZoneName", "fake_zone_name"), ]) with self.assertRaises(ValueError): blueprint.create_template()
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"), Variable("bar", "foo")]) self.assertEqual(expected_json, blueprint.to_json())
def test_variable_replace_simple_lookup(self): var = Variable("Param1", "${output fakeStack::FakeOutput}") self.assertEqual(len(var.lookups), 1) resolved_lookups = { mock_lookup("fakeStack::FakeOutput", "output"): "resolved", } var.replace(resolved_lookups) self.assertEqual(var.value, "resolved")
def _resolve_troposphere_var(self, tpe, value, **kwargs): var_name = "testVar" var_def = {"type": TroposphereType(tpe, **kwargs)} provided_variable = Variable(var_name, value) blueprint_name = "testBlueprint" return resolve_variable(var_name, var_def, provided_variable, blueprint_name)
def test_cloudfront_alias_adds_hosted_zone_id(self): blueprint = DNSRecords('route53_cf_alias_hosted_zone_id', self.ctx) blueprint.resolve_variables([ Variable("RecordSets", [ { "Name": "host.testdomain.com.", "Type": "A", "AliasTarget": { "DNSName": "d123456789f.cloudfront.net.", }, }, ]), Variable("HostedZoneId", "fake_zone_id"), ]) record_sets = blueprint.create_template() self.assertEqual(record_sets[0].AliasTarget.HostedZoneId, "Z2FDTNDATAQYW2")
def test_variable_replace_no_lookups_list(self): var = Variable("Param1", ["something", "here"]) self.assertEqual(len(var.lookups), 0) resolved_lookups = { mock_lookup("fakeStack::FakeOutput", "output"): "resolved", } var.replace(resolved_lookups) self.assertEqual(var.value, ["something", "here"])