示例#1
0
    def add_resources(self):
        """Add resources to template."""
        template = self.template
        variables = self.get_variables()

        targetgroup = template.add_resource(
            elasticloadbalancingv2.TargetGroup(
                'TargetGroup',
                HealthCheckIntervalSeconds=variables[
                    'HealthCheckIntervalSeconds'].ref,
                HealthCheckPath=variables['HealthCheckPath'].ref,
                HealthCheckPort=variables['HealthCheckPort'].ref,
                HealthCheckProtocol=variables['HealthCheckProtocol'].ref,
                HealthCheckTimeoutSeconds=variables[
                    'HealthCheckTimeoutSeconds'].ref,
                HealthyThresholdCount=variables['HealthyThresholdCount'].ref,
                UnhealthyThresholdCount=variables['UnhealthyThresholdCount'].
                ref,
                Matcher=elasticloadbalancingv2.Matcher(
                    HttpCode=variables['HealthCheckSuccessCodes'].ref),
                Name=variables['TargetGroupName'].ref,
                Port=variables['AppPort'].ref,
                Protocol=variables['AppProtocol'].ref,
                Tags=Tags(Application=variables['ApplicationName'].ref,
                          Environment=variables['EnvironmentName'].ref),
                TargetType=variables['TargetType'].ref,
                VpcId=variables['VpcId'].ref))

        template.add_output(
            Output("{}Arn".format(targetgroup.title),
                   Description="ARN of the Target Group",
                   Value=Ref(targetgroup),
                   Export=Export(
                       Sub('${AWS::StackName}-%sArn' % targetgroup.title))))
示例#2
0
def create_target_group(stack,
                        name,
                        port,
                        protocol='HTTPS',
                        targets=[],
                        http_codes='200',
                        health_check_path='/',
                        target_type='instance',
                        attributes=False):
    """Add Target Group Resource."""
    target_objects = []

    for target in targets:
        target_objects.append(alb.TargetDescription(Id=target))

    tg_atts = []

    if not attributes:
        tg_atts.append(
            alb.TargetGroupAttribute(
                Key='deregistration_delay.timeout_seconds', Value='300'))
    else:
        for att, value in attributes.items():
            tg_atts.append(alb.TargetGroupAttribute(Key=att, Value=value))

    if http_codes is not None:
        return stack.stack.add_resource(
            alb.TargetGroup('{0}TargetGroup'.format(name),
                            HealthCheckIntervalSeconds='30',
                            HealthCheckProtocol=protocol,
                            HealthCheckTimeoutSeconds='10',
                            HealthyThresholdCount='4',
                            HealthCheckPath=health_check_path,
                            Matcher=alb.Matcher(HttpCode=http_codes),
                            Name='{0}Target'.format(name),
                            Port=port,
                            Protocol=protocol,
                            Targets=target_objects,
                            TargetType=target_type,
                            UnhealthyThresholdCount='3',
                            TargetGroupAttributes=tg_atts,
                            VpcId=Ref(stack.vpc)))

    return stack.stack.add_resource(
        alb.TargetGroup('{0}TargetGroup'.format(name),
                        HealthCheckIntervalSeconds='30',
                        HealthCheckProtocol=protocol,
                        HealthCheckTimeoutSeconds='10',
                        HealthyThresholdCount='3',
                        Name='{0}Target'.format(name),
                        Port=port,
                        Protocol=protocol,
                        Targets=targets,
                        UnhealthyThresholdCount='3',
                        TargetType=target_type,
                        TargetGroupAttributes=tg_atts,
                        VpcId=Ref(stack.vpc)))
示例#3
0
    def handle(self, chain_context):
        chain_context.metadata[META_TARGET_GROUP_NAME] = self.name
        template = chain_context.template

        template.add_resource(
            alb.TargetGroup(self.name,
                            HealthCheckPath="/",
                            HealthCheckIntervalSeconds="30",
                            HealthCheckProtocol="HTTP",
                            HealthCheckTimeoutSeconds="10",
                            HealthyThresholdCount="4",
                            Matcher=alb.Matcher(HttpCode="200"),
                            Port=self.port,
                            Protocol="HTTP",
                            UnhealthyThresholdCount="3",
                            VpcId=self.vpc_id))
示例#4
0
 def create_target_group(self):
     t = self.template
     required_attributes = dict(
         Port=self.vars['ContainerPort'],
         Protocol=self.vars['TargetGroupProtocol'],
         TargetType='ip',
         VpcId=self.vars['VpcId'],
     )
     if self.vars['HealthCheckAttributes']:
         if 'Matcher' in self.vars['HealthCheckAttributes']:
             self.vars['HealthCheckAttributes']['Matcher'] = elb.Matcher(
                 **self.vars['HealthCheckAttributes']['Matcher'])
         tg_attributes = self.vars['HealthCheckAttributes'].copy()
     else:
         tg_attributes = dict()
     tg_attributes.update(required_attributes)
     return t.add_resource(elb.TargetGroup("TargetGroup", **tg_attributes))
示例#5
0
    def handle(self, chain_context):

        # todo: why is this not allowing a reference?

        name = '%sTargetGroup' % chain_context.instance_name

        chain_context.metadata[META_TARGET_GROUP_NAME] = name
        template = chain_context.template

        template.add_resource(alb.TargetGroup(
            name,
            HealthCheckPath="/",
            HealthCheckIntervalSeconds="30",
            HealthCheckProtocol="HTTP",
            HealthCheckTimeoutSeconds="10",
            HealthyThresholdCount="4",
            Matcher=alb.Matcher(HttpCode="200"),
            Port=self.port,
            Protocol="HTTP",
            UnhealthyThresholdCount="3",
            VpcId=self.vpc_id
        ))
示例#6
0
                Join("-", [
                    Select(0, Split("-", Ref("AWS::StackName"))),
                    "cluster-public-subnets"
                ]))),
        SecurityGroups=[Ref("LoadBalancerSecurityGroup")],
    ))

t.add_resource(
    elb.TargetGroup(
        "TargetGroup",
        DependsOn='LoadBalancer',
        HealthCheckIntervalSeconds="20",
        HealthCheckProtocol="HTTP",
        HealthCheckTimeoutSeconds="15",
        HealthyThresholdCount="5",
        Matcher=elb.Matcher(HttpCode="200"),
        Port=3000,
        Protocol="HTTP",
        UnhealthyThresholdCount="3",
        VpcId=ImportValue(
            Join("-", [
                Select(0, Split("-", Ref("AWS::StackName"))), "cluster-vpc-id"
            ])),
    ))

