diff --git a/cli.go b/cli.go index 4cf1aaf..eb03abc 100644 --- a/cli.go +++ b/cli.go @@ -4,10 +4,32 @@ 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() { @@ -16,14 +38,14 @@ func gatherResources(s *state) map[string]interface{} { groups[grp] = []string{} } - groups[grp] = append(groups[grp].([]string), res.Address()) + groups[grp] = appendUniq(groups[grp].([]string), res.Address()) + all_group.Hosts = appendUniq(all_group.Hosts, res.Address()) } } if len(s.outputs()) > 0 { - groups["all"] = make(map[string]interface{}, 0) for _, out := range s.outputs() { - groups["all"].(map[string]interface{})[out.keyName] = out.value + all_group.Vars[out.keyName] = out.value } } return groups @@ -37,31 +59,44 @@ func cmdInventory(stdout io.Writer, stderr io.Writer, s *state) int { groups := gatherResources(s) for group, res := range groups { - _, err := io.WriteString(stdout, "["+group+"]\n") - if err != nil { - fmt.Fprintf(stderr, "Error writing Invetory: %s\n", err) - return 1 - } - - for _, ress := range res.([]string) { + switch grp := res.(type) { + case []string: + writeLn("["+group+"]", stdout, stderr) + for _, item := range grp { + writeLn(item, stdout, stderr) + } - _, err := io.WriteString(stdout, ress+"\n") - if err != nil { - fmt.Fprintf(stderr, "Error writing Invetory: %s\n", err) - return 1 + 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) } } - _, err = io.WriteString(stdout, "\n") - if err != nil { - fmt.Fprintf(stderr, "Error writing Invetory: %s\n", err) - return 1 - } + 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() { diff --git a/parser_test.go b/parser_test.go index 02b116c..351d7a6 100644 --- a/parser_test.go +++ b/parser_test.go @@ -49,6 +49,18 @@ const exampleStateFile = ` } } }, + "aws_instance.dup.0": { + "type": "aws_instance", + "primary": { + "id": "i-aaaaaaaa", + "attributes": { + "id": "i-aaaaaaaa", + "private_ip": "10.0.0.1", + "tags.#": "1", + "tags.Role": "Web" + } + } + }, "aws_instance.one.1": { "type": "aws_instance", "primary": { @@ -139,8 +151,25 @@ const exampleStateFile = ` const expectedListOutput = ` { - "all": {"datacenter": "mydc", "olddatacenter": "<0.7_format", "ids": [1, 2, 3, 4], "map": {"key": "value"}}, + "all": { + "hosts": [ + "10.0.0.1", + "10.0.1.1", + "10.120.0.226", + "10.2.1.5", + "10.20.30.40", + "192.168.0.3", + "50.0.0.1" + ], + "vars": { + "datacenter": "mydc", + "olddatacenter": "<0.7_format", + "ids": [1, 2, 3, 4], + "map": {"key": "value"} + } + }, "one": ["10.0.0.1", "10.0.1.1"], + "dup": ["10.0.0.1"], "two": ["50.0.0.1"], "three": ["192.168.0.3"], "four": ["10.2.1.5"], @@ -148,6 +177,7 @@ const expectedListOutput = ` "six": ["10.120.0.226"], "one.0": ["10.0.0.1"], + "dup.0": ["10.0.0.1"], "one.1": ["10.0.1.1"], "two.0": ["50.0.0.1"], "three.0": ["192.168.0.3"],