def _create_test_document(self): template = Template() LaunchConfiguration( "launchconfig", template, ImageId='ami-809f84e6', InstanceType='t2.micro', Metadata=Metadata( Init({ 'config': InitConfigFromHTTP(url='http://www.example.com') }))) return json.loads(template.to_json())
}, " --resource myLaunchConfig", " --configsets InstallandRun", " --region ", { "Ref": "AWS::Region" }, "\n" ])), Metadata=Metadata( cf.Init({ "configsets": cf.InitConfigSets(InstallandRun=["install", "config"]), "install": cf.InitConfig(packages={"yum": { "git": [], "wget": [] }}), "config": cf.InitConfig(files=cf.InitFiles({ "/tmp/example.txt": cf.InitFile(content=Join('', [ "This is a file example.\n", "See another examples in:\n", "https://github.com/rabeloo/cf-templates\n" ]), owner="root", group="root", mode="000600") }), ), })))) autoscaling_group_resource = t.add_resource( AutoScalingGroup("myAutoScalingGroup", DesiredCapacity=Ref(desInstances_param), MinSize=Ref(minInstances_param),
Metadata=Metadata( Init({ 'config': InitConfig( files=InitFiles( { '/etc/cfn/cfn-hup.conf': InitFile( content=Join( '', [ '[main]\n', 'stack=', Ref('AWS::StackId'), # NOQA '\n', 'region=', Ref('AWS::Region'), '\n' ]), # NOQA mode='000400', owner='root', group='root'), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( content=Join( '', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init\n', # NOQA 'action=/opt/aws/bin/cfn-init -v ', '--stack ', Ref( # NOQA 'AWS::StackName'), ' --resource ContainerInstances ', ' --region ', Ref('AWS::Region'), '\n', # NOQA 'runas=root\n' ]), mode='000400', owner='root', group='root') }, ), services=InitServices({ 'cfn-hup': InitService( ensureRunning='true', enabled='true', files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }), commands={ '01_add_instance_to_cluster': { 'command': Join( '', [ '#!/bin/bash\n', # NOQA 'echo ECS_CLUSTER=', # NOQA Ref('ECSCluster'), # NOQA ' >> /etc/ecs/ecs.config' ]) }, # NOQA '02_install_ssm_agent': { 'command': Join( '', [ '#!/bin/bash\n', 'yum -y update\n', # NOQA 'curl https://amazon-ssm-eu-west-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm\n', # NOQA 'yum install -y amazon-ssm-agent.rpm' # NOQA ]) } }) }), ),
def add_ec2_instance(self): instance_metadata = Metadata( Init({ 'config': InitConfig( packages={'yum': { 'openvpn': [] }}, files=InitFiles({ '/etc/openvpn/server.conf': InitFile(content=Join('\n', [ 'port 1194', 'proto tcp-server', 'dev tun1', 'ifconfig 172.16.1.2 172.16.1.3', 'status server-tcp.log', 'verb 3', 'secret /etc/openvpn/static.key', 'keepalive 10 60', 'ping-timer-rem', 'persist-tun', 'persist-key', 'user nobody', 'group nobody', 'daemon', ]), mode='000644', owner='root', group='root'), '/etc/openvpn/client.ovpn': InitFile(content=Join('\n', [ 'proto tcp-client', 'remote {{public_ip}}', 'port 1194', 'dev tun', 'secret /tmp/secret.key', 'ifconfig 10.4.0.2 10.4.0.1', ]), mode='000644', owner='root', group='root'), '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', ]), mode='000400', owner='root', group='root'), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.OpenVpn.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), '--resource OpenVpn ', ' --region ', Ref('AWS::Region'), '\n', 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'openvpn': InitService(enabled=True, ensureRunning=True, files=['/etc/openvpn/server.conf']), 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) }) })) self.ec2_instance = self.template.add_resource( ec2.Instance( "OpenVpn", ImageId=FindInMap("RegionMap", Ref("AWS::Region"), "AMI"), InstanceType="t2.micro", KeyName=self.sceptre_user_data["keyname"], SecurityGroupIds=[Ref(self.securityGroup)], IamInstanceProfile=Ref(self.cfninstanceprofile), SubnetId=ImportValue('deploy-dev-vpc-PublicSubnet'), Metadata=instance_metadata, UserData=Base64( Join('', [ '#!/bin/bash -xe\n', 'yum install easy-rsa -y --enablerepo=epel\n', 'yum update -y aws-cfn-bootstrap\n', '/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), ' --resource OpenVpn --region ', Ref('AWS::Region'), '\n', '/opt/aws/bin/cfn-signal -e $? --stack ', Ref('AWS::StackName'), ' --resource OpenVpn --region ', Ref('AWS::Region'), '\n', 'cd /etc/openvpn\n', 'openvpn --genkey --secret static.key\n', 'aws s3 cp static.key s3://', ImportValue('deploy-dev-s3bucket-s3bucketname'), '/\n', 'sudo modprobe iptable_nat', '\n', 'echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward', '\n', 'sudo iptables -t nat -A POSTROUTING -s 10.4.0.1/2 -o eth0 -j MASQUERADE', '\n', 'external_ip=`curl http://169.254.169.254/latest/meta-data/public-ipv4`', '\n', 'sed -i "s|{{public_ip}}|$external_ip|g" /etc/openvpn/client.ovpn', '\n', 'aws s3 cp client.ovpn s3://', ImportValue('deploy-dev-s3bucket-s3bucketname'), '\n', ])), CreationPolicy=CreationPolicy(ResourceSignal=ResourceSignal( Timeout='PT15M')), Tags=Tags(Name="vpn-server"), ))
instance_metadata = Metadata( Init({ 'config': InitConfig( commands={'update_yum_packages': { 'command': 'yum update -y' }}, files=InitFiles({ # setup .bashrc ec2-user '/home/ec2-user/.bashrc': InitFile(content=Join( '', ['export PATH="/home/ec2-user/miniconda/bin:$PATH"\n']), owner='ec2-user', mode='000400', group='ec2-user'), # setup .bashrc root '/root/.bashrc': InitFile(content=Join('', [ 'export PATH="/home/ec2-user/miniconda/bin:$PATH"\n' f'export STREAM_NAME="{STREAM_NAME}"\n', f'export PRODUCER_NAME="{SERVER_NAME}"\n', f'export TWITTER_KEYWORDS="{TWITTER_KEYWORDS}"\n', 'export ENV="production"\n' ]), owner='root', mode='000400', group='root'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', f'path=Resources.{SERVER_NAME}.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), f' --resource {SERVER_NAME}', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService(enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) }) }))
template.add_description('Example VPC') vpc = VPC('vpc', template, CidrBlock=CidrBlock) subnet = Subnet('subnet', template, AvailabilityZone='us-east1a', CidrBlock=CidrBlock, MapPublicIpOnLaunch=False, VpcId=Ref(vpc)) launchconfig = LaunchConfigurationRPM( "launchconfig", template, ImageId='ami-13f7226a', InstanceType='t2.micro', Metadata=Metadata( Init({ 'config': InitConfigFromS3(url="https://s3.amazonaws.com/example/example.sh") }))) asg = AutoScalingGroup("asg", template, MinSize=0, MaxSize=1, DesiredCapacity=1, LaunchConfigurationName=Ref("launchconfig"), VPCZoneIdentifier=[Ref(subnet)]) print(template.to_json())
instance_metadata = Metadata( Init({ 'config': InitConfig( packages={'yum': {'httpd': []}}, files=InitFiles({ '/var/www/html/index.html': InitFile(content=Join('\n', [ '<img \ src="https://s3.amazonaws.com/cloudformation-examples/\ cloudformation_graphic.png" alt="AWS CloudFormation Logo"/>', '<h1>\ Congratulations, you have successfully launched the AWS CloudFormation sample.\ </h1>']), mode='000644', owner='root', group='root'), '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', ['[main]\n', 'stack=', ref_stack_id, '\n', 'region=', ref_region, '\n', ]), mode='000400', owner='root', group='root'), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( content=Join('', ['[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v ', ' --stack ', ref_stack_name, ' --resource WebServerInstance ', ' --region ', ref_region, '\n', 'runas=root\n', ]))}), services={ 'sysvinit': InitServices({ 'httpd': InitService( enabled=True, ensureRunning=True), 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ])})})}))
Metadata=Metadata( Init( { "config": InitConfig( files=InitFiles( { "/etc/cfn/cfn-hup.conf": InitFile( content=Join( "", [ "[main]\n", "stack=", Ref("AWS::StackId"), # NOQA "\n", "region=", Ref("AWS::Region"), "\n", ], ), # NOQA mode="000400", owner="root", group="root", ), "/etc/cfn/hooks.d/cfn-auto-reloader.conf": InitFile( content=Join( "", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init\n", # NOQA "action=/opt/aws/bin/cfn-init -v ", "--stack ", Ref("AWS::StackName"), # NOQA " --resource ContainerInstances ", " --region ", Ref("AWS::Region"), "\n", # NOQA "runas=root\n", ], ), mode="000400", owner="root", group="root", ), }, ), services=InitServices( { "cfn-hup": InitService( ensureRunning="true", enabled="true", files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf", ], ) } ), commands={ "01_add_instance_to_cluster": { "command": Join( "", [ "#!/bin/bash\n", # NOQA "echo ECS_CLUSTER=", # NOQA Ref("ECSCluster"), # NOQA " >> /etc/ecs/ecs.config", ], ) }, # NOQA "02_install_ssm_agent": { "command": Join( "", [ "#!/bin/bash\n", "yum -y update\n", # NOQA "curl https://amazon-ssm-eu-west-1.s3.amazonaws.com/latest/linux_amd64/amazon-ssm-agent.rpm -o amazon-ssm-agent.rpm\n", # NOQA "yum install -y amazon-ssm-agent.rpm", # NOQA ], ) }, }, ) } ), ),
instance_metadata = Metadata( Init( { "config": InitConfig( packages={"yum": {"httpd": []}}, files=InitFiles( { "/var/www/html/index.html": InitFile( content=Join( "\n", [ '<img \ src="https://s3.amazonaws.com/cloudformation-examples/\ cloudformation_graphic.png" alt="AWS CloudFormation Logo"/>', "<h1>\ Congratulations, you have successfully launched the AWS CloudFormation sample.\ </h1>", ], ), mode="000644", owner="root", group="root", ), "/etc/cfn/cfn-hup.conf": InitFile( content=Join( "", [ "[main]\n", "stack=", ref_stack_id, "\n", "region=", ref_region, "\n", ], ), mode="000400", owner="root", group="root", ), "/etc/cfn/hooks.d/cfn-auto-reloader.conf": InitFile( content=Join( "", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -v ", " --stack ", ref_stack_name, " --resource WebServerInstance ", " --region ", ref_region, "\n", "runas=root\n", ], ) ), } ), services={ "sysvinit": InitServices( { "httpd": InitService(enabled=True, ensureRunning=True), "cfn-hup": InitService( enabled=True, ensureRunning=True, files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf", ], ), } ) }, ) } ) )
instance_metadata = Metadata( Init({'config': InitConfig( commands={ 'update_yum_packages': { 'command': 'yum update -y' }, 'download_miniconda': { 'command': 'su - ec2-user -c "wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /home/ec2-user/miniconda.sh"', }, 'install_miniconda': { 'command': 'su - ec2-user -c "bash /home/ec2-user/miniconda.sh -b -p /home/ec2-user/miniconda"', }, 'remove_installer': { 'command': 'rm -rf /home/ec2-user/miniconda.sh', } }, files=InitFiles({ # setup .bashrc '/home/ec2-user/.bashrc': InitFile( content=Join('', [ 'export PATH="/home/ec2-user/miniconda/bin:$PATH"\n' ]), owner='ec2-user', mode='000400', group='ec2-user'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile( content=Join('', ['[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( content=Join('', ['[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.DevServer.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), ' --resource DevServer', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ] ) ) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) })} ) }) )
instance_metadata = Metadata( Init({ 'config': InitConfig( commands={ 'update_yum_packages': { 'command': 'yum update -y' }, 'download_miniconda': { 'command': 'su - ec2-user -c "wget http://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O /home/ec2-user/miniconda.sh"', }, 'install_miniconda': { 'command': 'su - ec2-user -c "bash /home/ec2-user/miniconda.sh -b -p /home/ec2-user/miniconda"', }, 'remove_installer': { 'command': 'rm -rf /home/ec2-user/miniconda.sh', } }, files=InitFiles({ # setup .bashrc '/home/ec2-user/.ssh/authorized_keys': InitFile(content=Join('', [ 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCjKxODWLSrmQAemYnpvYchmy7bwWvIKNWpHtfRiD7UKqnUV0euoFWIr9j+OwiNyMp/iopZQh7A8c+B4TYI8pd///J7ZWPSipndJkWc4HrnU37X66mKInGYIaPZAfek69eeUkl5cekqkEd6l6WsBUlrjPvMYtyGdDtd42M+aNQoy1TWq2C/6x0gBQaY/CUvHFBrMHr5ObhZvN7ou6PSyBCGgQxFf5jmnwSzeBRc/iWxMBltM/SQSTAgyKWdolcgBNTOTre5z8R8FCv/CIsfLoqUFuWthrT3YfpG1iOWlL3GBm8XxXlgrmvMUhV1qvcO/1no6ZeSp8VQMiTYkvAOQ7Hd\n' ]), owner='ec2-user', mode='000400', group='ec2-user'), # setup .bashrc '/home/ec2-user/.bashrc': InitFile(content=Join( '', ['export PATH="/home/ec2-user/miniconda/bin:$PATH"\n']), owner='ec2-user', mode='000400', group='ec2-user'), # configure cfn-hup '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n', 'interval=2', '\n', ]), mode='000400', owner='root', group='root'), # setup cfn-auto-reloader '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile(content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.Bastion.Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v', ' --stack ', Ref('AWS::StackId'), ' --resource Bastion', ' --region ', Ref('AWS::Region'), '\n' 'runas=root\n', ])) }), services={ 'sysvinit': InitServices({ 'cfn-hup': InitService(enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }) }) }))
SslPolicy="ELBSecurityPolicy-TLS-1-2-Ext-2018-06") template.add_resource(target_group) template.add_resource(listener) # Setup the ASG & launch config launch_config = LaunchConfiguration( "LaunchConfig", ImageId=image_id, IamInstanceProfile=Ref(example_instance_profile), InstanceType=instance_type, Metadata=Metadata( Init({ 'config': InitConfig( commands={ "01_run_container": { "command": "docker run -d -p 80:8000 --name whoami -t jwilder/whoami" } }) })), SecurityGroups=[Ref(ec2_security_group)]) auto_scale_group = AutoScalingGroup( "AutoscaleGroup", MinSize=autoscaling_min, MaxSize=autoscaling_max, DesiredCapacity=autoscaling_desired, LaunchConfigurationName=Ref(launch_config), TargetGroupARNs=[GetAtt(target_group, "LoadBalancerArns")], VPCZoneIdentifier=subnet_ids) template.add_resource(launch_config)
instance_metadata = Metadata( Init({ 'config': InitConfig( packages={'yum': {'httpd': []}}, commands={ 'copytest': {'command': 'cp /home/ec2-user/test.txt /var/www/html/'} }, files=InitFiles({ '/etc/cfn/cfn-hup.conf': InitFile(content=Join('', ['[main]\n', 'stack=', ref_stack_id, '\n', 'region=', ref_region, '\n', ]), mode='000400', owner='root', group='root'), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( content=Join('', ['[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.WebServerInstance.\ Metadata.AWS::CloudFormation::Init\n', 'action=/opt/aws/bin/cfn-init -v ', ' --stack ', ref_stack_name, ' --resource WebServerInstance ', ' --region ', ref_region, '\n', 'runas=root\n', ]))}), services={ 'sysvinit': InitServices({ 'httpd': InitService( enabled=True, ensureRunning=True), 'cfn-hup': InitService( enabled=True, ensureRunning=True, files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ])})})}))
def test_using_load_balancer(self): test_stack_name = "TestALB" init_cf_env(test_stack_name) ### t = Template() load_balancer_sg = ts_add_security_group( t, name="LoadBalancerSecurityGroup") instance_sg = ts_add_security_group(t) load_balancer = t.add_resource( LoadBalancer( "MyLoadBalancer", SecurityGroups=[Ref(load_balancer_sg)], # The ALB is publicly accessible. # (use `internal` instead of `internet-facing` to define a load balancer reachable from private network only) Scheme='internet-facing', Subnets=[get_subnet(index=0), get_subnet(index=1) ], # Attaches the ALB to the subnets Type='application')) target_group = t.add_resource( TargetGroup( "MyTargetGroup", HealthCheckIntervalSeconds=10, HealthCheckProtocol='HTTP', HealthCheckPath='/index.html', HealthCheckTimeoutSeconds=5, HealthyThresholdCount=3, UnhealthyThresholdCount=2, Matcher=Matcher( HttpCode='200-299' ), # If HTTP status code is 2XX, the backend is considered healthy. Port= 80, # The web server on the EC2 instances listens on port 80. Protocol='HTTP', VpcId=get_default_vpc(), )) listener = t.add_resource( Listener( "MyListener", LoadBalancerArn=Ref(load_balancer), Port=80, Protocol= 'HTTP', # The load balancer listens on port 80 for HTTP requests. DefaultActions=[ Action( Type='forward', # TargetGroupARN is the connection between the ALB and the auto-scaling group TargetGroupArn=Ref(target_group), ) ])) launch_config = t.add_resource( LaunchConfiguration( "MyLaunchConfiguration", ImageId=get_linux2_image_id(), InstanceType='m4.xlarge', KeyName=KEY, SecurityGroups=[Ref(instance_sg)], AssociatePublicIpAddress=True, InstanceMonitoring=False, UserData=Base64( Join('', [ '#!/bin/bash -xe\n', '/opt/aws/bin/cfn-init -v --stack ', Ref('AWS::StackName'), ' --resource MyLaunchConfiguration ', ' --region ', Ref('AWS::Region'), '\n' ])), Metadata=Metadata( Init({ 'config': InitConfig( packages={'yum': { 'httpd': [] }}, files={ '/tmp/config': { 'content': Join('\n', [ '#!/bin/bash -ex', 'PRIVATE_IP=`curl -s http://169.254.169.254/latest/meta-data/local-ipv4`', 'echo "$PRIVATE_IP" > index.html', ]), 'mode': '000500', 'owner': 'root', 'group': 'root', } }, commands={ '01_config': { 'command': "/tmp/config", 'cwd': '/var/www/html' } }, services={ 'sysvinit': { 'httpd': { 'enabled': True, 'ensureRunning': True } } }) })))) auto_scaling_group = t.add_resource( AutoScalingGroup( "MyAutoScalingGroup", LaunchConfigurationName=Ref(launch_config), DesiredCapacity=2, MinSize=2, MaxSize=2, VPCZoneIdentifier=[get_subnet(index=0), get_subnet(index=1)], TargetGroupARNs=[ Ref(target_group) ], # Registers new EC2 instances with the default target group. Tags=[ Tag( "Name", test_stack_name, True ) # 'True' means: Attaches the same tags to the virtual machine started by this auto-scaling group ])) t.add_output([ Output("URL", Value=Sub('http://${MyLoadBalancer.DNSName}')), ]) dump_template(t, True) create_stack(test_stack_name, t) outputs = get_stack_outputs(test_stack_name) lb_url = get_output_value(outputs, 'URL') private_ips = set() for i in range(10): private_ips.add(run(f'curl {lb_url}', True)) self.assertEqual(len(private_ips), 2)
def create_env(name, overrides, key_name, region, vpc_id, build, internal_domain, base_stack=None): t = Template() t.add_description("""\ microservices stack""") overrides = json.loads(overrides) if overrides else {} # creating private hosted zone (dns) hosted_zone = create_private_dns(t, internal_domain, vpc_id, region) # creating codecommit repo (if not exists) codecommit = boto3.client('codecommit', region_name=region) try: repo_res = codecommit.get_repository( repositoryName=name ) except botocore.exceptions.ClientError as e: if e.response['Error']['Code'] == 'RepositoryDoesNotExistException': repo_res = None new_repo = repo_res is not None if not repo_res: repo_res = codecommit.create_repository( repositoryName=name ) repo = repo_res['repositoryMetadata']['cloneUrlSsh'] # creating config service role_profile = create_ec2_instance_role(t, 'configserver') instance_info = get_instance_info('configserver', build, 't2.micro', role_profile['profile'], region, base_stack, overrides) commands = { "setappenvs": { "command": "echo \"\nspring.cloud.config.server.git.uri={}\n\" >> /home/ubuntu/application.properties".format(repo) } } if new_repo: # restarting the git repo with values for app\default (required for config service health) commands["initgit"] = { "command": "git init && git remote add origin {} && git add . && git commit -m \"init\" && git push origin master".format(repo), "cwd": "/home/ubuntu/gitinit" } metadata = Metadata( Init({ "config": InitConfig( commands=commands ) }), ) config_service = create_microservice_asg_with_elb( t, instance_info['ami'], key_name, instance_info['profile'], instance_info['instanceType'], 'configserver', vpc_id, elb_port=8888, instance_port=8888, region=region, min_size=2, max_size=2, metadata=metadata ) create_private_dns_elb(t, internal_domain, 'config-service', config_service['elb']['name'], 'DnsRecordConfig') # creating eureaka service # creating avatars service ''' avatars_service = create_microservice_asg_with_elb( t, services['avatars']['ami'], key_name, services['avatars']['profile'], services['avatars']['instance_type'], 'AvatarsService', vpc_id, region=region, min_size=2, max_size=2, depends_on=config_service['asg'] ) ''' return t
def create(): es = Template() es.add_description("Stack defining the elasticsearch instance") # Get latest AMIs def getAMI(region): AMIMap = {} print("Getting latest AMZN linux AMI in %s" % region) ec2conn = boto.ec2.connect_to_region(region) images = ec2conn.get_all_images( owners=["amazon"], filters={"name": "amzn-ami-hvm-*.x86_64-gp2"}) latestDate = "" latestAMI = "" for image in images: if image.creationDate > latestDate: latestDate = image.creationDate latestAMI = image.id AMIMap[region] = {"id": latestAMI} return AMIMap # Create AMI Map es.add_mapping("AMIMap", getAMI(region)) # Create es VPC esVPC = es.add_resource( VPC("esVPC", CidrBlock="10.0.0.0/16", Tags=Tags(Name="esVPC"))) # Create es IGW esIGW = es.add_resource(InternetGateway("esIGW")) # Attach IGW to VPC esIGWAttachment = es.add_resource( VPCGatewayAttachment("esIGWAttachment", VpcId=Ref(esVPC), InternetGatewayId=Ref(esIGW))) # Create es Subnet esSubnet = es.add_resource( Subnet("esSubnet", CidrBlock="10.0.0.0/24", VpcId=Ref(esVPC))) # Create es RTB esRTB = es.add_resource(RouteTable("esRTB", VpcId=Ref(esVPC))) # Create route to IGW esDefaultRoute = es.add_resource( Route("esDefaultRoute", DependsOn="esIGWAttachment", GatewayId=Ref(esIGW), DestinationCidrBlock="0.0.0.0/0", RouteTableId=Ref(esRTB))) # Associate RTB with Subnet esSubnetRTBAssociation = es.add_resource( SubnetRouteTableAssociation("esSubnetRTBAssociation", SubnetId=Ref(esSubnet), RouteTableId=Ref(esRTB))) # Create es Security Group esSecurityGroup = es.add_resource( SecurityGroup("esSecurityGroup", GroupDescription="Allow inbound access on port 9200", SecurityGroupIngress=[ SecurityGroupRule(IpProtocol="tcp", FromPort="9200", ToPort="9200", CidrIp="0.0.0.0/0") ], VpcId=Ref(esVPC))) # Create es instance metadata esInstanceMetadata = Metadata( Init( # Use ConfigSets to ensure GPG key and repo file are in place # before trying to install elasticsearch InitConfigSets(ordered=["first", "second"]), first=InitConfig( files=InitFiles({ # cfn-hup notices when the cloudformation stack is changed "/etc/cfn/cfn-hup.conf": InitFile(content=Join("", [ "[main]\n", "stack=", Ref("AWS::StackName"), "\n", "region=", Ref("AWS::Region"), "\n" ]), mode="000400", owner="root", group="root"), # cfn-hup will then trigger cfn-init to run. # This lets us update the instance just by updating the stack "/etc/cfn/hooks.d/cfn-auto-reloader.conf": InitFile(content=Join("", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.esInstance.Metadata\n", "action=/opt/aws/bin/cfn-init -v --stack ", Ref("AWS::StackName"), " ", "--resource esInstance ", "--region ", Ref("AWS::Region"), " ", "--c ordered\n" "runas=root\n" ]), mode="000400", owner="root", group="root"), # repo file for elastic search "/etc/yum.repos.d/elasticsearch.repo": InitFile(content=Join("", [ "[elasticsearch-2.x]\n", "name=Elasticsearch repository for 2.x packages\n", "baseurl=http://packages.elastic.co/elasticsearch/2.x/centos\n", "gpgcheck=1\n", "gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch\n", "enabled=1\n" ]), mode="000400", owner="root", group="root") }), commands={ # Install elasticsearch key so package will install "installGPG": { "command": "rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch" } }), second=InitConfig( packages={ "yum": { # Install elasticsearch "elasticsearch": [], } }, commands={ # Enable external access to elasticsearch "listenOnAllinterfaces": { "command": "echo \"network.host: 0.0.0.0\" >> /etc/elasticsearch/elasticsearch.yml" } }, services={ "sysvinit": InitServices({ "elasticsearch": InitService(enabled=True, ensureRunning=True), "cfn-hup": InitService( enabled=True, ensureRunning=True, files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf" ]) }) }))) # Create es Instance esInstance = es.add_resource( Instance( "esInstance", ImageId=FindInMap("AMIMap", Ref("AWS::Region"), "id"), InstanceType="t2.micro", Metadata=esInstanceMetadata, UserData=Base64( Join("", [ "#!/bin/bash\n", "/opt/aws/bin/cfn-init -v ", "--stack ", Ref("AWS::StackName"), " ", "--resource esInstance ", "--region ", Ref("AWS::Region"), " ", "-c ordered" ])), NetworkInterfaces=[ NetworkInterfaceProperty( GroupSet=[Ref(esSecurityGroup)], AssociatePublicIpAddress="true", DeviceIndex="0", DeleteOnTermination="true", SubnetId=Ref(esSubnet), ) ], Tags=Tags(Name="esInstance"))) # Output address es.add_output([ Output("esAddress", Description="Elastic Search address", Value=Join( "", ["http://", GetAtt("esInstance", "PublicIp"), ":9200/"])) ]) return es
Metadata=Metadata( cloudformation.Init( dict(config=cloudformation.InitConfig( commands=dict(register_cluster=dict(command=Join( "", [ "#!/bin/bash\n", # Register the cluster "echo ECS_CLUSTER=", Ref(main_cluster), " >> /etc/ecs/ecs.config\n", # Enable CloudWatch docker logging 'echo \'ECS_AVAILABLE_LOGGING_DRIVERS=', '["json-file","awslogs"]\'', " >> /etc/ecs/ecs.config\n", ]))), files=cloudformation.InitFiles({ "/etc/cfn/cfn-hup.conf": cloudformation.InitFile( content=Join("", [ "[main]\n", "template=", Ref(AWS_STACK_ID), "\n", "region=", Ref(AWS_REGION), "\n", ]), mode="000400", owner="root", group="root", ), "/etc/cfn/hooks.d/cfn-auto-reload.conf": cloudformation.InitFile( content=Join("", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.%s." % container_instance_configuration_name, "Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -v ", " --stack", Ref(AWS_STACK_NAME), " --resource %s" % container_instance_configuration_name, " --region ", Ref("AWS::Region"), "\n", "runas=root\n", ])) }), services=dict(sysvinit=cloudformation.InitServices({ 'cfn-hup': cloudformation.InitService( enabled=True, ensureRunning=True, files=[ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf", ]), })))))),
def main(): """Generates the CloudFormation template""" template = Template() template.add_version('2010-09-09') template.add_description( 'This template deploys an ECS cluster to the ' + 'provided VPC and subnets using an Auto Scaling Group') # Parameters # EnvironmentName env_name_param = template.add_parameter( Parameter( 'EnvironmentName', Type='String', Description= 'An environment name that will be prefixed to resource names', )) # InstanceType instance_type_param = template.add_parameter( Parameter( 'InstanceType', Type='String', Default='t2.nano', Description= 'Which instance type should we use to build the ECS cluster?', AllowedValues=[ 't2.nano', 't2.micro', 't2.small', 't2.medium', 't2.large', 't2.xlarge', 't2.2xlarge', ], )) # ClusterSize cluster_size_param = template.add_parameter( Parameter( 'ClusterSize', Type='Number', Description='How many ECS hosts do you want to initially deploy?', Default='1', )) # VPC template.add_parameter( Parameter( 'VPC', Type='AWS::EC2::VPC::Id', Description= 'Choose which VPC this ECS cluster should be deployed to', )) # Subnets subnets_param = template.add_parameter( Parameter( 'Subnets', Type='List<AWS::EC2::Subnet::Id>', Description= 'Choose which subnets this ECS cluster should be deployed to', )) # SecurityGroup sg_param = template.add_parameter( Parameter( 'SecurityGroup', Type='AWS::EC2::SecurityGroup::Id', Description= 'Select the Security Group to use for the ECS cluster hosts', )) # Mappings # AWSRegionToAMI template.add_mapping( 'AWSRegionToAMI', { 'us-east-1': { 'AMI': 'ami-a58760b3' }, 'us-east-2': { 'AMI': 'ami-a6e4bec3' }, 'us-west-1': { 'AMI': 'ami-74cb9b14' }, 'us-west-2': { 'AMI': 'ami-5b6dde3b' }, 'eu-west-1': { 'AMI': 'ami-e3fbd290' }, 'eu-west-2': { 'AMI': 'ami-77f6fc13' }, 'eu-central-1': { 'AMI': 'ami-38dc1157' }, 'ap-northeast-1': { 'AMI': 'ami-30bdce57' }, 'ap-southeast-1': { 'AMI': 'ami-9f75ddfc' }, 'ap-southeast-2': { 'AMI': 'ami-cf393cac' }, 'ca-central-1': { 'AMI': 'ami-1b01b37f' }, }, ) # Resources ecs_role = template.add_resource( Role( 'ECSRole', Path='/', RoleName=Sub('${EnvironmentName}-ECSRole-${AWS::Region}'), AssumeRolePolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[awacs.aws.Action('sts', 'AssumeRole')], Principal=awacs.aws.Principal('Service', ['ec2.amazonaws.com']), ), ]), Policies=[ Policy( PolicyName='ecs-service', PolicyDocument=awacs.aws.Policy(Statement=[ awacs.aws.Statement( Effect=awacs.aws.Allow, Action=[ awacs.aws.Action('ecs', 'CreateCluster'), awacs.aws.Action( 'ecs', 'DeregisterContainerInstance'), awacs.aws.Action('ecs', 'DiscoverPollEndpoint'), awacs.aws.Action('ecs', 'Poll'), awacs.aws.Action('ecs', 'RegisterContainerInstance'), awacs.aws.Action('ecs', 'StartTelemetrySession'), awacs.aws.Action('ecs', 'Submit*'), awacs.aws.Action('logs', 'CreateLogStream'), awacs.aws.Action( 'ecr', 'BatchCheckLayerAvailability'), awacs.aws.Action('ecr', 'BatchGetImage'), awacs.aws.Action('ecr', 'GetDownloadUrlForLayer'), awacs.aws.Action('ecr', 'GetAuthorizationToken'), ], Resource=['*'], ), ], ), ), ], )) ecs_instance_profile = template.add_resource( InstanceProfile( 'ECSInstanceProfile', Path='/', Roles=[Ref(ecs_role)], )) # ECSCluster ecs_cluster = template.add_resource( Cluster( 'ECSCluster', ClusterName=Ref(env_name_param), )) instance_metadata = Metadata( Init({ 'config': InitConfig( commands={ '01_add_instance_to_cluster': { 'command': Join('', [ '#!/bin/bash\n', 'echo ECS_CLUSTER=', Ref(ecs_cluster), ' >> /etc/ecs/ecs.config' ]) }, }, files=InitFiles({ '/etc/cfn/cfn-hup.conf': InitFile( mode='000400', owner='root', group='root', content=Join('', [ '[main]\n', 'stack=', Ref('AWS::StackId'), '\n', 'region=', Ref('AWS::Region'), '\n' ]), ), '/etc/cfn/hooks.d/cfn-auto-reloader.conf': InitFile( mode='000400', owner='root', group='root', content=Join('', [ '[cfn-auto-reloader-hook]\n', 'triggers=post.update\n', 'path=Resources.ContainerInstances.Metadata.AWS::CloudFormation::Init\n' 'action=/opt/aws/bin/cfn-init -v --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackId'), ' --resource ECSLaunchConfiguration\n' ]), ) }), services=InitServices({ 'cfn-hup': InitService(enabled='true', ensureRunning='true', files=[ '/etc/cfn/cfn-hup.conf', '/etc/cfn/hooks.d/cfn-auto-reloader.conf' ]) }), ) })) ecs_launch_config = template.add_resource( LaunchConfiguration( 'ECSLaunchConfiguration', ImageId=FindInMap('AWSRegionToAMI', Ref('AWS::Region'), 'AMI'), InstanceType=Ref(instance_type_param), SecurityGroups=[Ref(sg_param)], IamInstanceProfile=Ref(ecs_instance_profile), UserData=Base64( Join('', [ '#!/bin/bash\n', 'yum install -y aws-cfn-bootstrap\n', '/opt/aws/bin/cfn-init -v --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackName'), ' --resource ECSLaunchConfiguration\n', '/opt/aws/bin/cfn-signal -e $? --region ', Ref('AWS::Region'), ' --stack ', Ref('AWS::StackName'), ' --resource ECSAutoScalingGroup\n', ])), Metadata=instance_metadata, )) # ECSAutoScalingGroup: template.add_resource( AutoScalingGroup( 'ECSAutoScalingGroup', VPCZoneIdentifier=Ref(subnets_param), LaunchConfigurationName=Ref(ecs_launch_config), MinSize=Ref(cluster_size_param), MaxSize=Ref(cluster_size_param), DesiredCapacity=Ref(cluster_size_param), Tags=ASTags(Name=(Sub('${EnvironmentName} ECS host'), True)), CreationPolicy=CreationPolicy( ResourceSignal=ResourceSignal(Timeout='PT15M'), ), UpdatePolicy=UpdatePolicy( AutoScalingRollingUpdate=AutoScalingRollingUpdate( MinInstancesInService='1', MaxBatchSize='1', PauseTime='PT15M', WaitOnResourceSignals=True, )), )) # Output template.add_output( Output( 'Cluster', Description='A reference to the ECS cluster', Value=Ref(ecs_cluster), )) print(template.to_json())