Example #1
0
    def add_resources(self):

        metadata = {
            "AWS::CloudFormation::Init": {
                "configSets": {
                    "wordpress_install": [
                        "install_wordpress"]
                },
                "install_wordpress": {
                    "packages": {
                        "apt": {
                            "apache2": [],
                            "php": [],
                            "php-mysql": [],
                            "php7.0": [],
                            "php7.0-mysql": [],
                            "libapache2-mod-php7.0": [],
                            "php7.0-cli": [],
                            "php7.0-cgi": [],
                            "php7.0-gd": [],
                            "mysql-client": [],
                            "sendmail": []
                        }
                    },
                    "sources": {
                        "/var/www/html": "http://wordpress.org/latest.tar.gz"
                    },
                    "files": {
                        "/tmp/create-wp-config": {
                            "content": {
                                "Fn::Join": ["", [
                                    "#!/bin/bash\n",
                                    "cp /var/www/html/wordpress/wp-config-sample.php /var/www/html/wordpress/wp-config.php\n",
                                    "sed -i \"s/'database_name_here'/'", Ref(
                                        self.DBName), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'username_here'/'", Ref(
                                        self.DBUser), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'password_here'/'", Ref(
                                        self.DBPass), "'/g\" wp-config.php\n",
                                    "sed -i \"s/'localhost'/'", Ref(
                                        self.RDSEndpoint), "'/g\" wp-config.php\n"
                                ]]
                            },
                            "mode": "000500",
                            "owner": "root",
                            "group": "root"
                        }
                    },
                    "commands": {
                        "01_configure_wordpress": {
                            "command": "/tmp/create-wp-config",
                            "cwd": "/var/www/html/wordpress"
                        }
                    }
                }
            }
        }

        self.WaitHandle = self.template.add_resource(cloudformation.WaitConditionHandle(
            "WaitHandle",
        ))

        self.WaitCondition = self.template.add_resource(cloudformation.WaitCondition(
            "WaitCondition",
            Handle=Ref(self.WaitHandle),
            Timeout="600",
            DependsOn="WebServerAutoScalingGroup",
        ))

        self.WebServerLaunchConfiguration = self.template.add_resource(autoscaling.LaunchConfiguration(
            "WebServerLaunchConfiguration",
            Metadata=metadata,
            UserData=Base64(Join("", [
                "#!/bin/bash -x\n",
                "apt-get update\n",
                "apt-get install python-pip nfs-common -y \n",
                "mkdir -p /var/www/html/\n",
                "EC2_AZ=$(curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone)\n",
                "echo \"$EC2_AZ.", Ref(self.FileSystemID), ".efs.", Ref(
                    "AWS::Region"), ".amazonaws.com:/ /var/www/html/ nfs4 nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2 0 0\" >> /etc/fstab\n"
                "mount -a\n",
                "pip install https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz\n",

                # "exec > /tmp/userdata.log 2>&1\n",
                "/usr/local/bin/cfn-init -v  --stack ", Ref("AWS::StackName"),
                "         --resource WebServerLaunchConfiguration ",
                "         --configsets wordpress_install ",
                "         --region ", Ref("AWS::Region"),
                "\n",
                "/bin/mv /var/www/html/wordpress/* /var/www/html/\n",
                "/bin/rm -f /var/www/html/index.html\n",
                "/bin/rm -rf /var/www/html/wordpress/\n",
                "chown www-data:www-data /var/www/html/* -R\n",
                "/usr/sbin/service apache2 restart\n",
                "/usr/bin/curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar\n",
                "/bin/chmod +x wp-cli.phar\n",
                "/bin/mv wp-cli.phar /usr/local/bin/wp\n",
                "cd /var/www/html/\n",
                "if ! $(sudo -u www-data /usr/local/bin/wp core is-installed); then\n",
                "sudo -u www-data /usr/local/bin/wp core install ",
                "--url='", Ref(self.Hostname), ".", Ref(self.Domain), "' ",
                "--title='Cloudreach Meetup - ", Ref(
                    self.Environment), "' ",
                "--admin_user='******' ",
                "--admin_password='******' ",
                "--admin_email='*****@*****.**'\n",
                "wget  https://s3-eu-west-1.amazonaws.com/sceptre-meetup-munich/header.jpg -O /var/www/html/wp-content/themes/twentyseventeen/assets/images/header.jpg\n",
                "chown www-data:www-data /var/www/html/wp-content/themes/twentyseventeen/assets/images/header.jpg\n",

                "fi\n",

                "/usr/local/bin/cfn-signal -e $? --stack ", Ref(
                    "AWS::StackName"), "   -r \"Webserver setup complete\" '", Ref(self.WaitHandle), "'\n"

            ]
            )),
            ImageId=FindInMap("AWSRegion2AMI", Ref("AWS::Region"), "AMI"),
            KeyName=Ref(self.KeyName),
            SecurityGroups=[Ref(self.WebSecurityGroup)],
            InstanceType=Ref(self.InstanceType),
            AssociatePublicIpAddress=True,
        ))

        self.WebServerAutoScalingGroup = self.template.add_resource(autoscaling.AutoScalingGroup(
            "WebServerAutoScalingGroup",
            MinSize=Ref(self.WebServerCapacity),
            DesiredCapacity=Ref(self.WebServerCapacity),
            MaxSize=Ref(self.WebServerCapacity),
            VPCZoneIdentifier=[Ref(self.Subnet1), Ref(self.Subnet2)],
            AvailabilityZones=[Ref(self.AvailabilityZone1),
                               Ref(self.AvailabilityZone2)],
            Tags=autoscaling.Tags(
                Name=Join("-", [Ref(self.Project), "web", "asg"]),
                Environment=Ref(self.Environment),
                Project=Ref(self.Project),
            ),
            LoadBalancerNames=[Ref(self.ElasticLoadBalancer)],
            LaunchConfigurationName=Ref(self.WebServerLaunchConfiguration),
        ))

        self.WebServerScaleUpPolicy = self.template.add_resource(autoscaling.ScalingPolicy(
            "WebServerScaleUpPolicy",
            ScalingAdjustment="1",
            Cooldown="60",
            AutoScalingGroupName=Ref(self.WebServerAutoScalingGroup),
            AdjustmentType="ChangeInCapacity",
        ))

        self.WebServerScaleDownPolicy = self.template.add_resource(autoscaling.ScalingPolicy(
            "WebServerScaleDownPolicy",
            ScalingAdjustment="-1",
            Cooldown="60",
            AutoScalingGroupName=Ref(self.WebServerAutoScalingGroup),
            AdjustmentType="ChangeInCapacity",
        ))

        self.CPUAlarmLow = self.template.add_resource(cloudwatch.Alarm(
            "CPUAlarmLow",
            EvaluationPeriods="2",
            Dimensions=[
                cloudwatch.MetricDimension(
                    Name="AutoScalingGroupName",
                    Value=Ref(self.WebServerAutoScalingGroup)
                ),
            ],
            AlarmActions=[Ref(self.WebServerScaleDownPolicy)],
            AlarmDescription="Scale-down if CPU < 70% for 1 minute",
            Namespace="AWS/EC2",
            Period="60",
            ComparisonOperator="LessThanThreshold",
            Statistic="Average",
            Threshold="70",
            MetricName="CPUUtilization",
        ))

        self.CPUAlarmHigh = self.template.add_resource(cloudwatch.Alarm(
            "CPUAlarmHigh",
            EvaluationPeriods="2",
            Dimensions=[
                cloudwatch.MetricDimension(
                    Name="AutoScalingGroupName",
                    Value=Ref("WebServerAutoScalingGroup")
                ),
            ],
            AlarmActions=[Ref(self.WebServerScaleUpPolicy)],
            AlarmDescription="Scale-up if CPU > 50% for 1 minute",
            Namespace="AWS/EC2",
            Period="60",
            ComparisonOperator="GreaterThanThreshold",
            Statistic="Average",
            Threshold="50",
            MetricName="CPUUtilization",
        ))