t.add_resource(
    elb.Listener("Listener",
                 Port="3000",
                 Protocol="HTTP",
                 LoadBalancerArn=Ref("LoadBalancer"),
                 DefaultActions=[
示例#7
0
def main():
    t = Template("A template to create a load balanced autoscaled Web flask deployment using ansible.")

    addMapping(t)

    ### VPC CONFIGURATION ###
    vpc = ec2.VPC(
        "MainVPC",
        CidrBlock="10.1.0.0/16"
    )

    t.add_resource(vpc)

    vpc_id = Ref(vpc)

    subnet_1 = ec2.Subnet(
        "WebAppSubnet1",
        t,
        AvailabilityZone="us-east-1a",
        CidrBlock="10.1.0.0/24",
        MapPublicIpOnLaunch=True,
        VpcId=vpc_id,
    )
    subnet_1_id = Ref(subnet_1)

    subnet_2 = ec2.Subnet(
        "WebAppSubnet2",
        t,
        AvailabilityZone="us-east-1b",
        CidrBlock="10.1.1.0/24",
        MapPublicIpOnLaunch=True,
        VpcId=vpc_id,
    )
    subnet_2_id = Ref(subnet_2)

    ### NETWORKING ###
    igw = ec2.InternetGateway("internetGateway", t)

    gateway_to_internet = ec2.VPCGatewayAttachment(
        "GatewayToInternet",
        t,
        VpcId=vpc_id,
        InternetGatewayId=Ref(igw)
    )

    route_table = ec2.RouteTable(
        "subnetRouteTable",
        t,
        VpcId=vpc_id
    )

    route_table_id = Ref(route_table)
    internet_route = ec2.Route(
        "routeToInternet",
        t,
        DependsOn=gateway_to_internet,
        DestinationCidrBlock="0.0.0.0/0",
        GatewayId=Ref(igw),
        RouteTableId=route_table_id
    )
    subnet_1_route_assoc = ec2.SubnetRouteTableAssociation(
        "Subnet1RouteAssociation",
        t,
        RouteTableId=route_table_id,
        SubnetId=Ref(subnet_1)
    )
    subnet_2_route_assoc = ec2.SubnetRouteTableAssociation(
        "Subnet2RouteAssociation",
        t,
        RouteTableId=route_table_id,
        SubnetId=Ref(subnet_2)
    )

    http_ingress = {
        "CidrIp": "0.0.0.0/0",
        "Description": "Allow HTTP traffic in from internet.",
        "IpProtocol": "tcp",
        "FromPort": 80,
        "ToPort": 80,
    }
    ssh_ingress = {
        "CidrIp": "0.0.0.0/0",
        "Description": "Allow SSH traffic in from internet.",
        "IpProtocol": "tcp",
        "FromPort": 22,
        "ToPort": 22,
    }

    elb_sg = ec2.SecurityGroup(
        "elbSecurityGroup",
        t,
        GroupName="WebGroup",
        GroupDescription="Allow web traffic in from internet to ELB",
        VpcId=vpc_id,
        SecurityGroupIngress=[
            http_ingress
        ])
    ssh_sg = ec2.SecurityGroup(
        "sshSecurityGroup",
        t,
        GroupName="SSHGroup",
        GroupDescription="Allow SSH traffic in from internet",
        VpcId=vpc_id,
        SecurityGroupIngress=[
            ssh_ingress
        ]
    )
    elb_sg_id = Ref(elb_sg)
    ssh_sg_id = Ref(ssh_sg)

    autoscale_ingress = {
        "SourceSecurityGroupId": elb_sg_id,
        "Description": "Allow web traffic in from ELB",
        "IpProtocol": "tcp",
        "FromPort": 80,
        "ToPort": 80
    }
    autoscale_sg = ec2.SecurityGroup(
        "WebAutoscaleSG",
        t,
        GroupName="AutoscaleGroup",
        GroupDescription="Allow web traffic in from elb on port 80",
        VpcId=vpc_id,
        SecurityGroupIngress=[
            autoscale_ingress
        ]
    )
    autoscale_sg_id = Ref(autoscale_sg)

    # BUCKETS
    app_bucket = s3.Bucket(
        "CodeDeployApplicationBucket",
        t,
    )

    ### LOAD BALANCING ###
    Web_elb = elb.LoadBalancer(
        "WebElb",
        t,
        Name="WebElb", # TODO: Fix for name conflict
        Subnets=[subnet_1_id, subnet_2_id],
        SecurityGroups=[elb_sg_id]
    )

    Web_target_group = elb.TargetGroup(
        "WebTargetGroup",
        t,
        DependsOn=Web_elb,
        HealthCheckPath="/health",
        HealthCheckPort=80,
        HealthCheckProtocol="HTTP",
        Matcher=elb.Matcher(HttpCode="200"),
        Name="NginxTargetGroup",
        Port=80,
        Protocol="HTTP",
        VpcId=vpc_id
    )

    Web_listener = elb.Listener(
        "WebListener",
        t,
        LoadBalancerArn=Ref(Web_elb),
        DefaultActions=[
            elb.Action("forwardAction",
                TargetGroupArn=Ref(Web_target_group),
                Type="forward"
            )
        ],
        Port=80,
        Protocol="HTTP"
    )

    ### AUTOSCALING ###
    # Everything after sudo -u ubuntu is one command
    # The sudo command is required to properly set file permissions when
    # running the ansible script as it assumes running from non root user
    lc_user_data = Base64(Join("\n",
    [
        "#!/bin/bash",
        "apt-add-repository -y ppa:ansible/ansible",
        "apt-get update && sudo apt-get -y upgrade",
        "apt-get -y install git",
        "apt-get -y install ansible",
        "cd /home/ubuntu/",
        "sudo -H -u ubuntu bash -c '"
        "export LC_ALL=C.UTF-8 && "
        "export LANG=C.UTF-8 && "
        "ansible-pull -U https://github.com/DameonSmith/aws-meetup-ansible.git --extra-vars \"user=ubuntu\"'"
    ]))

    web_instance_role = iam.Role(
        "webInstanceCodeDeployRole",
        t,
        AssumeRolePolicyDocument={
            'Statement': [{
                'Effect': 'Allow',
                'Principal': {
                    'Service': 'ec2.amazonaws.com'
                },
                'Action': 'sts:AssumeRole'
            }]
        },
        Policies=[
            iam.Policy(
                PolicyName="CodeDeployS3Policy",
                PolicyDocument=aws.Policy(
                    Version='2012-10-17',
                    Statement=[
                        aws.Statement(
                            Sid='CodeDeployS3',
                            Effect=aws.Allow,
                            Action=[
                                aws_s3.PutObject,
                                aws_s3.GetObject,
                                aws_s3.GetObjectVersion,
                                aws_s3.DeleteObject,
                                aws_s3.ListObjects,
                                aws_s3.ListBucket,
                                aws_s3.ListBucketVersions,
                                aws_s3.ListAllMyBuckets,
                                aws_s3.ListMultipartUploadParts,
                                aws_s3.ListBucketMultipartUploads,
                                aws_s3.ListBucketByTags,
                            ],
                            Resource=[
                                GetAtt(app_bucket, 'Arn'),
                                Join('', [
                                    GetAtt(app_bucket, 'Arn'),
                                    '/*',
                                ]),
                                "arn:aws:s3:::aws-codedeploy-us-east-2/*",
                                "arn:aws:s3:::aws-codedeploy-us-east-1/*",
                                "arn:aws:s3:::aws-codedeploy-us-west-1/*",
                                "arn:aws:s3:::aws-codedeploy-us-west-2/*",
                                "arn:aws:s3:::aws-codedeploy-ca-central-1/*",
                                "arn:aws:s3:::aws-codedeploy-eu-west-1/*",
                                "arn:aws:s3:::aws-codedeploy-eu-west-2/*",
                                "arn:aws:s3:::aws-codedeploy-eu-west-3/*",
                                "arn:aws:s3:::aws-codedeploy-eu-central-1/*",
                                "arn:aws:s3:::aws-codedeploy-ap-northeast-1/*",
                                "arn:aws:s3:::aws-codedeploy-ap-northeast-2/*",
                                "arn:aws:s3:::aws-codedeploy-ap-southeast-1/*",
                                "arn:aws:s3:::aws-codedeploy-ap-southeast-2/*",
                                "arn:aws:s3:::aws-codedeploy-ap-south-1/*",
                                "arn:aws:s3:::aws-codedeploy-sa-east-1/*",
                            ]
                        )
                    ]
                )
            )
        ]
    )

    web_instance_profile = iam.InstanceProfile(
        "webInstanceProfile",
        t,
        Path='/',
        Roles=[Ref(web_instance_role)],
    )

    Web_launch_config = autoscaling.LaunchConfiguration(
        "webLaunchConfig",
        t,
        ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"), # TODO: Remove magic string
        SecurityGroups=[ssh_sg_id, autoscale_sg_id],
        IamInstanceProfile=Ref(web_instance_profile),
        InstanceType="t2.micro",
        BlockDeviceMappings= [{
            "DeviceName": "/dev/sdk",
            "Ebs": {"VolumeSize": "10"}
        }],
        UserData= lc_user_data,
        KeyName="advanced-cfn",
    )

    Web_autoscaler = autoscaling.AutoScalingGroup(
        "WebAutoScaler",
        t,
        LaunchConfigurationName=Ref(Web_launch_config),
        MinSize="2", # TODO: Change to parameter
        MaxSize="2",
        VPCZoneIdentifier=[subnet_2_id, subnet_1_id],
        TargetGroupARNs= [Ref(Web_target_group)]
    )

    t.add_output([
        Output(
            "ALBDNS",
            Description="The DNS name for the application load balancer.",
            Value=GetAtt(Web_elb, "DNSName")
        )
    ])


    # DEVTOOLS CONFIG
    codebuild_service_role = iam.Role(
        "CMSCodeBuildServiceRole",
        t,
        AssumeRolePolicyDocument={
            'Statement': [{
                'Effect': 'Allow',
                'Principal': {
                    'Service': ['codebuild.amazonaws.com']
                },
                'Action': ['sts:AssumeRole']
            }]
        },
        Policies=[
            iam.Policy(
                PolicyName="CloudWatchLogsPolicy",
                PolicyDocument=aws.Policy(
                    Version="2012-10-17",
                    Statement=[
                        aws.Statement(
                            Sid='logs',
                            Effect=aws.Allow,
                            Action=[
                                aws_logs.CreateLogGroup,
                                aws_logs.CreateLogStream,
                                aws_logs.PutLogEvents
                            ],
                            Resource=['*']
                        )
                    ]
                )
            ),
            iam.Policy(
                PolicyName="s3AccessPolicy",
                PolicyDocument=aws.Policy(
                    Version="2012-10-17",
                    Statement=[
                        aws.Statement(
                            Sid='codebuilder',
                            Effect=aws.Allow,
                            Action=[
                                aws_s3.PutObject,
                                aws_s3.GetObject,
                                aws_s3.GetObjectVersion,
                                aws_s3.DeleteObject
                            ],
                            Resource=[
                                GetAtt(app_bucket, 'Arn'),
                                Join('', [
                                    GetAtt(app_bucket, 'Arn'),
                                    '/*',
                                ])
                            ]
                        )
                    ]
                )
            )
        ]
    )


    github_repo = Parameter(
        "GithubRepoLink",
        Description="Name of the repository you wish to connect to codebuild.",
        Type="String"
    )

    artifact_key = Parameter(
        "ArtifactKey",
        Description="The key for the artifact that codebuild creates.",
        Type="String"
    )

    t.add_parameter(github_repo)
    t.add_parameter(artifact_key)


    cms_code_build_project = codebuild.Project(
        "CMSBuild",
        t,
        Name="CMS-Build",
        Artifacts=codebuild.Artifacts(
            Location=Ref(app_bucket),
            Name=Ref(artifact_key),
            NamespaceType="BUILD_ID",
            Type="S3",
            Packaging="ZIP"
        ),
        Description="Code build for CMS",
        Environment=codebuild.Environment(
            ComputeType="BUILD_GENERAL1_SMALL",
            Image="aws/codebuild/python:3.6.5",
            Type="LINUX_CONTAINER",
        ),
        ServiceRole=GetAtt(codebuild_service_role, 'Arn'),
        Source=codebuild.Source(
            "CMSSourceCode",
            Auth=codebuild.SourceAuth(
                "GitHubAuth",
                Type="OAUTH"
            ),
            Location=Ref(github_repo),
            Type="GITHUB"
        ),
        Triggers=codebuild.ProjectTriggers(
            Webhook=True
        )
    )


    codedeploy_service_role = iam.Role(
        "CMSDeploymentGroupServiceRole",
        t,
        AssumeRolePolicyDocument={
            'Statement': [{
                'Effect': 'Allow',
                'Principal': {
                    'Service': ['codedeploy.amazonaws.com']
                },
                'Action': ['sts:AssumeRole']
            }]
        },
        Policies=[
            iam.Policy(
                PolicyName="CloudWatchLogsPolicy",
                PolicyDocument=aws.Policy(
                    Version="2012-10-17",
                    Statement=[
                        aws.Statement(
                            Sid='logs',
                            Effect=aws.Allow,
                            Action=[
                                aws_logs.CreateLogGroup,
                                aws_logs.CreateLogStream,
                                aws_logs.PutLogEvents
                            ],
                            Resource=['*']
                        )
                    ]
                )
            ),
            iam.Policy(
                PolicyName="s3AccessPolicy",
                PolicyDocument=aws.Policy(
                    Version="2012-10-17",
                    Statement=[
                        aws.Statement(
                            Sid='codebuilder',
                            Effect=aws.Allow,
                            Action=[
                                aws_s3.PutObject,
                                aws_s3.GetObject,
                                aws_s3.GetObjectVersion,
                                aws_s3.DeleteObject
                            ],
                            Resource=[
                                GetAtt(app_bucket, 'Arn'),
                                Join('', [
                                    GetAtt(app_bucket, 'Arn'),
                                    '/*'
                                ])
                            ]
                        )
                    ]
                )
            ),
            iam.Policy(
                PolicyName="autoscalingAccess",
                PolicyDocument=aws.Policy(
                    Version="2012-10-17",
                    Statement=[
                        aws.Statement(
                            Sid='codebuilder',
                            Effect=aws.Allow,
                            Action=[
                                aws.Action('autoscaling', '*'),
                                aws.Action('elasticloadbalancing', '*')
                            ],
                            Resource=[
                                '*'
                            ]
                        )
                    ]
                )
            )
        ]
    )

    cms_codedeploy_application = codedeploy.Application(
        "CMSCodeDeployApplication",
        t,
    )


    cms_deployment_group = codedeploy.DeploymentGroup(
        "CMSDeploymentGroup",
        t,
        DependsOn=[cms_codedeploy_application],
        ApplicationName=Ref(cms_codedeploy_application),
        AutoScalingGroups=[Ref(Web_autoscaler)],
        LoadBalancerInfo=codedeploy.LoadBalancerInfo(
            "CodeDeployLBInfo",
            TargetGroupInfoList=[
                    codedeploy.TargetGroupInfoList(
                        "WebTargetGroup",
                       Name=GetAtt(Web_target_group, "TargetGroupName")
                    )
            ]
        ),
        ServiceRoleArn=GetAtt(codedeploy_service_role, 'Arn')
    )

    print(t.to_yaml())
def main():
    # Initialize template
    template = Template()
    template.set_version("2010-09-09")
    template.set_description("""\
    Configures autoscaling group for nginx app""")

    # Collect template properties through parameters
    InstanceType = template.add_parameter(
        Parameter(
            "InstanceType",
            Type="String",
            Description="WebServer EC2 instance type",
            Default="t2.small",
            AllowedValues=[
                "t2.micro", "t2.small", "t2.medium", "t2.large", "t2.xlarge"
            ],
            ConstraintDescription="Must be a valid EC2 instance type.",
        ))

    KeyName = template.add_parameter(
        Parameter(
            "KeyName",
            Type="String",
            Description="Name of an existing EC2 KeyPair to enable SSH access",
            MinLength="1",
            AllowedPattern="[\x20-\x7E]*",
            MaxLength="255",
            ConstraintDescription="Can contain only ASCII characters.",
        ))

    ScaleCapacity = template.add_parameter(
        Parameter(
            "ScaleCapacity",
            Default="1",
            Type="String",
            Description="Number of nginx servers to run",
        ))

    PublicSubnet1 = template.add_parameter(
        Parameter(
            "PublicSubnet1",
            Type="String",
            Description=
            "A public VPC subnet ID for the nginx app load balancer.",
        ))

    PublicSubnet2 = template.add_parameter(
        Parameter(
            "PublicSubnet2",
            Type="String",
            Description="A public VPC subnet ID for the nginx load balancer.",
        ))

    VPCAvailabilityZone2 = template.add_parameter(
        Parameter(
            "VPCAvailabilityZone2",
            MinLength="1",
            Type="String",
            Description="Second availability zone",
            MaxLength="255",
        ))

    VPCAvailabilityZone1 = template.add_parameter(
        Parameter(
            "VPCAvailabilityZone1",
            MinLength="1",
            Type="String",
            Description="First availability zone",
            MaxLength="255",
        ))

    PrivateSubnet2 = template.add_parameter(
        Parameter(
            "PrivateSubnet2",
            Type="String",
            Description="Second private VPC subnet ID for the nginx app.",
        ))

    PrivateSubnet1 = template.add_parameter(
        Parameter(
            "PrivateSubnet1",
            Type="String",
            Description="First private VPC subnet ID for the nginx app.",
        ))

    VpcId = template.add_parameter(
        Parameter(
            "VpcId",
            Type="String",
            Description="VPC Id.",
        ))

    # as of now only provide centos based ami id
    AmiId = template.add_parameter(
        Parameter(
            "AmiId",
            Type="String",
            Description="AMI Id.",
        ))

    # Create a common security group
    NginxInstanceSG = template.add_resource(
        ec2.SecurityGroup(
            "InstanceSecurityGroup",
            VpcId=Ref(VpcId),
            GroupDescription="Enable SSH and HTTP access on the inbound port",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="10.0.0.0/8",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="80",
                    ToPort="80",
                    CidrIp="0.0.0.0/0",
                )
            ]))

    # Add the application LB
    ApplicationElasticLB = template.add_resource(
        elb.LoadBalancer("ApplicationElasticLB",
                         Name="ApplicationElasticLB",
                         Scheme="internet-facing",
                         Subnets=[Ref(PublicSubnet1),
                                  Ref(PublicSubnet2)],
                         SecurityGroups=[Ref(NginxInstanceSG)]))

    # Add Target Group for the ALB
    TargetGroupNginx = template.add_resource(
        elb.TargetGroup(
            "TargetGroupNginx",
            VpcId=Ref(VpcId),
            HealthCheckIntervalSeconds="30",
            HealthCheckProtocol="HTTP",
            HealthCheckTimeoutSeconds="10",
            HealthyThresholdCount="4",
            Matcher=elb.Matcher(HttpCode="200"),
            Name="NginxTarget",
            Port="80",
            Protocol="HTTP",
            UnhealthyThresholdCount="3",
        ))

    # Add ALB listener
    Listener = template.add_resource(
        elb.Listener("Listener",
                     Port="80",
                     Protocol="HTTP",
                     LoadBalancerArn=Ref(ApplicationElasticLB),
                     DefaultActions=[
                         elb.Action(Type="forward",
                                    TargetGroupArn=Ref(TargetGroupNginx))
                     ]))

    # Add launch configuration for auto scaling
    LaunchConfig = template.add_resource(
        LaunchConfiguration(
            "LaunchConfiguration",
            ImageId=Ref(AmiId),
            KeyName=Ref(KeyName),
            AssociatePublicIpAddress="False",
            LaunchConfigurationName="nginx-LC",
            UserData=Base64(
                Join('', [
                    "#!/bin/bash\n", "yum update\n", "yum -y install nginx\n",
                    "chkconfig nginx on\n", "service nginx start"
                ])),
            SecurityGroups=[Ref(NginxInstanceSG)],
            InstanceType=Ref(InstanceType)))

    # Add auto scaling group
    AutoscalingGroup = template.add_resource(
        AutoScalingGroup(
            "AutoscalingGroup",
            DesiredCapacity=Ref(ScaleCapacity),
            LaunchConfigurationName=Ref(LaunchConfig),
            MinSize="1",
            TargetGroupARNs=[Ref(TargetGroupNginx)],
            MaxSize=Ref(ScaleCapacity),
            VPCZoneIdentifier=[Ref(PrivateSubnet1),
                               Ref(PrivateSubnet2)],
            AvailabilityZones=[
                Ref(VPCAvailabilityZone1),
                Ref(VPCAvailabilityZone2)
            ],
            HealthCheckType="EC2"))

    template.add_output(
        Output("URL",
               Description="URL of the sample website",
               Value=Join("",
                          ["http://",
                           GetAtt(ApplicationElasticLB, "DNSName")])))

    #print(template.to_json())

    with open('AutoScaling.yaml', 'w') as f:
        f.write(template.to_yaml())
def main():
    template = Template()
    template.add_version("2010-09-09")

    template.add_description(
        "AWS CloudFormation Sample Template: ELB with 2 EC2 instances")

    AddAMI(template)

    # Add the Parameters
    keyname_param = template.add_parameter(
        Parameter(
            "KeyName",
            Type='AWS::EC2::KeyPair::KeyName',
            Default="ansible-key",
            Description="Name of an existing EC2 KeyPair to "
            "enable SSH access to the instance",
        ))

    template.add_parameter(
        Parameter(
            "InstanceType",
            Type="String",
            Description="WebServer EC2 instance type",
            Default="t2.micro",
            AllowedValues=["t1.micro", "t2.micro"],
            ConstraintDescription="must be a valid EC2 instance type.",
        ))

    webport_param = template.add_parameter(
        Parameter(
            "WebServerPort",
            Type="String",
            Default="8888",
            Description="TCP/IP port of the web server",
        ))

    web2_param = template.add_parameter(
        Parameter(
            "ApiServerPort",
            Type="String",
            Default="8889",
            Description="TCP/IP port of the api server",
        ))

    subnetA = template.add_parameter(
        Parameter("subnetA",
                  Type="List<AWS::EC2::Subnet::Id>",
                  Description="Choose Subnets"))

    VpcId = template.add_parameter(
        Parameter("VpcId", Type="AWS::EC2::VPC::Id", Description="Choose VPC"))

    # Define the instance security group
    instance_sg = template.add_resource(
        ec2.SecurityGroup(
            "InstanceSecurityGroup",
            GroupDescription="Enable SSH and HTTP access on the inbound port",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort=Ref(webport_param),
                    ToPort=Ref(webport_param),
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort=Ref(web2_param),
                    ToPort=Ref(web2_param),
                    CidrIp="0.0.0.0/0",
                ),
            ]))

    # Add the web server instance
    WebInstance = template.add_resource(
        ec2.Instance(
            "WebInstance",
            SecurityGroups=[Ref(instance_sg)],
            KeyName=Ref(keyname_param),
            InstanceType=Ref("InstanceType"),
            ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"),
            UserData=Base64(
                Join('', [
                    '#!/bin/bash\n',
                    'sudo yum -y update\n',
                    'sudo yum install -y httpd php\n',
                    'sudo sed -i "42s/Listen 80/Listen 8888/" /etc/httpd/conf/httpd.conf\n',
                    'sudo service httpd restart \n',
                    'Ref(webport_param)',
                ]))))

    # Add the api server instance
    ApiInstance = template.add_resource(
        ec2.Instance(
            "ApiInstance",
            SecurityGroups=[Ref(instance_sg)],
            KeyName=Ref(keyname_param),
            InstanceType=Ref("InstanceType"),
            ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"),
            UserData=Base64(
                Join('', [
                    '#!/bin/bash\n',
                    'sudo yum -y update\n',
                    'sudo yum install -y httpd php\n',
                    'sudo sed -i "42s/Listen 80/Listen 8889/" /etc/httpd/conf/httpd.conf\n',
                    'sudo service httpd restart \n',
                    'Ref(web2_param)',
                ]))))

    # Add the application ELB
    ApplicationElasticLB = template.add_resource(
        elb.LoadBalancer("ApplicationElasticLB",
                         Name="ApplicationElasticLB",
                         Scheme="internet-facing",
                         Subnets=Ref("subnetA")))

    TargetGroupWeb = template.add_resource(
        elb.TargetGroup("TargetGroupWeb",
                        HealthCheckIntervalSeconds="30",
                        HealthCheckProtocol="HTTP",
                        HealthCheckTimeoutSeconds="10",
                        HealthyThresholdCount="4",
                        Matcher=elb.Matcher(HttpCode="200"),
                        Name="WebTarget",
                        Port=Ref(webport_param),
                        Protocol="HTTP",
                        Targets=[
                            elb.TargetDescription(Id=Ref(WebInstance),
                                                  Port=Ref(webport_param))
                        ],
                        UnhealthyThresholdCount="3",
                        VpcId=Ref(VpcId)))

    TargetGroupApi = template.add_resource(
        elb.TargetGroup("TargetGroupApi",
                        HealthCheckIntervalSeconds="30",
                        HealthCheckProtocol="HTTP",
                        HealthCheckTimeoutSeconds="10",
                        HealthyThresholdCount="4",
                        Matcher=elb.Matcher(HttpCode="200"),
                        Name="ApiTarget",
                        Port=Ref(web2_param),
                        Protocol="HTTP",
                        Targets=[
                            elb.TargetDescription(Id=Ref(ApiInstance),
                                                  Port=Ref(web2_param))
                        ],
                        UnhealthyThresholdCount="3",
                        VpcId=Ref(VpcId)))

    Listener = template.add_resource(
        elb.Listener("Listener",
                     Port="80",
                     Protocol="HTTP",
                     LoadBalancerArn=Ref(ApplicationElasticLB),
                     DefaultActions=[
                         elb.Action(Type="forward",
                                    TargetGroupArn=Ref(TargetGroupWeb))
                     ]))

    template.add_resource(
        elb.ListenerRule("ListenerRuleApi",
                         ListenerArn=Ref(Listener),
                         Conditions=[
                             elb.Condition(Field="path-pattern",
                                           Values=["/api/*"])
                         ],
                         Actions=[
                             elb.Action(Type="forward",
                                        TargetGroupArn=Ref(TargetGroupApi))
                         ],
                         Priority="1"))

    template.add_output(
        Output("URL",
               Description="URL of the sample website",
               Value=Join("",
                          ["http://",
                           GetAtt(ApplicationElasticLB, "DNSName")])))
    print(template.to_json())
示例#10
0
def buildStack(bootstrap, env):
    t = Template()

    t.add_description("""\
    Configures autoscaling group for hello world app""")

    vpcCidr = t.add_parameter(
        Parameter(
            "VPCCidr",
            Type="String",
            Description="VPC cidr (x.x.x.x/xx)",
        ))

    publicSubnet1 = t.add_parameter(
        Parameter(
            "PublicSubnet1",
            Type="String",
            Description="A public VPC subnet ID for the api app load balancer.",
        ))

    publicSubnet2 = t.add_parameter(
        Parameter(
            "PublicSubnet2",
            Type="String",
            Description="A public VPC subnet ID for the api load balancer.",
        ))

    dbName = t.add_parameter(
        Parameter(
            "DBName",
            Default="HelloWorldApp",
            Description="The database name",
            Type="String",
            MinLength="1",
            MaxLength="64",
            AllowedPattern="[a-zA-Z][a-zA-Z0-9]*",
            ConstraintDescription=("must begin with a letter and contain only"
                                   " alphanumeric characters.")))

    dbUser = t.add_parameter(
        Parameter(
            "DBUser",
            NoEcho=True,
            Description="The database admin account username",
            Type="String",
            MinLength="1",
            MaxLength="16",
            AllowedPattern="[a-zA-Z][a-zA-Z0-9]*",
            ConstraintDescription=("must begin with a letter and contain only"
                                   " alphanumeric characters.")))

    dbPassword = t.add_parameter(
        Parameter(
            "DBPassword",
            NoEcho=True,
            Description="The database admin account password",
            Type="String",
            MinLength="8",
            MaxLength="41",
            AllowedPattern="[a-zA-Z0-9]*",
            ConstraintDescription="must contain only alphanumeric characters.")
    )

    dbType = t.add_parameter(
        Parameter(
            "DBType",
            Default="db.t2.medium",
            Description="Database instance class",
            Type="String",
            AllowedValues=[
                "db.m5.large", "db.m5.xlarge", "db.m5.2xlarge",
                "db.m5.4xlarge", "db.m5.12xlarge", "db.m5.24xlarge",
                "db.m4.large", "db.m4.xlarge", "db.m4.2xlarge",
                "db.m4.4xlarge", "db.m4.10xlarge", "db.m4.16xlarge",
                "db.r4.large", "db.r4.xlarge", "db.r4.2xlarge",
                "db.r4.4xlarge", "db.r4.8xlarge", "db.r4.16xlarge",
                "db.x1e.xlarge", "db.x1e.2xlarge", "db.x1e.4xlarge",
                "db.x1e.8xlarge", "db.x1e.16xlarge", "db.x1e.32xlarge",
                "db.x1.16xlarge", "db.x1.32xlarge", "db.r3.large",
                "db.r3.xlarge", "db.r3.2xlarge", "db.r3.4xlarge",
                "db.r3.8xlarge", "db.t2.micro", "db.t2.small", "db.t2.medium",
                "db.t2.large", "db.t2.xlarge", "db.t2.2xlarge"
            ],
            ConstraintDescription="must select a valid database instance type.",
        ))

    dbAllocatedStorage = t.add_parameter(
        Parameter(
            "DBAllocatedStorage",
            Default="5",
            Description="The size of the database (Gb)",
            Type="Number",
            MinValue="5",
            MaxValue="1024",
            ConstraintDescription="must be between 5 and 1024Gb.",
        ))

    whitelistedCIDR = t.add_parameter(
        Parameter(
            "WhitelistedCIDR",
            Description="CIDR whitelisted to be open on public instances",
            Type="String",
        ))

    #### NETWORK SECTION ####
    vpc = t.add_resource(
        VPC("VPC", CidrBlock=Ref(vpcCidr), EnableDnsHostnames=True))

    subnet1 = t.add_resource(
        Subnet("Subnet1",
               CidrBlock=Ref(publicSubnet1),
               AvailabilityZone="eu-west-1a",
               VpcId=Ref(vpc)))
    subnet2 = t.add_resource(
        Subnet("Subnet2",
               CidrBlock=Ref(publicSubnet2),
               AvailabilityZone="eu-west-1b",
               VpcId=Ref(vpc)))

    internetGateway = t.add_resource(InternetGateway('InternetGateway'))

    gatewayAttachment = t.add_resource(
        VPCGatewayAttachment('AttachGateway',
                             VpcId=Ref(vpc),
                             InternetGatewayId=Ref(internetGateway)))

    routeTable = t.add_resource(RouteTable('RouteTable', VpcId=Ref(vpc)))

    route = t.add_resource(
        Route(
            'Route',
            DependsOn='AttachGateway',
            GatewayId=Ref('InternetGateway'),
            DestinationCidrBlock='0.0.0.0/0',
            RouteTableId=Ref(routeTable),
        ))

    subnetRouteTableAssociation = t.add_resource(
        SubnetRouteTableAssociation(
            'SubnetRouteTableAssociation',
            SubnetId=Ref(subnet1),
            RouteTableId=Ref(routeTable),
        ))

    subnetRouteTableAssociation2 = t.add_resource(
        SubnetRouteTableAssociation(
            'SubnetRouteTableAssociation2',
            SubnetId=Ref(subnet2),
            RouteTableId=Ref(routeTable),
        ))

    #### SECURITY GROUP ####
    loadBalancerSg = t.add_resource(
        ec2.SecurityGroup(
            "LoadBalancerSecurityGroup",
            VpcId=Ref(vpc),
            GroupDescription="Enable SSH access via port 22",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="80",
                    ToPort="80",
                    CidrIp="0.0.0.0/0",
                ),
            ],
        ))

    instanceSg = t.add_resource(
        ec2.SecurityGroup(
            "InstanceSecurityGroup",
            VpcId=Ref(vpc),
            GroupDescription="Enable SSH access via port 22",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp=Ref(whitelistedCIDR),
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="8000",
                    ToPort="8000",
                    SourceSecurityGroupId=Ref(loadBalancerSg),
                ),
            ],
        ))

    rdsSg = t.add_resource(
        SecurityGroup("RDSSecurityGroup",
                      GroupDescription="Security group for RDS DB Instance.",
                      VpcId=Ref(vpc),
                      SecurityGroupIngress=[
                          ec2.SecurityGroupRule(
                              IpProtocol="tcp",
                              FromPort="5432",
                              ToPort="5432",
                              SourceSecurityGroupId=Ref(instanceSg),
                          ),
                          ec2.SecurityGroupRule(
                              IpProtocol="tcp",
                              FromPort="5432",
                              ToPort="5432",
                              CidrIp=Ref(whitelistedCIDR),
                          ),
                      ]))

    #### DATABASE SECTION ####
    subnetGroup = t.add_resource(
        DBSubnetGroup(
            "SubnetGroup",
            DBSubnetGroupDescription=
            "Subnets available for the RDS DB Instance",
            SubnetIds=[Ref(subnet1), Ref(subnet2)],
        ))

    db = t.add_resource(
        DBInstance(
            "RDSHelloWorldApp",
            DBName=Join("", [Ref(dbName), env]),
            DBInstanceIdentifier=Join("", [Ref(dbName), env]),
            EnableIAMDatabaseAuthentication=True,
            PubliclyAccessible=True,
            AllocatedStorage=Ref(dbAllocatedStorage),
            DBInstanceClass=Ref(dbType),
            Engine="postgres",
            EngineVersion="10.4",
            MasterUsername=Ref(dbUser),
            MasterUserPassword=Ref(dbPassword),
            DBSubnetGroupName=Ref(subnetGroup),
            VPCSecurityGroups=[Ref(rdsSg)],
        ))

    t.add_output(
        Output("RDSConnectionString",
               Description="Connection string for database",
               Value=GetAtt("RDSHelloWorldApp", "Endpoint.Address")))

    if (bootstrap):
        return t

    #### INSTANCE SECTION ####
    keyName = t.add_parameter(
        Parameter(
            "KeyName",
            Type="String",
            Description="Name of an existing EC2 KeyPair to enable SSH access",
            MinLength="1",
            AllowedPattern="[\x20-\x7E]*",
            MaxLength="255",
            ConstraintDescription="can contain only ASCII characters.",
        ))

    scaleCapacityMin = t.add_parameter(
        Parameter(
            "ScaleCapacityMin",
            Default="1",
            Type="String",
            Description="Number of api servers to run",
        ))

    scaleCapacityMax = t.add_parameter(
        Parameter(
            "ScaleCapacityMax",
            Default="1",
            Type="String",
            Description="Number of api servers to run",
        ))

    scaleCapacityDesired = t.add_parameter(
        Parameter(
            "ScaleCapacityDesired",
            Default="1",
            Type="String",
            Description="Number of api servers to run",
        ))

    amiId = t.add_parameter(
        Parameter(
            "AmiId",
            Type="String",
            Default="ami-09693313102a30b2c",
            Description="The AMI id for the api instances",
        ))

    instanceType = t.add_parameter(
        Parameter("InstanceType",
                  Description="WebServer EC2 instance type",
                  Type="String",
                  Default="t2.medium",
                  AllowedValues=[
                      "t2.nano", "t2.micro", "t2.small", "t2.medium",
                      "t2.large", "m3.medium", "m3.large", "m3.xlarge",
                      "m3.2xlarge", "m4.large", "m4.xlarge", "m4.2xlarge",
                      "m4.4xlarge", "m4.10xlarge", "c4.large", "c4.xlarge",
                      "c4.2xlarge", "c4.4xlarge", "c4.8xlarge"
                  ],
                  ConstraintDescription="must be a valid EC2 instance type."))

    assumeRole = t.add_resource(
        Role("AssumeRole",
             AssumeRolePolicyDocument=json.loads("""\
{
  "Version": "2012-10-17",
  "Statement": [
    {
    "Action": "sts:AssumeRole",
    "Principal": {
      "Service": "ec2.amazonaws.com"
    },
    "Effect": "Allow",
    "Sid": ""
    }
  ]
}\
""")))

    instanceProfile = t.add_resource(
        InstanceProfile("InstanceProfile", Roles=[Ref(assumeRole)]))

    rolePolicyType = t.add_resource(
        PolicyType("RolePolicyType",
                   Roles=[Ref(assumeRole)],
                   PolicyName=Join("", ["CloudWatchHelloWorld", "-", env]),
                   PolicyDocument=json.loads("""\
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:DescribeLogStreams",
        "logs:PutLogEvents"
      ],
    "Effect": "Allow",
    "Resource": [
        "arn:aws:logs:*:*:*"
      ]
    }
  ]
}\
""")))

    appPassword = t.add_parameter(
        Parameter(
            "AppPassword",
            NoEcho=True,
            Description="The Password for the app user",
            Type="String",
            MinLength="8",
            MaxLength="41",
            AllowedPattern="[a-zA-Z0-9]*",
            ConstraintDescription="must contain only alphanumeric characters.")
    )

    launchConfig = t.add_resource(
        LaunchConfiguration(
            "LaunchConfiguration",
            Metadata=autoscaling.Metadata(
                cloudformation.Init({
                    "config":
                    cloudformation.InitConfig(files=cloudformation.InitFiles({
                        "/home/app/environment":
                        cloudformation.InitFile(content=Join(
                            "", [
                                "SPRING_DATASOURCE_URL=", "jdbc:postgresql://",
                                GetAtt("RDSHelloWorldApp", "Endpoint.Address"),
                                ":5432/HelloWorldApp" + env +
                                "?currentSchema=hello_world", "\n",
                                "SPRING_DATASOURCE_USERNAME=app", "\n",
                                "SPRING_DATASOURCE_PASSWORD="******"\n",
                                "SPRING_PROFILES_ACTIVE=", env, "\n"
                            ]),
                                                mode="000600",
                                                owner="app",
                                                group="app")
                    }), )
                }), ),
            UserData=Base64(
                Join('', [
                    "#!/bin/bash\n", "/opt/aws/bin/cfn-init",
                    "    --resource LaunchConfiguration", "    --stack ",
                    Ref("AWS::StackName"), "    --region ",
                    Ref("AWS::Region"), "\n", "/opt/aws/bin/cfn-signal -e $? ",
                    "         --stack ", {
                        "Ref": "AWS::StackName"
                    }, "         --resource AutoscalingGroup ",
                    "         --region ", {
                        "Ref": "AWS::Region"
                    }, "\n"
                ])),
            ImageId=Ref(amiId),
            KeyName=Ref(keyName),
            IamInstanceProfile=Ref(instanceProfile),
            BlockDeviceMappings=[
                ec2.BlockDeviceMapping(DeviceName="/dev/xvda",
                                       Ebs=ec2.EBSBlockDevice(VolumeSize="8")),
            ],
            SecurityGroups=[Ref(instanceSg)],
            InstanceType=Ref(instanceType),
            AssociatePublicIpAddress='True',
        ))

    applicationElasticLB = t.add_resource(
        elb.LoadBalancer("ApplicationElasticLB",
                         Name="ApplicationElasticLB-" + env,
                         Scheme="internet-facing",
                         Type="application",
                         SecurityGroups=[Ref(loadBalancerSg)],
                         Subnets=[Ref(subnet1), Ref(subnet2)]))

    targetGroup = t.add_resource(
        elb.TargetGroup("TargetGroupHelloWorld",
                        HealthCheckProtocol="HTTP",
                        HealthCheckTimeoutSeconds="15",
                        HealthyThresholdCount="5",
                        Matcher=elb.Matcher(HttpCode="200,404"),
                        Port="8000",
                        Protocol="HTTP",
                        UnhealthyThresholdCount="3",
                        TargetGroupAttributes=[
                            elb.TargetGroupAttribute(
                                Key="deregistration_delay.timeout_seconds",
                                Value="120",
                            )
                        ],
                        VpcId=Ref(vpc)))

    listener = t.add_resource(
        elb.Listener("Listener",
                     Port="80",
                     Protocol="HTTP",
                     LoadBalancerArn=Ref(applicationElasticLB),
                     DefaultActions=[
                         elb.Action(Type="forward",
                                    TargetGroupArn=Ref(targetGroup))
                     ]))

    t.add_output(
        Output("URL",
               Description="URL of the sample website",
               Value=Join("",
                          ["http://",
                           GetAtt(applicationElasticLB, "DNSName")])))

    autoScalingGroup = t.add_resource(
        AutoScalingGroup(
            "AutoscalingGroup",
            DesiredCapacity=Ref(scaleCapacityDesired),
            LaunchConfigurationName=Ref(launchConfig),
            MinSize=Ref(scaleCapacityMin),
            MaxSize=Ref(scaleCapacityMax),
            VPCZoneIdentifier=[Ref(subnet1), Ref(subnet2)],
            TargetGroupARNs=[Ref(targetGroup)],
            HealthCheckType="ELB",
            HealthCheckGracePeriod=360,
            UpdatePolicy=UpdatePolicy(
                AutoScalingReplacingUpdate=AutoScalingReplacingUpdate(
                    WillReplace=True, ),
                AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                    PauseTime='PT5M',
                    MinInstancesInService="1",
                    MaxBatchSize='1',
                    WaitOnResourceSignals=True)),
            CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal(
                Timeout="PT15M", Count=Ref(scaleCapacityDesired)))))

    # print(t.to_json())
    return t
def main():
    # Meta
    t.add_version("2010-09-09")
    t.add_description("Template for auto-scaling in an Application"
                      "load balancer target group. "
                      "The ALB will be used as an A Alias target "
                      "for a specified Route53 hosted zone. "
                      "This template also showcases "
                      "Metadata Parameter Grouping, "
                      "Special AWS Parameter Types, "
                      "and Cloudformation Outputs with Exports"
                      "which can be imported into other templates.")
    t.add_metadata({
        "Author": "https://github.com/hmain/",
        "LastUpdated": "2017 01 31",
        "Version": "1",
    })

    # Parameter grouping
    t.add_metadata({
        "AWS::CloudFormation::Interface": {
            "ParameterGroups": [{
                "Label": {
                    "default": "Global parameters"
                },
                "Parameters": ["environment"]
            }, {
                "Label": {
                    "default": "Application Loadbalancer"
                },
                "Parameters": [
                    "albSubnets", "loadbalancerPrefix", "loadBalancerArn",
                    "albPaths", "albPort"
                ]
            }, {
                "Label": {
                    "default": "VPC"
                },
                "Parameters": ["ec2Subnets", "VPC", "securityGroup"]
            }, {
                "Label": {
                    "default": "EC2"
                },
                "Parameters": ["ec2Name", "ec2Type", "ec2Key"]
            }, {
                "Label": {
                    "default": "Auto-scaling"
                },
                "Parameters": [
                    "asgCapacity", "asgMinSize", "asgMaxSize", "asgCooldown",
                    "asgHealthGrace"
                ]
            }, {
                "Label": {
                    "default": "Route53"
                },
                "Parameters": ["route53HostedZoneId", "route53HostedZoneName"]
            }]
        }
    })

    AddAMI(t)

    environment = t.add_parameter(
        Parameter(
            "environment",
            Default="dev",
            Type="String",
            Description="Development or Production environment",
            AllowedValues=["dev", "prod"],
            ConstraintDescription="dev or prod",
        ))
    route53_hosted_zone_id = t.add_parameter(
        Parameter("route53HostedZoneId",
                  Default="",
                  Type="AWS::Route53::HostedZone::Id",
                  Description="Route53 DNS zone ID"))

    route53_hosted_zone_name = t.add_parameter(
        Parameter("route53HostedZoneName",
                  Default="my.aws.dns.com",
                  Type="String",
                  Description="Route53 hosted zone name"))
    security_group = t.add_parameter(
        Parameter("securityGroup",
                  Default="",
                  Type="List<AWS::EC2::SecurityGroup::Id>",
                  Description="Which security groups to use"))
    alb_paths = t.add_parameter(
        Parameter(
            "albPaths",
            Default="/",
            Type="CommaDelimitedList",
            Description="Path-patterns you want the loadbalancer to point to in "
            "your application"))
    albPort = t.add_parameter(
        Parameter("albPort",
                  Default="80",
                  Type="Number",
                  Description="Which loadbalancer port to use"))
    ec2_subnets = t.add_parameter(
        Parameter("ec2Subnets",
                  Default="",
                  Type="List<AWS::EC2::Subnet::Id>",
                  Description="Private subnets for the instances."))
    alb_subnets = t.add_parameter(
        Parameter("albSubnets",
                  Default="",
                  Type="List<AWS::EC2::Subnet::Id>",
                  Description="Public subnets for the load balancer."))
    loadbalancer_prefix = t.add_parameter(
        Parameter(
            "loadbalancerPrefix",
            Default="",
            Type="String",
            Description="Specify a prefix for your loadbalancer",
        ))
    vpc = t.add_parameter(
        Parameter("VPC",
                  Default="",
                  Type="AWS::EC2::VPC::Id",
                  Description="Environment VPC"))

    # Auto scaling group parameters
    asg_capacity = t.add_parameter(
        Parameter("asgCapacity",
                  Default="0",
                  Type="Number",
                  Description="Number of instances"))
    asg_min_size = t.add_parameter(
        Parameter("asgMinSize",
                  Default="0",
                  Type="Number",
                  Description="Minimum size of AutoScalingGroup"))
    asg_max_size = t.add_parameter(
        Parameter("asgMaxSize",
                  Default="1",
                  Type="Number",
                  Description="Maximum size of AutoScalingGroup"))
    asg_cooldown = t.add_parameter(
        Parameter(
            "asgCooldown",
            Default="300",
            Type="Number",
            Description="Cooldown before starting/stopping another instance"))
    asg_health_grace = t.add_parameter(
        Parameter(
            "asgHealthGrace",
            Default="300",
            Type="Number",
            Description="Wait before starting/stopping another instance"))

    # EC2 parameters
    ec2_name = t.add_parameter(
        Parameter("ec2Name",
                  Default="myApplication",
                  Type="String",
                  Description="Name of the instances"))
    ec2_type = t.add_parameter(
        Parameter("ec2Type",
                  Default="t2.large",
                  Type="String",
                  Description="Instance type."))
    ec2_key = t.add_parameter(
        Parameter("ec2Key",
                  Default="",
                  Type="AWS::EC2::KeyPair::KeyName",
                  Description="EC2 Key Pair"))

    # Launchconfiguration
    ec2_launchconfiguration = t.add_resource(
        autoscaling.LaunchConfiguration(
            "EC2LaunchConfiguration",
            ImageId=FindInMap("windowsAMI", Ref("AWS::Region"), "AMI"),
            KeyName=Ref(ec2_key),
            SecurityGroups=Ref(security_group),
            InstanceType=Ref(ec2_type),
            AssociatePublicIpAddress=False,
        ))

    # Application ELB
    alb_target_group = t.add_resource(
        elb.TargetGroup("albTargetGroup",
                        HealthCheckPath=Select("0", Ref(alb_paths)),
                        HealthCheckIntervalSeconds="30",
                        HealthCheckProtocol="HTTP",
                        HealthCheckTimeoutSeconds="10",
                        HealthyThresholdCount="4",
                        Matcher=elb.Matcher(HttpCode="200"),
                        Name=Ref(ec2_name),
                        Port=80,
                        Protocol="HTTP",
                        UnhealthyThresholdCount="3",
                        VpcId=Ref(vpc)))

    # Auto scaling group
    t.add_resource(
        autoscaling.AutoScalingGroup(
            "autoScalingGroup",
            DesiredCapacity=Ref(asg_capacity),
            Tags=autoscaling.Tags(Environment=Ref(environment)),
            VPCZoneIdentifier=Ref(ec2_subnets),
            TargetGroupARNs=[Ref(alb_target_group)],
            MinSize=Ref(asg_min_size),
            MaxSize=Ref(asg_max_size),
            Cooldown=Ref(asg_cooldown),
            LaunchConfigurationName=Ref(ec2_launchconfiguration),
            HealthCheckGracePeriod=Ref(asg_health_grace),
            HealthCheckType="EC2",
        ))

    # Application Load Balancer
    application_load_balancer = t.add_resource(
        elb.LoadBalancer("applicationLoadBalancer",
                         Name=Ref(loadbalancer_prefix),
                         Scheme="internet-facing",
                         Subnets=Ref(alb_subnets),
                         SecurityGroups=Ref(security_group)))
    alb_listener = t.add_resource(
        elb.Listener("albListener",
                     Port=Ref(albPort),
                     Protocol="HTTP",
                     LoadBalancerArn=Ref(application_load_balancer),
                     DefaultActions=[
                         elb.Action(Type="forward",
                                    TargetGroupArn=Ref(alb_target_group))
                     ]))
    t.add_resource(
        elb.ListenerRule("albListenerRule",
                         ListenerArn=Ref(alb_listener),
                         Conditions=[
                             elb.Condition(Field="path-pattern",
                                           Values=Ref(alb_paths))
                         ],
                         Actions=[
                             elb.Action(Type="forward",
                                        TargetGroupArn=Ref(alb_target_group))
                         ],
                         Priority="1"))

    # Route53
    t.add_resource(
        route53.RecordSetGroup(
            "route53RoundRobin",
            HostedZoneId=Ref(route53_hosted_zone_id),
            RecordSets=[
                route53.RecordSet(
                    Weight=1,
                    SetIdentifier=Join(".", [
                        Ref(environment),
                        Ref(route53_hosted_zone_name), "ELB"
                    ]),
                    Name=Join(
                        ".", [Ref(environment),
                              Ref(route53_hosted_zone_name)]),
                    Type="A",
                    AliasTarget=route53.AliasTarget(
                        GetAtt(application_load_balancer,
                               "CanonicalHostedZoneID"),
                        GetAtt(application_load_balancer, "DNSName")))
            ]))

    t.add_output(
        Output(
            "URL",
            Description="URL of the website",
            Value=Join("", [
                "http://",
                GetAtt(application_load_balancer, "DNSName"),
                Select("0", Ref(alb_paths))
            ]),
            Export=Export(Sub("${AWS::StackName}-URL")),
        ))

    print(t.to_json())
