Last active
August 29, 2015 14:20
-
-
Save nfisher/522c303ef325bd5cf43e to your computer and use it in GitHub Desktop.
Go(ing) to the clouds complete example.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"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