Example #2
0
    ImageId=parameters.r_processing_ami,
    InstanceType='m4.large',
    UserData=base64.b64encode('#cloud-config\n' + yaml.safe_dump(r_server_user_data)),
    KeyName='bvanzant',
    SecurityGroups=[
        parameters.database_client_sg,
        GetAtt(default_instance_sg, 'GroupId'),
    ]
))

r_script_runner_asg = stack.add_resource(autoscaling.AutoScalingGroup(
    'RScriptRunnerASG',
    LaunchConfigurationName=Ref(r_script_runner_lc),
    MaxSize=2,
    MinSize=1,
    Tags=autoscaling.Tags(Name='RScriptRunner'),
    VPCZoneIdentifier=parameters.private_subnets.values(),
))


ourelb = stack.add_resource(elb.LoadBalancer(
    "ApplicationElasticLB",
    Name="ApplicationElasticLB",
    Scheme="internet-facing",
    Subnets=parameters.public_subnets.values(),
    SecurityGroups=[GetAtt(elb_sg, 'GroupId')],
))

webserver_target_group = stack.add_resource(elb.TargetGroup(
    "WebserverTarget",
    Port=80,
        # ImageId="ami-bc8ad2cb",  # eu-west-1
        KeyName=Ref(KeyName),
        SecurityGroups=[Ref(WebServerSecurityGroup)],
        InstanceType=Ref(InstanceType),
        AssociatePublicIpAddress=True,
    ))

WebServerAutoScalingGroup = t.add_resource(
    autoscaling.AutoScalingGroup(
        "WebServerAutoScalingGroup",
        MinSize=Ref(WebServerCapacity),
        MaxSize="5",
        VPCZoneIdentifier=[Ref(PubSubnet1), Ref(PubSubnet2)],
        AvailabilityZones=[Ref(AvailabilityZone1),
                           Ref(AvailabilityZone2)],
        Tags=autoscaling.Tags(Name=Join("-",
                                        ["WEB-ASG", Ref(Project)]), ),
        LoadBalancerNames=[Ref("ElasticLoadBalancer")],
        LaunchConfigurationName=Ref("WebServerLaunchConfiguration"),
        CreationPolicy=CreationPolicy(
            ResourceSignal=ResourceSignal(Count=1, Timeout='PT10M')),
        UpdatePolicy=UpdatePolicy(
            AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                PauseTime='PT5M',
                MinInstancesInService="1",
                MaxBatchSize='1',
                WaitOnResourceSignals=True))))

WebServerScaleUpPolicy = t.add_resource(
    autoscaling.ScalingPolicy(
        "WebServerScaleUpPolicy",
        ScalingAdjustment="1",
Example #4
0
def AS_LaunchTemplate():
    cfg.use_cfn_init = True
    InitConfigSets = ASInitConfigSets()

    CfmInitArgs = {}
    IBoxEnvApp = []
    Tags_List = []
    UserDataApp = []

    for n in cfg.Apps:
        name = f"Apps{n}"  # Ex. Apps1
        envname = f"EnvApp{n}Version"  # Ex EnvApp1Version
        reponame = f"{name}RepoName"  # Ex Apps1RepoName

        UserDataApp.extend(["#${%s}\n" % envname])

        p_EnvAppVersion = Parameter(
            envname,
            Description=f"Application {n} version",
            AllowedPattern="^[a-zA-Z0-9-_.]*$",
        )

        p_AppsRepoName = Parameter(
            reponame,
            Description=f"App {n} Repo Name - empty for default based on env/role",
            AllowedPattern="^[a-zA-Z0-9-_.]*$",
        )

        # parameters
        add_obj(
            [
                p_EnvAppVersion,
                p_AppsRepoName,
            ]
        )

        # conditions
        add_obj(
            {
                name: And(
                    Not(Equals(Ref(envname), "")),
                    Not(get_condition("", "equals", "None", reponame)),
                )
            }
        )

        InitConfigApps = ASInitConfigApps(name)
        CfmInitArgs[name] = InitConfigApps

        InitConfigAppsBuilAmi = ASInitConfigAppsBuildAmi(name)
        # AUTOSPOT - Let cfn-init always prepare instances on boot
        # CfmInitArgs[name + 'BuildAmi'] = InitConfigAppsBuilAmi
        CfmInitArgs[name] = InitConfigAppsBuilAmi

        IBoxEnvApp.extend(
            [
                f"export EnvApp{n}Version=",
                Ref(envname),
                "\n",
                f"export EnvRepo{n}Name=",
                get_endvalue(reponame),
                "\n",
            ]
        )

        InitConfigSetsApp = If(name, name, Ref("AWS::NoValue"))
        InitConfigSetsAppBuilAmi = If(name, f"{name}BuildAmi", Ref("AWS::NoValue"))
        IndexSERVICES = InitConfigSets.data["default"].index("SERVICES")
        InitConfigSets.data["default"].insert(IndexSERVICES, InitConfigSetsApp)
        # AUTOSPOT - Let cfn-init always prepare instances on boot
        # InitConfigSets.data['buildamifull'].append(
        #    InitConfigSetsAppBuilAmi)
        InitConfigSets.data["buildamifull"].append(InitConfigSetsApp)

        Tags_List.append(asg.Tag(envname, Ref(envname), True))

        # outputs
        Output_app = Output(envname, Value=Ref(envname))
        Output_repo = Output(reponame, Value=get_endvalue(reponame))

        add_obj([Output_app, Output_repo])

    InitConfigSetup = ASInitConfigSetup()
    InitConfigSetup.ibox_env_app = IBoxEnvApp
    InitConfigSetup.setup()

    InitConfigCodeDeploy = ASInitConfigCodeDeploy()

    CfmInitArgs["SETUP"] = InitConfigSetup
    CfmInitArgs["CWAGENT"] = ASInitConfigCloudWatchAgent("")

    if cfg.CodeDeploy:
        CfmInitArgs["CODEDEPLOY"] = InitConfigCodeDeploy

    if not getattr(cfg, "IBOX_LAUNCH_TEMPLATE_NO_WAIT_ELB_HEALTH", False):
        for lb in cfg.LoadBalancer:
            # LoadBalancerClassic
            if cfg.LoadBalancerType == "Classic":
                InitConfigELB = ASInitConfigELBClassic(scheme=lb)
                CfmInitArgs["ELBWAITER"] = InitConfigELB

            # LoadBalancerApplication
            if cfg.LoadBalancerType == "Application":
                InitConfigELB = ASInitConfigELBApplication(scheme=lb)
                CfmInitArgs["ELBWAITER"] = InitConfigELB

            # LoadBalancerNetwork
            if cfg.LoadBalancerType == "Network":
                for k in cfg.Listeners:
                    InitConfigELB = ASInitConfigELBApplication(
                        scheme=f"TargetGroupListeners{k}{lb}"
                    )
                    CfmInitArgs["ELBWAITER"] = InitConfigELB

    if getattr(cfg, "IBOX_LAUNCH_TEMPLATE_NO_SG_EXTRA", False):
        SecurityGroups = []
    else:
        SecurityGroups = cfg.SecurityGroupsImport

    # Resources
    R_LaunchTemplate = ec2.LaunchTemplate(
        "LaunchTemplate",
        LaunchTemplateName=Sub("${AWS::StackName}-${EnvRole}"),
        LaunchTemplateData=ASLaunchTemplateData(
            "LaunchTemplateData", UserDataApp=UserDataApp
        ),
    )
    R_LaunchTemplate.LaunchTemplateData.NetworkInterfaces[0].Groups.extend(
        SecurityGroups
    )

    # Import role specific cfn definition
    try:
        # Do not use role but direct cfg yaml configuration (ecs + cluster)
        cfn_envrole = f"cfn_{cfg.IBOX_ROLE_EX}"
    except Exception:
        cfn_envrole = f"cfn_{cfg.envrole}"
    cfn_envrole = cfn_envrole.replace("-", "_")
    if cfn_envrole in globals():  # Ex cfn_client_portal
        CfnRole = globals()[cfn_envrole]()
        CfmInitArgs.update(CfnRole)

    if cfg.use_cfn_init:
        R_LaunchTemplate.Metadata = cfm.Metadata(
            {
                "CloudFormationInitVersion": If(
                    "CloudFormationInit",
                    Ref("EnvStackVersion"),
                    Ref("AWS::NoValue"),
                )
            },
            cfm.Init(InitConfigSets, **CfmInitArgs),
            cfm.Authentication(
                {
                    "CfnS3Auth": cfm.AuthenticationBlock(
                        type="S3",
                        buckets=[
                            Sub(cfg.BucketNameAppRepository),
                            Sub(cfg.BucketNameAppData),
                        ],
                        roleName=Ref("RoleInstance"),
                    )
                }
            ),
        )

    add_obj(R_LaunchTemplate)

    Tags = asg.Tags()
    Tags.tags = Tags_List
    return Tags
Example #5
0
    def build_template(self):

        t = self._init_template()

        min_inst = t.add_parameter(
            Parameter('Input{}ASGMinInstances'.format(self.stack_name),
                      Type='String',
                      Default='2',
                      Description='{} Minimum # of instances'.format(
                          self.stack_name)))

        max_inst = t.add_parameter(
            Parameter('Input{}ASGMaxInstances'.format(self.stack_name),
                      Type='String',
                      Default='10',
                      Description='{} Minimum # of instances'.format(
                          self.stack_name)))

        des_inst = t.add_parameter(
            Parameter('Input{}ASGDesiredInstances'.format(self.stack_name),
                      Type='String',
                      Default='2',
                      Description='{} Minimum # of instances'.format(
                          self.stack_name)))

        inst_type = t.add_parameter(
            Parameter('Input{}ASGInstanceType'.format(self.stack_name),
                      Type='String',
                      Default='t2.micro',
                      Description='{} Instance Type'.format(self.stack_name)))

        inst_tag_name = t.add_parameter(
            Parameter('Input{}ASGTagName'.format(self.stack_name),
                      Type='String',
                      Default='{}ASG'.format(self.name),
                      Description='{} Instance Name Tag'.format(
                          self.stack_name)))

        # termination policies
        term_policies = t.add_parameter(
            Parameter('Input{}ASGTerminationPolicies'.format(self.stack_name),
                      Type='String',
                      Default='Default',
                      Description='{} Instance Type'.format(self.stack_name)))

        # root file size
        root_device_size = t.add_parameter(
            Parameter("Input{}ASGRootDeviceSize".format(self.stack_name),
                      Type="String",
                      Default="20",
                      Description="{} Root Device File Size".format(
                          self.stack_name)))

        # root device name
        root_device_name = t.add_parameter(
            Parameter("Input{}ASGRootDeviceName".format(self.stack_name),
                      Type="String",
                      Default="/dev/xvda",
                      Description="{} Root Device Name".format(
                          self.stack_name)))

        # root device type
        root_device_type = t.add_parameter(
            Parameter("Input{}ASGRootDeviceType".format(self.stack_name),
                      Type="String",
                      Default="gp2",
                      Description="{} Root Device Type".format(
                          self.stack_name)))

        # instance profile
        instance_profile_param = t.add_parameter(
            Parameter(self.iam_profile.output_instance_profile(),
                      Type='String'))

        min_in_service = Ref(des_inst)

        # sec groups
        sec_groups = [
            Ref(
                t.add_parameter(
                    Parameter(sg.output_security_group(), Type='String')))
            for sg in self.security_groups
        ]

        # user data params
        user_data = []
        for i in range(0, 4):
            user_data.append(
                Ref(
                    t.add_parameter(
                        Parameter('{}UserData{}'.format(self.stack_name, i),
                                  Type='String',
                                  Default=' ',
                                  Description='{} UserData #{}'.format(
                                      self.stack_name, i)))))

        # subnet list
        if self.private_subnet:
            sn_list = [i for i in self.vpc_stack.output_private_subnets()]
            associate_public_ip = False
        else:
            sn_list = [i for i in self.vpc_stack.output_public_subnets()]
            associate_public_ip = True

        sn_list = [
            Ref(t.add_parameter(Parameter(i, Type='String'))) for i in sn_list
        ]

        elb_list = [
            Ref(t.add_parameter(Parameter(elb.output_elb(), Type='String')))
            for elb in self.elb_stacks
        ]

        lconfig = t.add_resource(
            autoscaling.LaunchConfiguration(
                '{}LaunchConfiguration'.format(self.name),
                AssociatePublicIpAddress=associate_public_ip,
                IamInstanceProfile=Ref(instance_profile_param),
                BlockDeviceMappings=[
                    ec2.BlockDeviceMapping(
                        DeviceName=Ref(root_device_name),
                        Ebs=ec2.EBSBlockDevice(
                            VolumeSize=Ref(root_device_size),
                            VolumeType=Ref(root_device_type),
                            DeleteOnTermination=True))
                ],
                InstanceType=Ref(inst_type),
                SecurityGroups=sec_groups,
                ImageId=self.ami,
                UserData=Base64(
                    Join(
                        '',
                        [
                            "#!/bin/bash\n",
                            "exec > >(tee /var/log/user-data.log|logger ",
                            "-t user-data -s 2>/dev/console) 2>&1\n",
                        ] + user_data + [
                            "\n",
                            "\n",
                            "curl -L https://gist.github.com/ibejohn818",
                            "/aa2bcd6743a59f62e1baa098d6365a61/raw",
                            "/install-cfn-init.sh",
                            " -o /tmp/install-cfn-init.sh && chmod +x /tmp/install-cfn-init.sh",  # noqa
                            "\n",
                            "/tmp/install-cfn-init.sh ",
                            " {}AutoScalingGroup".format(self.stack_name),
                            " ",
                            Ref("AWS::StackName"),
                            " ",
                            Ref("AWS::Region"),
                            "\n",
                        ]))))

        if self.keyname:
            lconfig.KeyName = self.keyname

        asg = t.add_resource(
            autoscaling.AutoScalingGroup(
                '{}AutoScalingGroup'.format(self.stack_name),
                LaunchConfigurationName=Ref(lconfig),
                MinSize=Ref(min_inst),
                MaxSize=Ref(max_inst),
                DesiredCapacity=Ref(des_inst),
                VPCZoneIdentifier=sn_list,
                HealthCheckType='EC2',
                TerminationPolicies=[Ref(term_policies)],
                LoadBalancerNames=elb_list,
                Tags=autoscaling.Tags(Name=Ref(inst_tag_name)),
                UpdatePolicy=UpdatePolicy(
                    AutoScalingRollingUpdate=AutoScalingRollingUpdate(
                        PauseTime=self.pause_time,
                        MinInstancesInService=min_in_service,
                        MaxBatchSize=str(self.update_policy_instance_count),
                        WaitOnResourceSignals=True))))

        t.add_output([Output('{}ASG'.format(self.stack_name), Value=Ref(asg))])

        return t
Example #6
0
File: ac3.py Project: ghac3/cfwp
            Version=GetAtt('WordPressAsgLaunchTemplate',
                           'LatestVersionNumber')),
        Cooldown=360,
        MinSize=If(
            'IsProd', '2',
            Ref('pAsgMinSize')),  # Dev gets 1 but we need 2 for HA in Prod
        MaxSize=If('IsProd', Ref('pAsgMaxSize'),
                   '1'),  # Dev gets max=1 but max=5 for Prod.
        #   AvailabilityZones=If('IsProd', [Ref('pVPCAvailabilityZone1'), Ref('pVPCAvailabilityZone2')], [Ref('pVPCAvailabilityZone1')]),
        HealthCheckType="EC2",
        MetricsCollection=[
            autoscaling.MetricsCollection(Granularity='1Minute')
        ],
        VPCZoneIdentifier=[Ref('pSubnet1'), Ref('pSubnet2')],
        Tags=autoscaling.Tags(Name=Join(
            '_', ['WordPressASG', Ref('AWS::StackName')]),
                              **base_tags)))

