diff --git a/.gitignore b/.gitignore index 06db48d..36153ab 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,9 @@ # Test binary, built with `go test -c` *.test +# Binary built with `go build` +cmd/tfstate-lookup/tfstate-lookup + # Output of the go coverage tool, specifically when used with LiteIDE *.out diff --git a/tfstate/lookup.go b/tfstate/lookup.go index 92dec34..d6e3dc0 100644 --- a/tfstate/lookup.go +++ b/tfstate/lookup.go @@ -8,6 +8,7 @@ import ( "net/url" "os" "path/filepath" + "regexp" "sort" "strings" "sync" @@ -242,24 +243,36 @@ func (s *TFState) Lookup(key string) (*Object, error) { // // quoteJQQuery does it. func quoteJQQuery(query string) string { - if !strings.Contains(query, "-") { - return query - } - parts := strings.Split(query, ".") - var builder strings.Builder + splitRegex := regexp.MustCompile(`[.\[\]]`) + indexRegex := regexp.MustCompile(`^-?[0-9]+$`) + parts := splitRegex.Split(query, -1) + parts_coalesced := make([]string, 0, len(parts)) + for _, part := range parts { - // Split(".outputs", ".") -> {"", "outputs"} - if part == "" { - continue + if part != "" { + parts_coalesced = append(parts_coalesced, part) } - if strings.Contains(part, "-") { - builder.WriteString(`["`) + } + + var builder strings.Builder + builder.WriteByte('.') + + for _, part := range parts_coalesced { + builder.WriteByte('[') + if indexRegex.MatchString(part) { builder.WriteString(part) - builder.WriteString(`"]`) } else { - builder.WriteByte('.') + if !strings.HasPrefix(part, `"`) { + builder.WriteByte('"') + } + builder.WriteString(part) + + if !strings.HasSuffix(part, `"`) { + builder.WriteByte('"') + } } + builder.WriteByte(']') } return builder.String() } diff --git a/tfstate/lookup_test.go b/tfstate/lookup_test.go index 6cbce7b..77a1c11 100644 --- a/tfstate/lookup_test.go +++ b/tfstate/lookup_test.go @@ -25,6 +25,7 @@ func init() { var TestNames = []string{ `output.bar`, `output.foo`, + `output.dash-tuple`, `data.aws_caller_identity.current`, `aws_acm_certificate.main`, `module.logs.aws_cloudwatch_log_group.main`, @@ -182,6 +183,14 @@ var TestSuitesOK = []TestSuite{ Key: `data.terraform_remote_state.hyphenated-id.outputs.repository-uri`, Result: `123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/app`, }, + { + Key: `output.dash-tuple[1]`, + Result: float64(2), + }, + { + Key: `output.dash-tuple[-1]`, + Result: float64(1), + }, } func testLookupState(t *testing.T, state *tfstate.TFState) { diff --git a/tfstate/test/terraform.tfstate b/tfstate/test/terraform.tfstate index cda4b82..1084f31 100644 --- a/tfstate/test/terraform.tfstate +++ b/tfstate/test/terraform.tfstate @@ -22,6 +22,21 @@ "string" ] ] + }, + "dash-tuple": { + "value": [ + 3, + 2, + 1 + ], + "type": [ + "tuple", + [ + "number", + "number", + "number" + ] + ] } }, "resources": [