1
1
Fork 0
mirror of https://github.com/adammck/terraform-inventory synced 2024-05-24 21:26:03 +02:00
terraform-inventory/terraform-inventory.go
Adam Mckaig 2938602cae Rename to terraform-inventory
To match the recommended plugin naming scheme, even though this isn't a
plugin (yet?).
2014-09-24 15:35:55 -04:00

140 lines
2.5 KiB
Go

package main
import (
"encoding/json"
"flag"
"fmt"
"github.com/hashicorp/terraform/terraform"
"os"
"path/filepath"
)
var list = flag.Bool("list", false, "list mode")
var host = flag.String("host", "", "host mode")
type Host struct {
Name string `json:"name"`
IP string `json:"ip"`
vars HostVars
}
type HostVars map[string]interface{}
type Group struct {
name string
hosts []*Host
}
func main() {
flag.Parse()
file := flag.Arg(0)
if file == "" {
fmt.Printf("Usage: %s [options] path\n", os.Args[0])
os.Exit(1)
}
if !*list && *host == "" {
fmt.Println("Either --host or --list must be specified")
os.Exit(1)
}
path, err := filepath.Abs(file)
if err != nil {
fmt.Printf("Invalid file: %s\n", err)
os.Exit(1)
}
f, err := os.Open(path)
if err != nil {
fmt.Printf("Error opening tfstate file: %s\n", err)
os.Exit(1)
}
state, err := terraform.ReadState(f)
if err != nil {
fmt.Printf("Error reading state: %s\n", err)
os.Exit(1)
}
if *list {
hosts := mustGetList(state)
os.Stdout.Write(mustMarshal(hosts))
} else if *host != "" {
host := mustGetHost(state, *host)
os.Stdout.Write(mustMarshal(host.vars))
}
}
func mustGetList(state *terraform.State) interface{} {
hosts, err := getList(state)
if err != nil {
fmt.Printf("Error getting host list: %s\n", err)
os.Exit(1)
}
return hosts
}
func mustGetHost(state *terraform.State, hostname string) *Host {
host, err := getHost(state, hostname)
if err != nil {
fmt.Printf("Error getting host variables: %s\n", err)
os.Exit(1)
}
return host
}
func mustMarshal(whatever interface{}) []byte {
json, err := json.Marshal(whatever)
if err != nil {
fmt.Printf("Error encoding JSON: %s\n", err)
os.Exit(1)
}
return json
}
func getList(state *terraform.State) (interface{}, error) {
hostnames := make([]string, 0)
for _, h := range readHosts(state) {
hostnames = append(hostnames, h.IP)
}
groups := map[string][]string{"production": hostnames}
return groups, nil
}
func getHost(state *terraform.State, hostname string) (*Host, error) {
for _, h := range readHosts(state) {
if h.IP == hostname {
return h, nil
}
}
return nil, fmt.Errorf("No such host: %s", hostname)
}
func readHosts(state *terraform.State) []*Host {
hosts := make([]*Host, 0)
for _, resource := range state.Resources {
if resource.Type == "aws_instance" {
host := &Host{
Name: resource.Attributes["id"],
IP: resource.Attributes["public_ip"],
vars: HostVars{},
}
hosts = append(hosts, host)
}
}
return hosts
}