# This is the RDS instance. We set MultiAZ to True here if we're in a Production Environment.
rds = template.add_resource(
    rds.DBInstance(
        "WordPressRDS",
        DBName=Ref('pDBName'),
        AllocatedStorage=5,
        DBInstanceClass=Ref('pRDSInstance'),
        Engine="MySQL",
        EngineVersion="5.7",
        MasterUsername="******",
        MasterUserPassword="******",
        VPCSecurityGroups=[Ref('RDSSG')],
        #DBSubnetGroupName='default2',  # Depending on your VPC this might be required
Example #7
0
             ]))

instance_profile = template.add_resource(
    iam.InstanceProfile("InstanceProfile", Path="/", Roles=[Ref(role)]))

launch_configuration = template.add_resource(
    asc.LaunchConfiguration("LaunchConfiguration",
                            ImageId=Ref(image),
                            SecurityGroups=[Ref(security_group)],
                            InstanceMonitoring=False,
                            IamInstanceProfile=Ref(instance_profile),
                            InstanceType=Ref(instance_type),
                            KeyName=Ref(ssh_key_name),
                            UserData=from_file("out/cloud-config.yaml"),
                            AssociatePublicIpAddress=True))

autoscaling_group = template.add_resource(
    asc.AutoScalingGroup(
        "AutoScalingGroup",
        DependsOn=["PublicRoute"],
        AvailabilityZones=[Ref(availability_zone_1),
                           Ref(availability_zone_2)],
        VPCZoneIdentifier=[Ref(subnet_1), Ref(subnet_2)],
        LaunchConfigurationName=Ref(launch_configuration),
        MinSize=0,
        MaxSize=1,
        DesiredCapacity=1,
        Tags=asc.Tags(Name="euca.me")))

