1
1
mirror of https://github.com/adammck/terraform-inventory synced 2024-11-26 11:53:48 +01:00
terraform-inventory/cli.go
Jonathan McCall 0e941ce0d5 Create all group as per Ansible inventory script conventions (#46)
* Conform to Ansible inventory script conventions
* Make cmdInventory work with all group
* Add only uniq hosts to group "all"'s host list
* go fmt
* Fix typo
* Fix tests broken by #46
* Add duplicate host to test appendUniq
* Fix appendUniq and dedup other groups besides "all"
2016-09-22 00:13:26 -04:00

128 lines
2.8 KiB
Go

package main
import (
"encoding/json"
"fmt"
"io"
"sort"
)
type allGroup struct {
Hosts []string `json:"hosts"`
Vars map[string]interface{} `json:"vars"`
}
func appendUniq(strs []string, item string) []string {
if len(strs) == 0 {
strs = append(strs, item)
return strs
}
sort.Strings(strs)
i := sort.SearchStrings(strs, item)
if i == len(strs) || (i < len(strs) && strs[i] != item) {
strs = append(strs, item)
}
return strs
}
func gatherResources(s *state) map[string]interface{} {
groups := make(map[string]interface{}, 0)
all_group := allGroup{Vars: make(map[string]interface{})}
groups["all"] = &all_group
for _, res := range s.resources() {
for _, grp := range res.Groups() {
_, ok := groups[grp]
if !ok {
groups[grp] = []string{}
}
groups[grp] = appendUniq(groups[grp].([]string), res.Address())
all_group.Hosts = appendUniq(all_group.Hosts, res.Address())
}
}
if len(s.outputs()) > 0 {
for _, out := range s.outputs() {
all_group.Vars[out.keyName] = out.value
}
}
return groups
}
func cmdList(stdout io.Writer, stderr io.Writer, s *state) int {
return output(stdout, stderr, gatherResources(s))
}
func cmdInventory(stdout io.Writer, stderr io.Writer, s *state) int {
groups := gatherResources(s)
for group, res := range groups {
switch grp := res.(type) {
case []string:
writeLn("["+group+"]", stdout, stderr)
for _, item := range grp {
writeLn(item, stdout, stderr)
}
case *allGroup:
writeLn("["+group+"]", stdout, stderr)
for _, item := range grp.Hosts {
writeLn(item, stdout, stderr)
}
writeLn("", stdout, stderr)
writeLn("["+group+":vars]", stdout, stderr)
for key, item := range grp.Vars {
writeLn(key+"="+item.(string), stdout, stderr)
}
}
writeLn("", stdout, stderr)
}
return 0
}
func writeLn(str string, stdout io.Writer, stderr io.Writer) {
_, err := io.WriteString(stdout, str+"\n")
checkErr(err, stderr)
}
func checkErr(err error, stderr io.Writer) int {
if err != nil {
fmt.Fprintf(stderr, "Error writing inventory: %s\n", err)
return 1
}
return 0
}
func cmdHost(stdout io.Writer, stderr io.Writer, s *state, hostname string) int {
for _, res := range s.resources() {
if hostname == res.Address() {
return output(stdout, stderr, res.Attributes())
}
}
fmt.Fprintf(stderr, "No such host: %s\n", hostname)
return 1
}
// output marshals an arbitrary JSON object and writes it to stdout, or writes
// an error to stderr, then returns the appropriate exit code.
func output(stdout io.Writer, stderr io.Writer, whatever interface{}) int {
b, err := json.Marshal(whatever)
if err != nil {
fmt.Fprintf(stderr, "Error encoding JSON: %s\n", err)
return 1
}
_, err = stdout.Write(b)
if err != nil {
fmt.Fprintf(stderr, "Error writing JSON: %s\n", err)
return 1
}
return 0
}