-
-
Save joshuadfranklin/d3fcc7a7672a76249f22 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
import ( | |
"fmt" | |
"github.com/aws/aws-sdk-go/aws" | |
"github.com/aws/aws-sdk-go/aws/credentials" | |
"github.com/aws/aws-sdk-go/service/ec2" | |
"github.com/vaughan0/go-ini" | |
"net/url" | |
"os" | |
"runtime" | |
"strings" | |
"sync" | |
) | |
func check(e error) { | |
if e != nil { | |
panic(e) | |
} | |
} | |
/* | |
printIds accepts aws credentials and a region, and prints out all | |
instances within the region in a format that's acceptable to us. Currently that | |
format is like this: | |
instance_id name private_ip instance_type public_ip account | |
Any values that aren't available (such as public ip) will be printed out as | |
"None" | |
Because the "name" parameter is user-defined, we'll run QueryEscape on it so that | |
our output stays as a space-separated line. | |
*/ | |
func printIds(key string, pass string, account string, region string, wg *sync.WaitGroup) { | |
defer wg.Done() | |
creds := credentials.NewStaticCredentials(key,pass,"") | |
svc := ec2.New(&aws.Config{ | |
Credentials: creds, | |
Region: region, | |
}) | |
// Here we create an input that will filter any instances that aren't either | |
// of these two states. This is generally what we want | |
params := &ec2.DescribeInstancesInput{ | |
Filters: []*ec2.Filter{ | |
&ec2.Filter{ | |
Name: aws.String("instance-state-name"), | |
Values: []*string{ | |
aws.String("running"), | |
aws.String("pending"), | |
}, | |
}, | |
}, | |
} | |
// TODO: Actually care if we can't connect to a host | |
resp, _ := svc.DescribeInstances(params) | |
// if err != nil { | |
// panic(err) | |
// } | |
// Loop through the instances. They don't always have a name-tag so set it | |
// to None if we can't find anything. | |
for idx, _ := range resp.Reservations { | |
for _, inst := range resp.Reservations[idx].Instances { | |
// We need to see if the Name is one of the tags. It's not always | |
// present and not required in Ec2. | |
name := "None" | |
for _, keys := range inst.Tags { | |
if *keys.Key == "Name" { | |
name = url.QueryEscape(*keys.Value) | |
} | |
} | |
important_vals := []*string{ | |
inst.InstanceID, | |
&name, | |
inst.PrivateIPAddress, | |
inst.InstanceType, | |
inst.PublicIPAddress, | |
&account, | |
®ion, | |
} | |
// Convert any nil value to a printable string in case it doesn't | |
// doesn't exist, which is the case with certain values | |
output_vals := []string{} | |
for _, val := range important_vals { | |
if val != nil { | |
output_vals = append(output_vals, *val) | |
} else { | |
output_vals = append(output_vals, "None") | |
} | |
} | |
// The values that we care about, in the order we want to print them | |
fmt.Println(strings.Join(output_vals, " ")) | |
} | |
} | |
} | |
func main() { | |
// Go for it! | |
runtime.GOMAXPROCS(runtime.NumCPU()) | |
// Make sure the config file exists | |
config := os.Getenv("HOME") + "/.aws/credentials" | |
if _, err := os.Stat(config); os.IsNotExist(err) { | |
fmt.Println("No config file found at: %s", config) | |
os.Exit(1) | |
} | |
var wg sync.WaitGroup | |
file, err := ini.LoadFile(config) | |
check(err) | |
for key, values := range file { | |
profile := strings.Fields(key) | |
account := profile[0] | |
key := values["aws_access_key_id"] | |
pass := values["aws_secret_access_key"] | |
creds := credentials.NewSharedCredentials( os.Getenv("HOME") + "/.aws/credentials", "default") | |
// Gather a list of all available AWS regions. Even though we're gathering | |
// all regions, we still must use a region here for api calls. | |
svc := ec2.New(&aws.Config{ | |
Credentials: creds, | |
Region: "us-west-1", | |
}) | |
// Iterate over every single stinking region to get a list of available | |
// ec2 instances | |
regions, err := svc.DescribeRegions(&ec2.DescribeRegionsInput{}) | |
check(err) | |
for _, region := range regions.Regions { | |
wg.Add(1) | |
go printIds(key, pass, account, *region.RegionName, &wg) | |
} | |
} | |
// Allow the goroutines to finish printing | |
wg.Wait() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment