Add Fn::Sub support
This commit is contained in:
		
							parent
							
								
									711dbaf4fd
								
							
						
					
					
						commit
						d3faaad46b
					
				@ -4,6 +4,7 @@ import functools
 | 
				
			|||||||
import logging
 | 
					import logging
 | 
				
			||||||
import copy
 | 
					import copy
 | 
				
			||||||
import warnings
 | 
					import warnings
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from moto.autoscaling import models as autoscaling_models
 | 
					from moto.autoscaling import models as autoscaling_models
 | 
				
			||||||
from moto.awslambda import models as lambda_models
 | 
					from moto.awslambda import models as lambda_models
 | 
				
			||||||
@ -167,6 +168,25 @@ def clean_json(resource_json, resources_map):
 | 
				
			|||||||
            select_list = clean_json(resource_json['Fn::Select'][1], resources_map)
 | 
					            select_list = clean_json(resource_json['Fn::Select'][1], resources_map)
 | 
				
			||||||
            return select_list[select_index]
 | 
					            return select_list[select_index]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if 'Fn::Sub' in resource_json:
 | 
				
			||||||
 | 
					            if isinstance(resource_json['Fn::Sub'], list):
 | 
				
			||||||
 | 
					                warnings.warn(
 | 
				
			||||||
 | 
					                    "Tried to parse Fn::Sub with variable mapping but it's not supported by moto's CloudFormation implementation")
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                fn_sub_value = clean_json(resource_json['Fn::Sub'], resources_map)
 | 
				
			||||||
 | 
					                to_sub = re.findall('(?=\${)[^!^"]*?}', fn_sub_value)
 | 
				
			||||||
 | 
					                literals = re.findall('(?=\${!)[^"]*?}', fn_sub_value)
 | 
				
			||||||
 | 
					                for sub in to_sub:
 | 
				
			||||||
 | 
					                    if '.' in sub:
 | 
				
			||||||
 | 
					                        cleaned_ref = clean_json({'Fn::GetAtt': re.findall('(?<=\${)[^"]*?(?=})', sub)[0].split('.')}, resources_map)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        cleaned_ref = clean_json({'Ref': re.findall('(?<=\${)[^"]*?(?=})', sub)[0]}, resources_map)
 | 
				
			||||||
 | 
					                    fn_sub_value = fn_sub_value.replace(sub, cleaned_ref)
 | 
				
			||||||
 | 
					                for literal in literals:
 | 
				
			||||||
 | 
					                    fn_sub_value = fn_sub_value.replace(literal, literal.replace('!', ''))
 | 
				
			||||||
 | 
					                return fn_sub_value
 | 
				
			||||||
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        cleaned_json = {}
 | 
					        cleaned_json = {}
 | 
				
			||||||
        for key, value in resource_json.items():
 | 
					        for key, value in resource_json.items():
 | 
				
			||||||
            cleaned_val = clean_json(value, resources_map)
 | 
					            cleaned_val = clean_json(value, resources_map)
 | 
				
			||||||
 | 
				
			|||||||
@ -85,6 +85,26 @@ split_select_template = {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub_template = {
 | 
				
			||||||
 | 
					    "AWSTemplateFormatVersion": "2010-09-09",
 | 
				
			||||||
 | 
					    "Resources": {
 | 
				
			||||||
 | 
					        "Queue1": {
 | 
				
			||||||
 | 
					            "Type": "AWS::SQS::Queue",
 | 
				
			||||||
 | 
					            "Properties": {
 | 
				
			||||||
 | 
					                "QueueName": {"Fn::Sub": '${AWS::StackName}-queue-${!Literal}'},
 | 
				
			||||||
 | 
					                "VisibilityTimeout": 60,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        "Queue2": {
 | 
				
			||||||
 | 
					            "Type": "AWS::SQS::Queue",
 | 
				
			||||||
 | 
					            "Properties": {
 | 
				
			||||||
 | 
					                "QueueName": {"Fn::Sub": '${Queue1.QueueName}'},
 | 
				
			||||||
 | 
					                "VisibilityTimeout": 60,
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
outputs_template = dict(list(dummy_template.items()) +
 | 
					outputs_template = dict(list(dummy_template.items()) +
 | 
				
			||||||
                        list(output_dict.items()))
 | 
					                        list(output_dict.items()))
 | 
				
			||||||
bad_outputs_template = dict(
 | 
					bad_outputs_template = dict(
 | 
				
			||||||
@ -99,6 +119,7 @@ bad_output_template_json = json.dumps(bad_outputs_template)
 | 
				
			|||||||
get_attribute_outputs_template_json = json.dumps(
 | 
					get_attribute_outputs_template_json = json.dumps(
 | 
				
			||||||
    get_attribute_outputs_template)
 | 
					    get_attribute_outputs_template)
 | 
				
			||||||
split_select_template_json = json.dumps(split_select_template)
 | 
					split_select_template_json = json.dumps(split_select_template)
 | 
				
			||||||
 | 
					sub_template_json = json.dumps(sub_template)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_parse_stack_resources():
 | 
					def test_parse_stack_resources():
 | 
				
			||||||
@ -294,3 +315,15 @@ def test_parse_split_and_select():
 | 
				
			|||||||
    queue = stack.resource_map['Queue']
 | 
					    queue = stack.resource_map['Queue']
 | 
				
			||||||
    queue.name.should.equal("myqueue")
 | 
					    queue.name.should.equal("myqueue")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def test_sub():
 | 
				
			||||||
 | 
					    stack = FakeStack(
 | 
				
			||||||
 | 
					        stack_id="test_id",
 | 
				
			||||||
 | 
					        name="test_stack",
 | 
				
			||||||
 | 
					        template=sub_template_json,
 | 
				
			||||||
 | 
					        parameters={},
 | 
				
			||||||
 | 
					        region_name='us-west-1')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    queue1 = stack.resource_map['Queue1']
 | 
				
			||||||
 | 
					    queue2 = stack.resource_map['Queue2']
 | 
				
			||||||
 | 
					    queue2.name.should.equal(queue1.name)
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user