diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4d9851b --- /dev/null +++ b/.gitignore @@ -0,0 +1,113 @@ + +# Created by https://www.gitignore.io/api/go,macos,intellij+all + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, build with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +### Intellij+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff: +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/dictionaries + +# Sensitive or high-churn files: +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.xml +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml + +# Gradle: +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-debug/ + +# Mongo Explorer plugin: +.idea/**/mongoSettings.xml + +## File-based project format: +*.iws + +## Plugin-specific files: + +# IntelliJ +/out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Ruby plugin and RubyMine +/.rakeTasks + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +### Intellij+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +# End of https://www.gitignore.io/api/go,macos,intellij+all diff --git a/README.md b/README.md index 29a0cd9..21eeeba 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ -# di -di - quickly describe instances in EC2 +# li +li - Like `ls` but for EC2 instances + +## Usage + +``` +-a, --adress show IP adresses +-d, --details show all information +-h, --help show help +-i, --id show instance-ID +-s, --status show instance status +-t, --type show instance type +-z, --zone show availability-zone +``` + +## Examples + +IP Address only +``` +~> li -a redis sentinel +Redis Sentinel 165.91.65.2 +``` + +IP Address, instance status and availability-zone +``` +~> li -asz redis sentinel +Redis Sentinel 165.91.65.2 running us-west-1a + +``` diff --git a/main.go b/main.go new file mode 100644 index 0000000..aeec46c --- /dev/null +++ b/main.go @@ -0,0 +1,88 @@ +package main + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go/service/ec2" + flag "github.com/spf13/pflag" + "os" + "strings" + "text/tabwriter" +) + +func main() { + ip := flag.BoolP("adress", "a", false, "show IP adresses") + id := flag.BoolP("id", "i", false, "show instance-ID") + status := flag.BoolP("status", "s", false, "show instance status") + instanceType := flag.BoolP("type", "t", false, "show instance type") + zone := flag.BoolP("zone", "z", false, "show availability-zone") + help := flag.BoolP("help", "h", false, "show help") + detailed := flag.BoolP("details", "d", false, "show all information") + flag.Parse() + + if *help { + flag.PrintDefaults() + os.Exit(0) + } + + sess := session.Must(session.NewSessionWithOptions(session.Options{ + SharedConfigState: session.SharedConfigEnable, + })) + + ec2Svc := ec2.New(sess) + + result, err := ec2Svc.DescribeInstances(nil) + if err != nil { + fmt.Printf("Error", err) + os.Exit(1) + } + + query := strings.Join(flag.Args(), " ") + b := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + + for _, r := range result.Reservations { + for _, i := range r.Instances { + for _, t := range i.Tags { + if *t.Key == "Name" && matches(*t.Value, query) { + s := *t.Value + + if *ip || *detailed { + s = s + "\t" + *i.PrivateIpAddress + } + + if *id || *detailed { + s = s + "\t" + *i.InstanceId + } + + if *status || *detailed { + s = s + "\t" + *i.State.Name + } + + if *instanceType || *detailed { + s = s + "\t" + *i.InstanceType + } + + if *zone || *detailed { + s = s + "\t" + *i.Placement.AvailabilityZone + } + + fmt.Fprintln(b, s) + } + } + } + } + b.Flush() +} + +func matches(value string, query string) bool { + if query == "" { + return true + } + + l, q := strings.ToLower(value), strings.ToLower(query) + if strings.Contains(l, q) { + return true + } + + return false +}