def test_stack_create(): s = Stack(name='teststack') s.body assert True with pytest.raises(AssertionError): # Create a stack with an invalid name s = Stack(name='test_stack')
def test_create_stack(): s = Stack(name='teststack') aws_env = AWSEnv(regions=['us-east-1']) with default_region('us-east-1'): cfn_client = aws_env.client('cloudformation', region='us-east-1') stubber = Stubber(cfn_client) stubber.add_response('create_stack', {}, { 'Capabilities': ['CAPABILITY_IAM'], 'StackName': 'teststack', 'TemplateBody': ANY }) with stubber: s.create()
def test_create_network(): s = Stack(name='teststack') s = Stack(name='MyStack') s += VPC('BuildVPC', '10.10.0.0/16') s += InternetGateway('Gate') s += Subnet('BuildPublicSubnet', s['BuildVPC'], '10.10.10.0/24') s += Subnet('BuildPrivateSubnet', s['BuildVPC'], '10.10.20.0/24') s += VPCGatewayAttachment('GateAttach', s['BuildVPC'], s['Gate']) s += RouteTable('RT', s['BuildVPC']) s += Route('PRoute', s['RT'], '0.0.0.0/0', s['Gate'], s['GateAttach']) s += SubnetRouteTableAssociation('RTSAssoc', s['BuildPublicSubnet'], s['RT']) assert s.body
def test_create_change_set(): s = Stack(name="teststack") aws_env = AWSEnv(regions=["us-east-1"]) with default_region("us-east-1"): cfn_client = aws_env.client("cloudformation", region="us-east-1") stubber = Stubber(cfn_client) stubber.add_response( "create_change_set", {}, { "Capabilities": ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"], "StackName": "teststack", "ChangeSetName": "name1", "TemplateBody": ANY, }, ) stubber.add_response( "create_change_set", {}, { "Capabilities": ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"], "ChangeSetName": "name2", "StackName": "teststack", "TemplateURL": ANY, }, ) with stubber: s.create_change_set("name1") s.create_change_set("name2", url="noprotocol://nothing")
def test_create_change_set(): s = Stack(name='teststack') aws_env = AWSEnv(regions=['us-east-1']) with default_region('us-east-1'): cfn_client = aws_env.client('cloudformation', region='us-east-1') stubber = Stubber(cfn_client) stubber.add_response( 'create_change_set', {}, { 'Capabilities': ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM'], 'StackName': 'teststack', 'ChangeSetName': 'name1', 'TemplateBody': ANY }) stubber.add_response( 'create_change_set', {}, { 'Capabilities': ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM'], 'ChangeSetName': 'name2', 'StackName': 'teststack', 'TemplateURL': ANY }) with stubber: s.create_change_set('name1') s.create_change_set('name2', url='noprotocol://nothing')
def test_create_network(): s = Stack(name="teststack") s = Stack(name="MyStack") s += VPC("BuildVPC", "10.10.0.0/16") s += InternetGateway("Gate") s += Subnet("BuildPublicSubnet", s["BuildVPC"], "10.10.10.0/24") s += Subnet("BuildPrivateSubnet", s["BuildVPC"], "10.10.20.0/24") s += VPCGatewayAttachment("GateAttach", s["BuildVPC"], s["Gate"]) s += RouteTable("RT", s["BuildVPC"]) s += Route("PRoute", s["RT"], "0.0.0.0/0", s["Gate"], s["GateAttach"]) s += SubnetRouteTableAssociation("RTSAssoc", s["BuildPublicSubnet"], s["RT"]) p = PolicyDocument().append( Allow( to="GetObject", on="arn:aws:s3:::abucket/*", apply_to=Principal(PrincipalKind.SERVICE, "ec2.amazonaws.com"), ) ) s += VPCEndpoint("S3EndPoint", "s3", s["BuildVPC"], [s["RT"]], policy_document=p) assert s.body
def test_create_network(): s = Stack(name='teststack') s = Stack(name='MyStack') s += VPC('BuildVPC', '10.10.0.0/16') s += InternetGateway('Gate') s += Subnet('BuildPublicSubnet', s['BuildVPC'], '10.10.10.0/24') s += Subnet('BuildPrivateSubnet', s['BuildVPC'], '10.10.20.0/24') s += VPCGatewayAttachment('GateAttach', s['BuildVPC'], s['Gate']) s += RouteTable('RT', s['BuildVPC']) s += Route('PRoute', s['RT'], '0.0.0.0/0', s['Gate'], s['GateAttach']) s += SubnetRouteTableAssociation('RTSAssoc', s['BuildPublicSubnet'], s['RT']) p = PolicyDocument().append( Allow(to='GetObject', on='arn:aws:s3:::abucket/*', apply_to=Principal(PrincipalKind.SERVICE, 'ec2.amazonaws.com'))) s += VPCEndpoint('S3EndPoint', 's3', s['BuildVPC'], [s['RT']], policy_document=p) assert s.body
def test_cfn_init_set(): s = Stack(name='teststack') aws_env = AWSEnv(regions=['us-east-1'], stub=True) with default_region('us-east-1'): stub = aws_env.stub('ec2', region='us-east-1') stub.add_response( 'describe_images', { 'Images': [{ 'ImageId': 'ami-1234', 'RootDeviceName': '/dev/sda1', 'Tags': [] }] }, {'ImageIds': ANY}) s += Instance('server', AMI('ami-1234')) s['server'].set_cfn_init(s) assert s.body
def test_nat_gateway(): """Create a NATGateway.""" s = Stack(name="MyStack") s += VPC("BuildVPC", "10.10.0.0/16") s += Subnet("BuildPublicSubnet", s["BuildVPC"], "10.10.10.0/24") s += Subnet("BuildPrivateSubnet", s["BuildVPC"], "10.10.20.0/24") s += InternetGateway("Gate") s += VPCGatewayAttachment("GateAttach", s["BuildVPC"], s["Gate"]) s += RouteTable("RT", s["BuildVPC"]) s += Route("PRoute", s["RT"], "0.0.0.0/0", s["Gate"], s["GateAttach"]) s += SubnetRouteTableAssociation("RTSAssoc", s["BuildPublicSubnet"], s["RT"]) s += EIP("NatEip", s["GateAttach"]) s += NatGateway("NatGate", s["NatEip"], s["BuildPublicSubnet"]) s += RouteTable("NATRT", s["BuildVPC"]) s += Route("NATRoute", s["NATRT"], "0.0.0.0/0", s["NatGate"], s["GateAttach"]) s += SubnetRouteTableAssociation("NatRTSAssoc", s["BuildPrivateSubnet"], s["NATRT"]) assert s.body
def test_validate(): s = Stack(name='teststack') aws_env = AWSEnv(regions=['us-east-1']) with default_region('us-east-1'): cfn_client = aws_env.client('cloudformation', region='us-east-1') stubber = Stubber(cfn_client) stubber.add_response('validate_template', {}, {'TemplateBody': ANY}) stubber.add_response('validate_template', {}, {'TemplateURL': ANY}) with stubber: s.validate() s.validate(url='noprotocol://nothing')
def test_validate(): s = Stack(name="teststack") aws_env = AWSEnv(regions=["us-east-1"]) with default_region("us-east-1"): cfn_client = aws_env.client("cloudformation", region="us-east-1") stubber = Stubber(cfn_client) stubber.add_response("validate_template", {}, {"TemplateBody": ANY}) stubber.add_response("validate_template", {}, {"TemplateURL": ANY}) with stubber: s.validate() s.validate(url="noprotocol://nothing")
def test_cfn_init_set(): s = Stack(name="teststack") aws_env = AWSEnv(regions=["us-east-1"], stub=True) with default_region("us-east-1"): stub = aws_env.stub("ec2", region="us-east-1") stub.add_response( "describe_images", { "Images": [ {"ImageId": "ami-1234", "RootDeviceName": "/dev/sda1", "Tags": []} ] }, {"ImageIds": ANY}, ) s += Instance("server", AMI("ami-1234")) s["server"].set_cfn_init() assert s.body
def test_nat_gateway(): """Create a NATGateway.""" s = Stack(name='MyStack') s += VPC('BuildVPC', '10.10.0.0/16') s += Subnet('BuildPublicSubnet', s['BuildVPC'], '10.10.10.0/24') s += Subnet('BuildPrivateSubnet', s['BuildVPC'], '10.10.20.0/24') s += InternetGateway('Gate') s += VPCGatewayAttachment('GateAttach', s['BuildVPC'], s['Gate']) s += RouteTable('RT', s['BuildVPC']) s += Route('PRoute', s['RT'], '0.0.0.0/0', s['Gate'], s['GateAttach']) s += SubnetRouteTableAssociation('RTSAssoc', s['BuildPublicSubnet'], s['RT']) s += EIP('NatEip', s['GateAttach']) s += NatGateway('NatGate', s['NatEip'], s['BuildPublicSubnet']) s += RouteTable('NATRT', s['BuildVPC']) s += Route('NATRoute', s['NATRT'], '0.0.0.0/0', s['NatGate'], s['GateAttach']) s += SubnetRouteTableAssociation('NatRTSAssoc', s['BuildPrivateSubnet'], s['NATRT']) assert s.body
def execute_for_stack(self, stack: Stack) -> int: """Execute application for a given stack and return exit status. :param Stack: the stack on which the application executes """ assert self.args is not None try: if self.args.command in ("push", "update"): # Synchronize resources to the S3 bucket s3 = self.aws_env.client("s3") with tempfile.TemporaryDirectory() as tempd: # Push data associated with CFNMain and then all data # related to the stack self.create_data_dir(root_dir=tempd) stack.create_data_dir(root_dir=tempd) if self.s3_data_key is not None: # synchronize data to the bucket before creating the stack for f in find(tempd): with open(f, "rb") as fd: subkey = os.path.relpath(f, tempd).replace( "\\", "/") logging.info( "Upload %s to %s:%s%s", subkey, self.s3_bucket, self.s3_data_key, subkey, ) s3.put_object( Bucket=self.s3_bucket, Body=fd, ServerSideEncryption="AES256", Key=self.s3_data_key + subkey, ) if self.s3_template_key is not None: logging.info("Upload template to %s:%s", self.s3_bucket, self.s3_template_key) s3.put_object( Bucket=self.s3_bucket, Body=stack.body.encode("utf-8"), ServerSideEncryption="AES256", Key=self.s3_template_key, ) logging.info("Validate template for stack %s" % stack.name) try: stack.validate(url=self.s3_template_url) except Exception: logging.error("Invalid cloud formation template") logging.error(stack.body) raise if stack.exists(): changeset_name = "changeset%s" % int(time.time()) logging.info("Push changeset: %s" % changeset_name) stack.create_change_set(changeset_name, url=self.s3_template_url) result = stack.describe_change_set(changeset_name) while result["Status"] in ("CREATE_PENDING", "CREATE_IN_PROGRESS"): time.sleep(1.0) result = stack.describe_change_set(changeset_name) if result["Status"] == "FAILED": change_executed = False if ("The submitted information didn't contain changes" in result["StatusReason"]): logging.warning(result["StatusReason"]) change_executed = True else: logging.error(result["StatusReason"]) stack.delete_change_set(changeset_name) if not change_executed: return 1 else: for el in result["Changes"]: if "ResourceChange" not in el: continue logging.info( "%-8s %-32s: (replacement:%s)", el["ResourceChange"].get("Action"), el["ResourceChange"].get("LogicalResourceId"), el["ResourceChange"].get("Replacement", "n/a"), ) if self.args.apply_changeset: ask = input("Apply change (y/N): ") if ask[0] in "Yy": stack.execute_change_set( changeset_name=changeset_name, wait=self.args.wait_stack_creation, ) return 0 else: logging.info("Create new stack") stack.create(url=self.s3_template_url, wait=self.args.wait_stack_creation) elif self.args.command == "show": print(stack.body) elif self.args.command == "protect": # Enable termination protection result = stack.enable_termination_protection() if self.stack_policy_body is not None: stack.set_stack_policy(self.stack_policy_body) else: print("No stack policy to set") elif self.args.command == "show-cfn-policy": try: print( json.dumps( stack.cfn_policy_document(). as_dict, # type: ignore indent=2, )) except AttributeError as attr_e: print( f"command supported only with troposphere stacks: {attr_e}" ) elif self.args.command == "delete": stack.delete(wait=self.args.wait_stack_creation) return 0 except botocore.exceptions.ClientError as e: logging.error(str(e)) return 1
def create_stack(self): return [Stack(name="existing-stack")]
def test_stack_compose(): s = Stack(name="teststack") s2 = Stack(name="teststack2") s2.add(Bucket("bucket1")).add(Bucket("bucket2")) s += s2 assert len(s.export()["Resources"]) == 2
def test_stack_compose(): s = Stack(name='teststack') s2 = Stack(name='teststack2') s2.add(Bucket('bucket1')).add(Bucket('bucket2')) s += s2 assert len(s.export()['Resources']) == 2
def create_stack(self): return [Stack(name="first-stack"), Stack(name="second-stack")]
def create_stack(self): return Stack(name="teststack")
def create_stack(self): return Stack(name='teststack')