# Create the ALB
ALB = t.add_resource(elasticloadbalancingv2.LoadBalancer(
    "ALB",
    Scheme="internet-facing",
    Subnets=[Ref(PubSubnetAz1), Ref(PubSubnetAz2)],
    SecurityGroups=[Ref(ALBSecurityGroup)]
))

# Create the ALB"s Target Group
ALBTargetGroup = t.add_resource(elasticloadbalancingv2.TargetGroup(
    "ALBTargetGroup",
    HealthCheckIntervalSeconds="30",
    HealthCheckProtocol="HTTP",
    HealthCheckTimeoutSeconds="10",
    HealthyThresholdCount="4",
    Matcher=elasticloadbalancingv2.Matcher(
        HttpCode="200"),
    Port=80,
    Protocol="HTTP",
    UnhealthyThresholdCount="3",
    TargetType="ip",
    VpcId=Ref(VPC)
))

ALBListener = t.add_resource(elasticloadbalancingv2.Listener(
    "ALBListener",
    Port="80",
    Protocol="HTTP",
    LoadBalancerArn=Ref(ALB),
    DefaultActions=[elasticloadbalancingv2.Action(
        Type="forward",
        TargetGroupArn=Ref(ALBTargetGroup)
示例#13
0
def generate_template(d):

    # Set template metadata
    t = Template()
    t.add_version("2010-09-09")
    t.set_description(d["cf_template_description"])

    aws_account_id = Ref("AWS::AccountId")
    aws_region = Ref("AWS::Region")

    # Task definition
    task_definition = t.add_resource(
        TaskDefinition(
            "TaskDefinition",
            Family=Join(
                "",
                [d["env"], "-", d["project_name"], "-", d["service_name"]]),
            RequiresCompatibilities=["FARGATE"],
            Cpu=d["container_cpu"],
            Memory=d["container_memory"],
            NetworkMode="awsvpc",
            ExecutionRoleArn=ImportValue(d["ecs_stack_name"] +
                                         "-ECSClusterRole"),
            ContainerDefinitions=[
                ContainerDefinition(
                    Name=Join("", [
                        d["env"], "-", d["project_name"], "-",
                        d["service_name"]
                    ]),
                    Image=Join(
                        "",
                        [
                            aws_account_id, ".dkr.ecr.", aws_region,
                            ".amazonaws.com/", d["env"], d["project_name"],
                            d["service_name"], ":latest"
                        ],
                    ),
                    Essential=True,
                    PortMappings=[
                        PortMapping(
                            ContainerPort=d["container_port"],
                            HostPort=d["container_port"],
                        )
                    ],
                    EntryPoint=["sh", "-c"],
                    Command=[d["container_command"]],
                    LogConfiguration=LogConfiguration(
                        LogDriver="awslogs",
                        Options={
                            "awslogs-region":
                            aws_region,
                            "awslogs-group":
                            Join("", [
                                d["env"], "-", d["project_name"], "-",
                                d["service_name"]
                            ]),
                            "awslogs-stream-prefix":
                            "ecs",
                            "awslogs-create-group":
                            "true"
                        }))
            ],
            Tags=Tags(d["tags"],
                      {"Name": d["project_name"] + "-task-definition"}),
        ))

    # ECR
    ecr = t.add_resource(
        Repository(
            "ECR",
            DependsOn="ListenerRule",
            RepositoryName=Join(
                "",
                [d["env"], "-", d["project_name"], "-", d["service_name"]]),
            Tags=Tags(d["tags"], {"Name": d["project_name"] + "-ecr"}),
        ))
    # Target group
    target_group = t.add_resource(
        elb.TargetGroup(
            "TargetGroup",
            Name=Join("", [d["env"], "-", d["service_name"]]),
            HealthCheckIntervalSeconds="30",
            HealthCheckProtocol="HTTP",
            HealthCheckPort=d["container_port"],
            HealthCheckTimeoutSeconds="10",
            HealthyThresholdCount="4",
            HealthCheckPath=d["tg_health_check_path"],
            Matcher=elb.Matcher(HttpCode="200-299"),
            Port=d["container_port"],
            Protocol="HTTP",
            TargetType="ip",
            UnhealthyThresholdCount="3",
            VpcId=ImportValue(d["network_stack_name"] + "-VPCId"),
            Tags=Tags(d["tags"], {"Name": d["project_name"] + "-ecr"}),
        ))
    # Listener rule
    t.add_resource(
        elb.ListenerRule(
            "ListenerRule",
            DependsOn="TargetGroup",
            ListenerArn=ImportValue(d["ecs_stack_name"] + "-ListenerArnHTTP"),
            Conditions=[
                elb.Condition(Field="path-pattern",
                              Values=[d["application_path_api"]])
            ],
            Actions=[
                elb.Action(Type="forward", TargetGroupArn=Ref(target_group))
            ],
            Priority="1",
        ))
    # ECS service
    ecs_service = t.add_resource(
        Service(
            "ECSService",
            ServiceName=Join(
                "",
                [d["env"], "-", d["project_name"], "-", d["service_name"]]),
            DependsOn="pipeline",
            DesiredCount=d["container_desired_tasks_count"],
            TaskDefinition=Ref(task_definition),
            LaunchType="FARGATE",
            NetworkConfiguration=NetworkConfiguration(
                AwsvpcConfiguration=AwsvpcConfiguration(
                    Subnets=[
                        ImportValue(d["network_stack_name"] +
                                    "-PrivateSubnetId1"),
                        ImportValue(d["network_stack_name"] +
                                    "-PrivateSubnetId2"),
                    ],
                    SecurityGroups=[
                        ImportValue(d["ecs_stack_name"] + "-ECSClusterSG")
                    ],
                )),
            LoadBalancers=([
                LoadBalancer(
                    ContainerName=Join(
                        "",
                        [
                            d["env"], "-", d["project_name"], "-",
                            d["service_name"]
                        ],
                    ),
                    ContainerPort=d["container_port"],
                    TargetGroupArn=Ref(target_group),
                )
            ]),
            Cluster=ImportValue(d["ecs_stack_name"] + "-ECSClusterName"),
            Tags=Tags(d["tags"], {"Name": d["project_name"] + "-ecs-service"}),
        ))
    # App Autoscaling target

    # App Autoscaling policy

    # Codebuild project
    codebuild = t.add_resource(
        Project(
            "codebuild",
            Name=Join(
                "",
                [d["env"], "-", d["project_name"], "-", d["service_name"]]),
            DependsOn="ECR",
            ServiceRole=ImportValue(d["ecs_stack_name"] +
                                    "-CodebuildDeveloperRole"),
            Artifacts=Artifacts(
                Name="Build",
                Location=d["artifact_store"],
                Type="S3",
            ),
            Description="Build a docker image and send it to ecr",
            Source=Source(
                BuildSpec="buildspec.yml",
                Type="S3",
                Location=d["artifact_store"] + "/" + d["artifact_name"],
            ),
            Environment=Environment(
                ComputeType="BUILD_GENERAL1_SMALL",
                Image="aws/codebuild/standard:4.0",
                PrivilegedMode=True,
                Type="LINUX_CONTAINER",
                EnvironmentVariables=[
                    EnvironmentVariable(
                        Name="AWS_DEFAULT_REGION",
                        Type="PLAINTEXT",
                        Value=aws_region,
                    ),
                    EnvironmentVariable(
                        Name="SERVICE_NAME",
                        Type="PLAINTEXT",
                        Value=Join(
                            "",
                            [
                                d["env"], "-", d["project_name"], "-",
                                d["service_name"]
                            ],
                        ),
                    ),
                    EnvironmentVariable(
                        Name="IMAGE_URI",
                        Type="PLAINTEXT",
                        Value=Join(
                            "",
                            [
                                aws_account_id,
                                ".dkr.ecr.",
                                aws_region,
                                ".amazonaws.com/",
                                d["env"],
                                "-",
                                d["project_name"],
                                "-",
                                d["service_name"],
                            ],
                        ),
                    ),
                ],
            ),
            Tags=Tags(d["tags"], {"Name": d["project_name"] + "-codebuild"}),
        ))

    # Codepipeline
    pipeline = t.add_resource(
        Pipeline(
            "pipeline",
            Name=Join(
                "",
                [d["env"], "-", d["project_name"], "-", d["service_name"]]),
            RoleArn=ImportValue(d["ecs_stack_name"] + "-CodePipelineRole"),
            Stages=[
                Stages(
                    Name="Source",
                    Actions=[
                        Actions(
                            Name="Source",
                            ActionTypeId=ActionTypeId(
                                Category="Source",
                                Owner="AWS",
                                Version="1",
                                Provider="S3",
                            ),
                            OutputArtifacts=[
                                OutputArtifacts(Name="source_artifact")
                            ],
                            Configuration={
                                "S3Bucket": d["artifact_store"],
                                "S3ObjectKey": d["artifact_name"],
                            },
                            RunOrder="1",
                        )
                    ],
                ),
                Stages(
                    Name="Build",
                    Actions=[
                        Actions(
                            Name="Build",
                            InputArtifacts=[
                                InputArtifacts(Name="source_artifact")
                            ],
                            OutputArtifacts=[
                                OutputArtifacts(Name="build_artifact")
                            ],
                            ActionTypeId=ActionTypeId(
                                Category="Build",
                                Owner="AWS",
                                Version="1",
                                Provider="CodeBuild",
                            ),
                            Configuration={"ProjectName": Ref(codebuild)},
                            RunOrder="1",
                        )
                    ],
                ),
                Stages(
                    Name="Deploy",
                    Actions=[
                        Actions(
                            Name="Deploy",
                            InputArtifacts=[
                                InputArtifacts(Name="build_artifact")
                            ],
                            ActionTypeId=ActionTypeId(
                                Category="Deploy",
                                Owner="AWS",
                                Version="1",
                                Provider="ECS",
                            ),
                            Configuration={
                                "ClusterName":
                                ImportValue(d["ecs_stack_name"] +
                                            "-ECSClusterName"),
                                "ServiceName":
                                Join(
                                    "",
                                    [
                                        d["env"],
                                        "-",
                                        d["project_name"],
                                        "-",
                                        d["service_name"],
                                    ],
                                ),
                                "FileName":
                                "definitions.json",
                            },
                        )
                    ],
                ),
            ],
            ArtifactStore=ArtifactStore(Type="S3",
                                        Location=d["artifact_store"]),
        ))
    # Route53

    # Outputs

    return t
                      Protocol='HTTP',
                      Port='80',
                      Targets=[
                          elbv2.TargetDescription(
                              Id=Ref(param_instance_id),
                              Port='80',
                          )
                      ],
                      HealthCheckIntervalSeconds='15',
                      HealthCheckPath='/',
                      HealthCheckPort='80',
                      HealthCheckProtocol='HTTP',
                      HealthCheckTimeoutSeconds='5',
                      HealthyThresholdCount='3',
                      UnhealthyThresholdCount='5',
                      Matcher=elbv2.Matcher(HttpCode='200'),
                      TargetGroupAttributes=[
                          elbv2.TargetGroupAttribute(
                              Key='deregistration_delay.timeout_seconds',
                              Value='20')
                      ]))

http_listener = t.add_resource(
    elbv2.Listener(
        'HttpListener',
        DefaultActions=[
            elbv2.Action(TargetGroupArn=Ref(targetgroup), Type='forward')
        ],
        LoadBalancerArn=Ref(load_balancer),
        Port='80',
        Protocol='HTTP',
示例#15
0
    def elbv2_target_group(self,
                           name,
                           protocol,
                           port,
                           vpc_id,
                           health_check_details={},
                           matcher=None,
                           target_group_attributes=False,
                           targets=[]):
        """
        Create ELBv2 Target Group

        :param name: Name of the target group
        :param protocol: Protocol
        :param port: Port
        :param vpc_id: VPC id
        :param health_check_details: Array of health check detail
        :param matcher: HTTP code to use when checking for health check response
        :param target_group_attributes: Additional target group attributes
        :param targets: Targets, if applicable
        :return: Target Group CFN object
        """

        target_group = elbv2.TargetGroup(
            name,
            Protocol=protocol,
            Port=port,
            VpcId=vpc_id,
            HealthCheckProtocol=health_check_details["health_check_protocol"],
            HealthCheckPort=health_check_details["health_check_port"],
            HealthCheckIntervalSeconds=health_check_details[
                "health_check_interval"],
            HealthyThresholdCount=health_check_details["healthy_threshold"],
            UnhealthyThresholdCount=health_check_details[
                "unhealthy_threshold"],
            Targets=targets)

        if health_check_details.get("health_check_path"):
            target_group.HealthCheckPath = health_check_details[
                "health_check_path"]

        if health_check_details.get("health_check_timeout"):
            target_group.HealthCheckTimeoutSeconds = health_check_details[
                "health_check_timeout"]

        if matcher:
            target_group.Matcher = elbv2.Matcher(HttpCode=matcher)

        if target_group_attributes:
            attributes = []
            for attr in target_group_attributes:
                attributes.append(
                    elbv2.TargetGroupAttribute(Key=attr['key'],
                                               Value=attr['value']))
            target_group.TargetGroupAttributes = attributes

        self.template.add_resource(target_group)
        self.template.add_output(
            Output(name,
                   Value=Ref(name),
                   Description="Target Group {} ARN".format(name),
                   Export=Export(Sub("${AWS::StackName}-" + name))))

        return target_group
def define_load_balancer(template, sg):
    alb_target_group_80 = elb.TargetGroup(
        stack_name_strict + "TG80",
        Tags=Tags(Name=stack_name, Custo=app_name),
        HealthCheckPath=Ref(alb_health_check_path),
        HealthCheckIntervalSeconds="30",
        HealthCheckProtocol="HTTP",
        HealthCheckTimeoutSeconds="10",
        HealthyThresholdCount="3",
        Matcher=elb.Matcher(HttpCode="301"),
        Port=80,
        Protocol="HTTP",
        UnhealthyThresholdCount="2",
        VpcId=Ref(vpc_id))
    template.add_resource(alb_target_group_80)

    alb_target_group_9090 = elb.TargetGroup(
        stack_name_strict + "TG9090",
        Tags=Tags(Name=stack_name, Custo=app_name),
        HealthCheckPath=Ref(alb_health_check_path),
        HealthCheckIntervalSeconds="30",
        HealthCheckProtocol="HTTP",
        HealthCheckTimeoutSeconds="10",
        HealthyThresholdCount="3",
        Matcher=elb.Matcher(HttpCode="200"),
        Port=9090,
        Protocol="HTTP",
        UnhealthyThresholdCount="2",
        VpcId=Ref(vpc_id))
    template.add_resource(alb_target_group_9090)

    alb = elb.LoadBalancer(stack_name_strict + "ALB",
                           Tags=Tags(Name=stack_name, Custo=app_name),
                           Scheme="internet-facing",
                           Subnets=[Ref(subnet_id1),
                                    Ref(subnet_id2)],
                           SecurityGroups=[Ref(sg)])
    template.add_resource(alb)

    alb_listener_80 = elb.Listener(
        stack_name_strict + "ListenerALB80",
        Port=80,
        Protocol="HTTP",
        LoadBalancerArn=Ref(alb),
        DefaultActions=[
            elb.Action(Type="forward", TargetGroupArn=Ref(alb_target_group_80))
        ])
    template.add_resource(alb_listener_80)

    alb_listener_443 = elb.Listener(
        stack_name_strict + "ListenerALB443",
        Port=443,
        Protocol="HTTPS",
        Certificates=[
            elb.Certificate(CertificateArn=Ref(ssl_certificate_arn))
        ],
        LoadBalancerArn=Ref(alb),
        DefaultActions=[
            elb.Action(Type="forward",
                       TargetGroupArn=Ref(alb_target_group_9090))
        ])
    template.add_resource(alb_listener_443)

    return {
        "loadbalancer": alb,
        "alb_target_group_80": alb_target_group_80,
        "alb_target_group_9090": alb_target_group_9090,
        "alb_listener_80": alb_listener_80,
        "alb_listener_9090": alb_listener_443
    }
示例#17
0
def main():
    template = Template()
    template.add_version("2010-09-09")

    template.add_description(
        "AWS CloudFormation Sample Template: ELB with 2 EC2 instances")

    AddAMI(template)

    # Add the Parameters
    keyname_param = template.add_parameter(Parameter(
        "KeyName",
        Type="String",
        Default="mark",
        Description="Name of an existing EC2 KeyPair to "
                    "enable SSH access to the instance",
    ))

    template.add_parameter(Parameter(
        "InstanceType",
        Type="String",
        Description="WebServer EC2 instance type",
        Default="m1.small",
        AllowedValues=[
            "t1.micro", "m1.small", "m1.medium", "m1.large", "m1.xlarge",
            "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "c1.medium", "c1.xlarge",
            "cc1.4xlarge", "cc2.8xlarge", "cg1.4xlarge"
        ],
        ConstraintDescription="must be a valid EC2 instance type.",
    ))

    webport_param = template.add_parameter(Parameter(
        "WebServerPort",
        Type="String",
        Default="8888",
        Description="TCP/IP port of the web server",
    ))

    apiport_param = template.add_parameter(Parameter(
        "ApiServerPort",
        Type="String",
        Default="8889",
        Description="TCP/IP port of the api server",
    ))

    subnetA = template.add_parameter(Parameter(
        "subnetA",
        Type="String",
        Default="subnet-096fd06d"
    ))

    subnetB = template.add_parameter(Parameter(
        "subnetB",
        Type="String",
        Default="subnet-1313ef4b"
    ))

    VpcId = template.add_parameter(Parameter(
        "VpcId",
        Type="String",
        Default="vpc-82c514e6"
    ))

    # Define the instance security group
    instance_sg = template.add_resource(
        ec2.SecurityGroup(
            "InstanceSecurityGroup",
            GroupDescription="Enable SSH and HTTP access on the inbound port",
            SecurityGroupIngress=[
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort="22",
                    ToPort="22",
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort=Ref(webport_param),
                    ToPort=Ref(webport_param),
                    CidrIp="0.0.0.0/0",
                ),
                ec2.SecurityGroupRule(
                    IpProtocol="tcp",
                    FromPort=Ref(apiport_param),
                    ToPort=Ref(apiport_param),
                    CidrIp="0.0.0.0/0",
                ),
            ]
        )
    )

    # Add the web server instance
    WebInstance = template.add_resource(ec2.Instance(
        "WebInstance",
        SecurityGroups=[Ref(instance_sg)],
        KeyName=Ref(keyname_param),
        InstanceType=Ref("InstanceType"),
        ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"),
        UserData=Base64(Ref(webport_param)),
    ))

    # Add the api server instance
    ApiInstance = template.add_resource(ec2.Instance(
        "ApiInstance",
        SecurityGroups=[Ref(instance_sg)],
        KeyName=Ref(keyname_param),
        InstanceType=Ref("InstanceType"),
        ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"),
        UserData=Base64(Ref(apiport_param)),
    ))

    # Add the application ELB
    ApplicationElasticLB = template.add_resource(elb.LoadBalancer(
        "ApplicationElasticLB",
        Name="ApplicationElasticLB",
        Scheme="internet-facing",
        Subnets=[Ref(subnetA), Ref(subnetB)]
    ))

    TargetGroupWeb = template.add_resource(elb.TargetGroup(
        "TargetGroupWeb",
        HealthCheckIntervalSeconds="30",
        HealthCheckProtocol="HTTP",
        HealthCheckTimeoutSeconds="10",
        HealthyThresholdCount="4",
        Matcher=elb.Matcher(
            HttpCode="200"),
        Name="WebTarget",
        Port=Ref(webport_param),
        Protocol="HTTP",
        Targets=[elb.TargetDescription(
            Id=Ref(WebInstance),
            Port=Ref(webport_param))],
        UnhealthyThresholdCount="3",
        VpcId=Ref(VpcId)

    ))

    TargetGroupApi = template.add_resource(elb.TargetGroup(
        "TargetGroupApi",
        HealthCheckIntervalSeconds="30",
        HealthCheckProtocol="HTTP",
        HealthCheckTimeoutSeconds="10",
        HealthyThresholdCount="4",
        Matcher=elb.Matcher(
            HttpCode="200"),
        Name="ApiTarget",
        Port=Ref(apiport_param),
        Protocol="HTTP",
        Targets=[elb.TargetDescription(
            Id=Ref(ApiInstance),
            Port=Ref(apiport_param))],
        UnhealthyThresholdCount="3",
        VpcId=Ref(VpcId)

    ))

    Listener = template.add_resource(elb.Listener(
        "Listener",
        Port="80",
        Protocol="HTTP",
        LoadBalancerArn=Ref(ApplicationElasticLB),
        DefaultActions=[elb.Action(
            Type="forward",
            TargetGroupArn=Ref(TargetGroupWeb)
        )]
    ))

    template.add_resource(elb.ListenerRule(
        "ListenerRuleApi",
        ListenerArn=Ref(Listener),
        Conditions=[elb.Condition(
            Field="path-pattern",
            Values=["/api/*"])],
        Actions=[elb.Action(
            Type="forward",
            TargetGroupArn=Ref(TargetGroupApi)
        )],
        Priority="1"
    ))

    template.add_output(Output(
        "URL",
        Description="URL of the sample website",
        Value=Join("", ["http://", GetAtt(ApplicationElasticLB, "DNSName")])
    ))

    print(template.to_json())
示例#18
0
    def generate_app_load_balancer(self, lb_name, typ, port, cert_arn, log_bucket):

        lb_name = self.cfn_name(lb_name)

        if len(lb_name) >= 32:
            alb_name = lb_name[0:31]
        else:
            alb_name = lb_name

        if len(lb_name + 'TG') >= 32:
            tg_name = '{}TG'.format(lb_name[0:29])
        else:
            tg_name = '{}TG'.format(lb_name)

        if typ not in ['internal', 'internet-facing']:
            raise NameError("Load balancer type must be of type internal, internet-facing")

        # Use the system security groups (automatic) if internal, else use the limited external security group
        sg = self.security_groups if typ == 'internal' else [Ref(self.elb_external_security_group)]

        _alb = elasticloadbalancingv2.LoadBalancer(
            alb_name,
            Name=alb_name,
            IpAddressType='ipv4',
            LoadBalancerAttributes=[
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='access_logs.s3.enabled',
                    Value='true'
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='access_logs.s3.bucket',
                    Value=log_bucket
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='access_logs.s3.prefix',
                    Value="ELB/{}/{}".format(self.env, lb_name)
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='deletion_protection.enabled',
                    Value='false'
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='idle_timeout.timeout_seconds',
                    Value='60'
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='routing.http.drop_invalid_header_fields.enabled',
                    Value='false'
                ),
                elasticloadbalancingv2.LoadBalancerAttributes(
                    Key='routing.http2.enabled',
                    Value='true'
                )
            ],
            Scheme=typ,
            SecurityGroups=sg,
            Subnets=[s['SubnetId'] for s in self.get_subnets('private' if typ == 'internal' else 'public')],
            Type='application',
            Tags=self.get_tags(
                service_override="InternalALB" if typ == 'internal' else "ExternalALB",
                role_override=lb_name
            ) + [ec2.Tag('Name', lb_name)]
        )

        _target_group = elasticloadbalancingv2.TargetGroup(
            tg_name,
            Name=tg_name,
            HealthCheckIntervalSeconds=30,
            HealthCheckPath='/ping',
            HealthCheckPort=port,
            HealthCheckProtocol='HTTP',
            HealthCheckTimeoutSeconds=5,
            HealthyThresholdCount=5,
            UnhealthyThresholdCount=2,
            Matcher=elasticloadbalancingv2.Matcher(
                HttpCode='200'
            ),
            Port=port,
            Protocol='HTTP',
            TargetGroupAttributes=[
                elasticloadbalancingv2.TargetGroupAttribute(
                    Key='deregistration_delay.timeout_seconds',
                    Value='300'
                ),
                elasticloadbalancingv2.TargetGroupAttribute(
                    Key='stickiness.enabled',
                    Value='false'
                ),
                elasticloadbalancingv2.TargetGroupAttribute(
                    Key='stickiness.type',
                    Value='lb_cookie'
                ),
                elasticloadbalancingv2.TargetGroupAttribute(
                    Key='load_balancing.algorithm.type',
                    Value='least_outstanding_requests'
                )
            ],
            TargetType='instance',
            VpcId=self.vpc_id,
            Tags=self.get_tags(
                service_override="InternalALB" if typ == 'internal' else "ExternalALB",
                role_override=lb_name
            ) + [ec2.Tag('Name', '{}TG'.format(lb_name))]
        )

        _listener_80 = self.add_resource(elasticloadbalancingv2.Listener(
            '{}80Listener'.format(lb_name),
            Port='80',
            Protocol='HTTP',
            LoadBalancerArn=Ref(_alb),
            DefaultActions=[
                elasticloadbalancingv2.Action(
                    Type='redirect',
                    RedirectConfig=elasticloadbalancingv2.RedirectConfig(
                        Host='#{host}',
                        Path='/#{path}',
                        Port='443',
                        Protocol='HTTPS',
                        Query='#{query}',
                        StatusCode='HTTP_301'
                    )
                )
            ],
        ))
        _listener_443 = self.add_resource(elasticloadbalancingv2.Listener(
            '{}443Listener'.format(lb_name),
            Port='443',
            Protocol='HTTPS',
            LoadBalancerArn=Ref(_alb),
            SslPolicy='ELBSecurityPolicy-2016-08',
            Certificates=[
                elasticloadbalancingv2.Certificate(
                    CertificateArn=cert_arn
                )
            ],
            DefaultActions=[
                elasticloadbalancingv2.Action(
                    Type='forward',
                    TargetGroupArn=Ref(_target_group)
                )
            ],
        ))
        return _alb, _target_group