Name resources via CloudFormation naming convention and tag EC2 resources.

* Make sure taggable resources are tagged per convention: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack-parameters.html
  * Update CloudFormation parsing to use logical resource ids and name resources as CloudFomation would.
  * Fix tests for CloudFormation stack integration.
This commit is contained in:
Joseph Lawson 2014-10-20 15:16:39 -04:00
parent 91a74424e5
commit 832769b8a7
2 changed files with 39 additions and 24 deletions

View File

@ -94,7 +94,7 @@ def resource_name_property_from_type(resource_type):
return NAME_TYPE_MAP.get(resource_type)
def parse_resource(resource_name, resource_json, resources_map):
def parse_resource(logical_id, resource_json, resources_map):
resource_type = resource_json['Type']
resource_class = resource_class_from_type(resource_type)
if not resource_class:
@ -108,11 +108,17 @@ def parse_resource(resource_name, resource_json, resources_map):
if not resource_name_property in resource_json['Properties']:
resource_json['Properties'][resource_name_property] = '{0}-{1}-{2}'.format(
resources_map.get('AWS::StackName'),
resource_name,
logical_id,
random_suffix())
resource_name = resource_json['Properties'][resource_name_property]
else:
resource_name = '{0}-{1}-{2}'.format(resources_map.get('AWS::StackName'),
logical_id,
random_suffix())
resource = resource_class.create_from_cloudformation_json(resource_name, resource_json)
resource.type = resource_type
resource.logical_resource_id = resource_name
resource.logical_resource_id = logical_id
return resource
@ -136,24 +142,24 @@ class ResourceMap(collections.Mapping):
}
def __getitem__(self, key):
resource_name = key
resource_logical_id = key
if resource_name in self._parsed_resources:
return self._parsed_resources[resource_name]
if resource_logical_id in self._parsed_resources:
return self._parsed_resources[resource_logical_id]
else:
resource_json = self._resource_json_map.get(resource_name)
new_resource = parse_resource(resource_name, resource_json, self)
self._parsed_resources[resource_name] = new_resource
resource_json = self._resource_json_map.get(resource_logical_id)
new_resource = parse_resource(resource_logical_id, resource_json, self)
self._parsed_resources[resource_logical_id] = new_resource
return new_resource
def __iter__(self):
return iter(self.resource_names)
return iter(self.resources)
def __len__(self):
return len(self._resource_json_map)
@property
def resource_names(self):
def resources(self):
return self._resource_json_map.keys()
def load_parameters(self):
@ -167,5 +173,10 @@ class ResourceMap(collections.Mapping):
# Since this is a lazy map, to create every object we just need to
# iterate through self.
for resource_name in self.resource_names:
self[resource_name]
tags = {'aws:cloudformation:stack-name': self.get('AWS::StackName'),
'aws:cloudformation:stack-id': self.get('AWS::StackId')}
for resource in self.resources:
self[resource]
if isinstance(self[resource], ec2_models.TaggedEC2Resource):
tags['aws:cloudformation:logical-id'] = resource
ec2_models.ec2_backend.create_tags([self[resource].physical_resource_id],tags)

View File

@ -75,7 +75,7 @@ def test_stack_ec2_integration():
stack = conn.describe_stacks()[0]
instance = stack.describe_resources()[0]
instance.resource_type.should.equal('AWS::EC2::Instance')
instance.logical_resource_id.should.equal("WebServerGroup")
instance.logical_resource_id.should.contain("WebServerGroup")
instance.physical_resource_id.should.equal(ec2_instance.id)
@ -186,7 +186,7 @@ def test_stack_security_groups():
ec2_conn = boto.connect_ec2()
security_groups = ec2_conn.get_all_security_groups()
for group in security_groups:
if group.name == "InstanceSecurityGroup":
if "InstanceSecurityGroup" in group.name:
instance_group = group
else:
other_group = group
@ -245,6 +245,7 @@ def test_autoscaling_group_with_elb():
"InstancePort": "80",
"Protocol": "HTTP"
}],
"LoadBalancerName": "my-elb",
"HealthCheck": {
"Target": "80",
"HealthyThreshold": "3",
@ -267,7 +268,7 @@ def test_autoscaling_group_with_elb():
autoscale_conn = boto.connect_autoscale()
autoscale_group = autoscale_conn.get_all_groups()[0]
autoscale_group.launch_config_name.should.equal("my-launch-config")
autoscale_group.launch_config_name.should.contain("my-launch-config")
autoscale_group.load_balancers[0].should.equal('my-elb')
# Confirm the Launch config was actually created
@ -280,13 +281,13 @@ def test_autoscaling_group_with_elb():
stack = conn.describe_stacks()[0]
resources = stack.describe_resources()
as_group_resource = [resource for resource in resources if resource.resource_type == 'AWS::AutoScaling::AutoScalingGroup'][0]
as_group_resource.physical_resource_id.should.equal("my-as-group")
as_group_resource.physical_resource_id.should.contain("my-as-group")
launch_config_resource = [resource for resource in resources if resource.resource_type == 'AWS::AutoScaling::LaunchConfiguration'][0]
launch_config_resource.physical_resource_id.should.equal("my-launch-config")
launch_config_resource.physical_resource_id.should.contain("my-launch-config")
elb_resource = [resource for resource in resources if resource.resource_type == 'AWS::ElasticLoadBalancing::LoadBalancer'][0]
elb_resource.physical_resource_id.should.equal("my-elb")
elb_resource.physical_resource_id.should.contain("my-elb")
@mock_ec2()
@ -427,18 +428,21 @@ def test_iam_roles():
iam_conn = boto.connect_iam()
role = iam_conn.get_role("my-role")
role.role_name.should.equal("my-role")
role_result = iam_conn.list_roles()['list_roles_response']['list_roles_result']['roles'][0]
role = iam_conn.get_role(role_result.role_name)
role.role_name.should.contain("my-role")
role.path.should.equal("my-path")
instance_profile = iam_conn.get_instance_profile("my-instance-profile")
instance_profile.instance_profile_name.should.equal("my-instance-profile")
instance_profile_response = iam_conn.list_instance_profiles()['list_instance_profiles_response']
cfn_instance_profile = instance_profile_response['list_instance_profiles_result']['instance_profiles'][0]
instance_profile = iam_conn.get_instance_profile(cfn_instance_profile.instance_profile_name)
instance_profile.instance_profile_name.should.contain("my-instance-profile")
instance_profile.path.should.equal("my-path")
instance_profile.role_id.should.equal(role.role_id)
autoscale_conn = boto.connect_autoscale()
launch_config = autoscale_conn.get_all_launch_configurations()[0]
launch_config.instance_profile_name.should.equal("my-instance-profile")
launch_config.instance_profile_name.should.contain("my-instance-profile")
stack = conn.describe_stacks()[0]
resources = stack.describe_resources()