print(template.to_json())
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())
        "SaasBaseSecretAccessKey",
        Type="String",
        Description=
        "SaasBase S3 repo read-only AWS account Secret Access Key (http://saasbase.corp.adobe.com/ops/operations/deployment.html)",
    ))

t.add_condition("HasIamInstanceProfile",
                Not(Equals(Ref(iam_instance_profile), "")))
t.add_condition("HasLbs", Not(Equals(Join("", Ref(load_balancer_names)), "")))

body = t.add_resource(
    asn.AutoScalingGroup(
        "Body",
        DesiredCapacity=Ref(group_size),
        Tags=asn.Tags(
            role=Ref(role),
            cell=Ref(cell_name),
        ),
        LaunchConfigurationName=Ref("BodyLaunchConfig"),
        MinSize="0",
        MaxSize="1000",
        VPCZoneIdentifier=[Ref(subnet)],
        LoadBalancerNames=If("HasLbs", Ref(load_balancer_names), []),
        TerminationPolicies=["NewestInstance", "ClosestToNextInstanceHour"]))

ROOT_DEVICE_SIZE = 200
root_block_device_mapping = [
    ec2.BlockDeviceMapping(DeviceName='/dev/sda1',
                           Ebs=ec2.EBSBlockDevice(DeleteOnTermination=True,
                                                  VolumeType='gp2',
                                                  VolumeSize=ROOT_DEVICE_SIZE))
]