def jinja_txt(self, value): if not self.stack._deploying: return value context = self.stack.infra.context env = utils.jinja_env(context) t = env[0].from_string(value) return t.render(context.vars)
def jinja_env_vars(self): if not self._deploying or \ len(self.vars.keys()) <= 0: return context = self.infra.context env = utils.jinja_env(context) for k, v in self.vars.items(): t = env[0].from_string(v) self.vars[k] = t.render(context.vars)
def test_infra(): infra = stackformation.Infra("test") test_infra = infra.create_sub_infra("test") ec2_stack = test_infra.add_stack(ec2.EC2Stack('test')) env = utils.jinja_env(test_infra.context, True) return { 'infra': infra, 'test_infra': test_infra, 'ec2_stack': ec2_stack, 'env': env }
def review(self, infra): review = { 'dependent_stacks': [], } review['info'] = self.stack_info() # get stack dependencies deps = infra.get_dependent_stacks(self) # noqa for k, v in deps.items(): info = v.stack_info() v.load_stack_outputs(self.infra) outputs = v.get_outputs() params = {} if info and info.get('Parameters'): for p in info.get('Parameters'): params.update({p['ParameterKey']: p['ParameterValue']}) review['dependent_stacks'].append({ 'stack': v, 'outputs': outputs, 'stack_info': info, 'parameters': params }) context = self.infra.context env = utils.jinja_env(context) review['template'] = self.build_template() parameters = self.get_parameters() template_vars = self.render_template_components(env[0], context) # noqa self.before_deploy(context, parameters) review['parameters'] = self.fill_params(parameters, context) review['template_vars'] = template_vars return review
def get_dependent_stacks(self, stack): results = {} params = list(stack.get_parameters().keys()) env = utils.jinja_env({}, True) stack.render_template_components(env[0], Context()) params += env[1] stacks = self.list_stacks() for stk in stacks: ops = stk.get_outputs().keys() for o in ops: if o in params: results.update({stk.get_stack_name(): stk}) return results
def test_ec2_stack(infra): ebs_stack = infra[6] eip_stack = infra[5] vpc_stack = infra[4] web_profile = infra[3] iam_stack = infra[2] prod_infra = infra[1] infra = infra[0] ec2_stack = prod_infra.add_stack( ec2.EC2Stack("Web", vpc_stack, web_profile)) web_vol = ebs_stack.add_volume(ebs.EBSVolume("Web", 100)) ec2_stack.add_volume(web_vol) ssh_sg = vpc_stack.add_security_group(vpc.SSHSecurityGroup("SSH")) ec2_stack.add_security_group(ssh_sg) ec2_stack.keypair("testkey") ec2_stack.ami = "ami-id" t = ec2_stack.build_template() inst = t.resources['WebEC2Instance'].to_dict() assert ec2_stack.output_instance() == "ProdTestWebEC2WebEC2Instance" assert inst['Properties']['KeyName'] == 'testkey' assert inst['Properties']['NetworkInterfaces'][0]['SubnetId'] == { 'Ref': 'ProdTestVPCPublicSubnet0' } assert inst['Properties']['NetworkInterfaces'][0]['GroupSet'][0] == { 'Ref': 'ProdTestVPCSSHSecurityGroup' } ec2_stack.private_subnet = True t = ec2_stack.build_template() inst = t.resources['WebEC2Instance'].to_dict() assert inst['Properties']['NetworkInterfaces'][0]['SubnetId'] == { 'Ref': 'ProdTestVPCPrivateSubnet1' } web_eip = eip_stack.add_ip("WebEip") ec2_stack.add_user_data(user_data.EIPInfo(web_eip)) env = utils.jinja_env(prod_infra.context, True) res = ec2_stack.render_template_components(env[0], prod_infra.context) assert env[1][0] == 'ProdTestTestEIPWebEipEIP' assert env[1][1] == 'ProdTestTestEIPWebEipAllocationId' params = ec2_stack.get_parameters() ec2_stack.before_deploy(prod_infra.context, params) assert prod_infra.get_var("WebUserData0") == res['WebUserData'][0]
def start_deploy(self, infra, context): """ """ present = True # check if the stack has been deployed cf = infra.boto_session.client("cloudformation") try: cf.describe_stacks(StackName=self.get_remote_stack_name()) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == "ValidationError": present = False else: print(e.response['Error']['Code']) print("FATAL ERROR") exit(1) env = utils.jinja_env(context) self._deploying = True template = self.build_template() self._deploying = False parameters = self.get_parameters() template_vars = self.render_template_components(env[0], context) # noqa self.before_deploy(context, parameters) parameters = self.fill_params(parameters, context) dep_kw = { 'StackName': self.get_remote_stack_name(), 'Parameters': parameters, 'Capabilities': ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM'] } # check template size constraint json_template = template.to_json() if len(json_template) < 5100: dep_kw['TemplateBody'] = json_template else: dep_kw['TemplateURL'] = self.upload_to_s3( infra, self.get_remote_stack_name(), json_template) # import json # print(json.dumps(dep_kw, indent=True)) # exit(1) dep_kw['Tags'] = [{ 'Key': 'Stackformation', 'Value': stackformation.__version__ }] try: if present: cf.update_stack(**dep_kw) logger.info('{}UPDATING STACK:{} {}'.format( utils.colors('b'), Style.RESET_ALL, self.get_stack_name())) else: cf.create_stack(**dep_kw) logger.info('{}CREATING STACK:{} {}'.format( utils.colors('b', True), Style.RESET_ALL, self.get_stack_name())) except botocore.exceptions.ClientError as e: err = e.response['Error'] if (err['Code'] == "ValidationError" and re.search("No updates", err['Message'])): # noqa return False else: raise e return True