Go(ing) to the clouds complete example.
package main | |
// This command will allow you to provision, delete, describe, or estimate the cost of the specified CloudFormation template. | |
// | |
// Once compiled use the -help flag for details. | |
import ( | |
"bufio" | |
"flag" | |
"fmt" | |
"io/ioutil" | |
"log" | |
"os" | |
"github.com/awslabs/aws-sdk-go/aws" | |
"github.com/awslabs/aws-sdk-go/aws/awsutil" | |
awscf "github.com/awslabs/aws-sdk-go/service/cloudformation" | |
) | |
func provisionStack(svc *awscf.CloudFormation, b []byte, params []*awscf.Parameter, stackName string) { | |
input := &awscf.CreateStackInput{ | |
StackName: aws.String(stackName), | |
Capabilities: []*string{ | |
aws.String("CAPABILITY_IAM"), | |
}, | |
OnFailure: aws.String("DELETE"), | |
Parameters: params, | |
TemplateBody: aws.String(string(b)), | |
TimeoutInMinutes: aws.Long(20), | |
} | |
resp, err := svc.CreateStack(input) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println(awsutil.StringValue(resp)) | |
} | |
func delStack(svc *awscf.CloudFormation, stackName string) { | |
input := &awscf.DeleteStackInput{ | |
StackName: aws.String(stackName), | |
} | |
resp, err := svc.DeleteStack(input) | |
if err != nil { | |
log.Fatal(err) | |
} | |
log.Println(awsutil.StringValue(resp)) | |
} | |
func descStack(svc *awscf.CloudFormation, stackName string) { | |
input := &awscf.DescribeStackEventsInput{ | |
StackName: aws.String(stackName), | |
} | |
resp, err := svc.DescribeStackEvents(input) | |
if err != nil { | |
log.Fatal(err) | |
} | |
if len(resp.StackEvents) > 0 { | |
log.Println(awsutil.StringValue(resp.StackEvents[0])) | |
} | |
} | |
func cost(svc *awscf.CloudFormation, b []byte, params []*awscf.Parameter) { | |
estInput := &awscf.EstimateTemplateCostInput{ | |
Parameters: params, | |
TemplateBody: aws.String(string(b)), | |
} | |
cost, err := svc.EstimateTemplateCost(estInput) | |
if err != nil { | |
log.Fatal(err) | |
} | |
fmt.Println(awsutil.StringValue(cost.URL)) | |
} | |
func main() { | |
var templateFile string | |
var outputCost bool | |
var provision bool | |
var desc bool | |
var del bool | |
var b []byte | |
var params []*awscf.Parameter | |
var stackName string | |
var region string | |
flag.StringVar(®ion, "region", "eu-west-1", "AWS region to provision script to.") | |
flag.StringVar(&templateFile, "template", "", "Template to validate.") | |
flag.StringVar(&stackName, "name", "", "Stack name (required).") | |
flag.BoolVar(&outputCost, "cost", false, "Output cost URL.") | |
flag.BoolVar(&provision, "provision", false, "Provision template.") | |
flag.BoolVar(&desc, "desc", false, "Describe stack.") | |
flag.BoolVar(&del, "del", false, "Delete stack.") | |
flag.Parse() | |
if stackName == "" { | |
fmt.Println("Stack name cannot be empty!\n") | |
flag.Usage() | |
return | |
} | |
config := &aws.Config{Region: region} | |
svc := awscf.New(config) | |
if outputCost || provision { | |
f, err := os.Open(templateFile) | |
if err != nil { | |
log.Fatal(err) | |
} | |
b, err = ioutil.ReadAll(f) | |
if err != nil { | |
log.Fatal(err) | |
} | |
input := &awscf.ValidateTemplateInput{ | |
TemplateBody: aws.String(string(b)), | |
} | |
resp, err := svc.ValidateTemplate(input) | |
if err != nil { | |
log.Fatal(err) | |
} | |
// output the template description | |
fmt.Println(awsutil.StringValue(resp.Description)) | |
params = make([]*awscf.Parameter, len(resp.Parameters)) | |
// fill out the parameters from the template | |
stdin := bufio.NewReader(os.Stdin) | |
for i, p := range resp.Parameters { | |
fmt.Printf("%v (%v): ", awsutil.StringValue(p.Description), awsutil.StringValue(p.DefaultValue)) | |
// don't care about isMore if someone's typing so much oh well | |
b, _, err := stdin.ReadLine() | |
if err != nil { | |
log.Fatal(err) | |
} | |
line := string(b) | |
params[i] = &awscf.Parameter{ | |
ParameterKey: p.ParameterKey, | |
UsePreviousValue: aws.Boolean(true), | |
} | |
if line != "" { | |
params[i].ParameterValue = aws.String(line) | |
} else { | |
params[i].ParameterValue = p.DefaultValue | |
} | |
} | |
} | |
if outputCost { | |
cost(svc, b, params) | |
return | |
} else if provision { | |
provisionStack(svc, b, params, stackName) | |
} else if desc { | |
descStack(svc, stackName) | |
} else if del { | |
delStack(svc, stackName) | |
} | |
} |
{ | |
"AWSTemplateFormatVersion" : "2010-09-09", | |
"Description" : "AWS CloudFormation Sample Template VPC_with_PublicIPs_And_DNS: Sample template showing how to create a VPC with DNS and Public IPs enabled. You will be billed for the AWS resources used if you create a stack from this template.", | |
"Parameters" : { | |
"KeyName" : { | |
"Description" : "Name of an existing EC2 KeyPair to enable SSH access to the bastion host", | |
"Type" : "AWS::EC2::KeyPair::KeyName", | |
"ConstraintDescription" : "must be the name of an existing EC2 KeyPair.", | |
"Default" : "nfisher.macair" | |
}, | |
"SSHLocation" : { | |
"Description" : "Lockdown SSH access to the bastion host (default can be accessed from anywhere)", | |
"Type" : "String", | |
"MinLength": "9", | |
"MaxLength": "18", | |
"Default" : "0.0.0.0/0", | |
"AllowedPattern" : "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", | |
"ConstraintDescription" : "must be a valid CIDR range of the form x.x.x.x/x." | |
}, | |
"EC2InstanceType" : { | |
"Description" : "EC2 instance type", | |
"Type" : "String", | |
"Default" : "t2.micro", | |
"AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"] | |
, | |
"ConstraintDescription" : "must be a valid EC2 instance type." | |
} | |
}, | |
"Mappings" : { | |
"SubnetConfig" : { | |
"VPC" : { "CIDR" : "10.0.0.0/16" }, | |
"Public" : { "CIDR" : "10.0.0.0/24" } | |
}, | |
"AWSInstanceType2Arch" : { | |
"t1.micro" : { "Arch" : "PV64" }, | |
"t2.micro" : { "Arch" : "HVM64" }, | |
"t2.small" : { "Arch" : "HVM64" }, | |
"t2.medium" : { "Arch" : "HVM64" }, | |
"m1.small" : { "Arch" : "PV64" }, | |
"m1.medium" : { "Arch" : "PV64" }, | |
"m1.large" : { "Arch" : "PV64" }, | |
"m1.xlarge" : { "Arch" : "PV64" }, | |
"m2.xlarge" : { "Arch" : "PV64" }, | |
"m2.2xlarge" : { "Arch" : "PV64" }, | |
"m2.4xlarge" : { "Arch" : "PV64" }, | |
"m3.medium" : { "Arch" : "HVM64" }, | |
"m3.large" : { "Arch" : "HVM64" }, | |
"m3.xlarge" : { "Arch" : "HVM64" }, | |
"m3.2xlarge" : { "Arch" : "HVM64" }, | |
"c1.medium" : { "Arch" : "PV64" }, | |
"c1.xlarge" : { "Arch" : "PV64" }, | |
"c3.large" : { "Arch" : "HVM64" }, | |
"c3.xlarge" : { "Arch" : "HVM64" }, | |
"c3.2xlarge" : { "Arch" : "HVM64" }, | |
"c3.4xlarge" : { "Arch" : "HVM64" }, | |
"c3.8xlarge" : { "Arch" : "HVM64" }, | |
"c4.large" : { "Arch" : "HVM64" }, | |
"c4.xlarge" : { "Arch" : "HVM64" }, | |
"c4.2xlarge" : { "Arch" : "HVM64" }, | |
"c4.4xlarge" : { "Arch" : "HVM64" }, | |
"c4.8xlarge" : { "Arch" : "HVM64" }, | |
"g2.2xlarge" : { "Arch" : "HVMG2" }, | |
"r3.large" : { "Arch" : "HVM64" }, | |
"r3.xlarge" : { "Arch" : "HVM64" }, | |
"r3.2xlarge" : { "Arch" : "HVM64" }, | |
"r3.4xlarge" : { "Arch" : "HVM64" }, | |
"r3.8xlarge" : { "Arch" : "HVM64" }, | |
"i2.xlarge" : { "Arch" : "HVM64" }, | |
"i2.2xlarge" : { "Arch" : "HVM64" }, | |
"i2.4xlarge" : { "Arch" : "HVM64" }, | |
"i2.8xlarge" : { "Arch" : "HVM64" }, | |
"d2.xlarge" : { "Arch" : "HVM64" }, | |
"d2.2xlarge" : { "Arch" : "HVM64" }, | |
"d2.4xlarge" : { "Arch" : "HVM64" }, | |
"d2.8xlarge" : { "Arch" : "HVM64" }, | |
"hi1.4xlarge" : { "Arch" : "HVM64" }, | |
"hs1.8xlarge" : { "Arch" : "HVM64" }, | |
"cr1.8xlarge" : { "Arch" : "HVM64" }, | |
"cc2.8xlarge" : { "Arch" : "HVM64" } | |
} | |
, | |
"AWSRegionArch2AMI" : { | |
"us-east-1" : {"PV64" : "ami-1ccae774", "HVM64" : "ami-10cae778", "HVMG2" : "ami-8c6b40e4"}, | |
"us-west-2" : {"PV64" : "ami-ff527ecf", "HVM64" : "ami-e9527ed9", "HVMG2" : "ami-abbe919b"}, | |
"us-west-1" : {"PV64" : "ami-d514f291", "HVM64" : "ami-cb14f28f", "HVMG2" : "ami-f31ffeb7"}, | |
"eu-west-1" : {"PV64" : "ami-bf0897c8", "HVM64" : "ami-a30897d4", "HVMG2" : "ami-d5bc24a2"}, | |
"eu-central-1" : {"PV64" : "ami-ac221fb1", "HVM64" : "ami-ae221fb3", "HVMG2" : "ami-7cd2ef61"}, | |
"ap-northeast-1" : {"PV64" : "ami-27f90e27", "HVM64" : "ami-c7f90ec7", "HVMG2" : "ami-6318e863"}, | |
"ap-southeast-1" : {"PV64" : "ami-acd9e8fe", "HVM64" : "ami-64d8e936", "HVMG2" : "ami-3807376a"}, | |
"ap-southeast-2" : {"PV64" : "ami-ff9cecc5", "HVM64" : "ami-f39cecc9", "HVMG2" : "ami-89790ab3"}, | |
"sa-east-1" : {"PV64" : "ami-bb2890a6", "HVM64" : "ami-b72890aa", "HVMG2" : "NOT_SUPPORTED"}, | |
"cn-north-1" : {"PV64" : "ami-fa39abc3", "HVM64" : "ami-e839abd1", "HVMG2" : "NOT_SUPPORTED"} | |
} | |
}, | |
"Resources" : { | |
"VPC" : { | |
"Type" : "AWS::EC2::VPC", | |
"Properties" : { | |
"EnableDnsSupport" : "true", | |
"EnableDnsHostnames" : "true", | |
"CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "VPC", "CIDR" ]}, | |
"Tags" : [ | |
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, | |
{ "Key" : "Network", "Value" : "Public" } | |
] | |
} | |
}, | |
"PublicSubnet" : { | |
"Type" : "AWS::EC2::Subnet", | |
"Properties" : { | |
"VpcId" : { "Ref" : "VPC" }, | |
"CidrBlock" : { "Fn::FindInMap" : [ "SubnetConfig", "Public", "CIDR" ]}, | |
"Tags" : [ | |
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, | |
{ "Key" : "Network", "Value" : "Public" } | |
] | |
} | |
}, | |
"InternetGateway" : { | |
"Type" : "AWS::EC2::InternetGateway", | |
"Properties" : { | |
"Tags" : [ | |
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, | |
{ "Key" : "Network", "Value" : "Public" } | |
] | |
} | |
}, | |
"GatewayToInternet" : { | |
"Type" : "AWS::EC2::VPCGatewayAttachment", | |
"Properties" : { | |
"VpcId" : { "Ref" : "VPC" }, | |
"InternetGatewayId" : { "Ref" : "InternetGateway" } | |
} | |
}, | |
"PublicRouteTable" : { | |
"Type" : "AWS::EC2::RouteTable", | |
"Properties" : { | |
"VpcId" : { "Ref" : "VPC" }, | |
"Tags" : [ | |
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, | |
{ "Key" : "Network", "Value" : "Public" } | |
] | |
} | |
}, | |
"PublicRoute" : { | |
"Type" : "AWS::EC2::Route", | |
"DependsOn" : "GatewayToInternet", | |
"Properties" : { | |
"RouteTableId" : { "Ref" : "PublicRouteTable" }, | |
"DestinationCidrBlock" : "0.0.0.0/0", | |
"GatewayId" : { "Ref" : "InternetGateway" } | |
} | |
}, | |
"PublicSubnetRouteTableAssociation" : { | |
"Type" : "AWS::EC2::SubnetRouteTableAssociation", | |
"Properties" : { | |
"SubnetId" : { "Ref" : "PublicSubnet" }, | |
"RouteTableId" : { "Ref" : "PublicRouteTable" } | |
} | |
}, | |
"PublicNetworkAcl" : { | |
"Type" : "AWS::EC2::NetworkAcl", | |
"Properties" : { | |
"VpcId" : { "Ref" : "VPC" }, | |
"Tags" : [ | |
{ "Key" : "Application", "Value" : { "Ref" : "AWS::StackName" } }, | |
{ "Key" : "Network", "Value" : "Public" } | |
] | |
} | |
}, | |
"InboundHTTPPublicNetworkAclEntry" : { | |
"Type" : "AWS::EC2::NetworkAclEntry", | |
"Properties" : { | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }, | |
"RuleNumber" : "100", | |
"Protocol" : "6", | |
"RuleAction" : "allow", | |
"Egress" : "false", | |
"CidrBlock" : "0.0.0.0/0", | |
"PortRange" : { "From" : "80", "To" : "80" } | |
} | |
}, | |
"InboundHTTPSPublicNetworkAclEntry" : { | |
"Type" : "AWS::EC2::NetworkAclEntry", | |
"Properties" : { | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }, | |
"RuleNumber" : "101", | |
"Protocol" : "6", | |
"RuleAction" : "allow", | |
"Egress" : "false", | |
"CidrBlock" : "0.0.0.0/0", | |
"PortRange" : { "From" : "443", "To" : "443" } | |
} | |
}, | |
"InboundSSHPublicNetworkAclEntry" : { | |
"Type" : "AWS::EC2::NetworkAclEntry", | |
"Properties" : { | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }, | |
"RuleNumber" : "102", | |
"Protocol" : "6", | |
"RuleAction" : "allow", | |
"Egress" : "false", | |
"CidrBlock" : { "Ref" : "SSHLocation" }, | |
"PortRange" : { "From" : "22", "To" : "22" } | |
} | |
}, | |
"InboundEphemeralPublicNetworkAclEntry" : { | |
"Type" : "AWS::EC2::NetworkAclEntry", | |
"Properties" : { | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }, | |
"RuleNumber" : "103", | |
"Protocol" : "6", | |
"RuleAction" : "allow", | |
"Egress" : "false", | |
"CidrBlock" : "0.0.0.0/0", | |
"PortRange" : { "From" : "1024", "To" : "65535" } | |
} | |
}, | |
"OutboundPublicNetworkAclEntry" : { | |
"Type" : "AWS::EC2::NetworkAclEntry", | |
"Properties" : { | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" }, | |
"RuleNumber" : "100", | |
"Protocol" : "6", | |
"RuleAction" : "allow", | |
"Egress" : "true", | |
"CidrBlock" : "0.0.0.0/0", | |
"PortRange" : { "From" : "0", "To" : "65535" } | |
} | |
}, | |
"PublicSubnetNetworkAclAssociation" : { | |
"Type" : "AWS::EC2::SubnetNetworkAclAssociation", | |
"Properties" : { | |
"SubnetId" : { "Ref" : "PublicSubnet" }, | |
"NetworkAclId" : { "Ref" : "PublicNetworkAcl" } | |
} | |
}, | |
"EC2Host" : { | |
"Type" : "AWS::EC2::Instance", | |
"DependsOn" : "GatewayToInternet", | |
"Properties" : { | |
"InstanceType" : { "Ref" : "EC2InstanceType" }, | |
"KeyName" : { "Ref" : "KeyName" }, | |
"ImageId" : { "Fn::FindInMap" : [ "AWSRegionArch2AMI", { "Ref" : "AWS::Region" }, | |
{ "Fn::FindInMap" : [ "AWSInstanceType2Arch", { "Ref" : "EC2InstanceType" }, "Arch" ] } ] }, | |
"NetworkInterfaces" : [{ | |
"GroupSet" : [{ "Ref" : "EC2SecurityGroup" }], | |
"AssociatePublicIpAddress" : "true", | |
"DeviceIndex" : "0", | |
"DeleteOnTermination" : "true", | |
"SubnetId" : { "Ref" : "PublicSubnet" } | |
}] | |
} | |
}, | |
"EC2SecurityGroup" : { | |
"Type" : "AWS::EC2::SecurityGroup", | |
"Properties" : { | |
"GroupDescription" : "Enable access to the EC2 host", | |
"VpcId" : { "Ref" : "VPC" }, | |
"SecurityGroupIngress" : [ { | |
"IpProtocol" : "tcp", | |
"FromPort" : "22", | |
"ToPort" : "22", | |
"CidrIp" : { "Ref" : "SSHLocation" } | |
} ] | |
} | |
} | |
}, | |
"Outputs" : { | |
"VPCId" : { | |
"Description" : "VPCId of the newly created VPC", | |
"Value" : { "Ref" : "VPC" } | |
}, | |
"PublicSubnet" : { | |
"Description" : "SubnetId of the public subnet", | |
"Value" : { "Ref" : "PublicSubnet" } | |
}, | |
"DNSName" : { | |
"Description" : "DNS Name of the EC2 host", | |
"Value" : { "Fn::GetAtt" : ["EC2Host", "PublicDnsName"] } | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment