Skip to content

Commit

Permalink
feat: add support for escaping . in address
Browse files Browse the repository at this point in the history
  • Loading branch information
mcwarman committed Aug 11, 2023
1 parent 12a186a commit fea2d8d
Show file tree
Hide file tree
Showing 17 changed files with 320 additions and 15 deletions.
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,26 @@ resource "foo" "bar" {
}
```

### Address escaping

Address escaping is supported for labels that contain `.`.

Given the following file:

```body.hcl
resource "foo.bar" {
attr1 = "val1"
nested {
attr2 = "val2"
}
}
```

```
$ cat tmp/attr.hcl | hcledit attribute get 'resource.foo\.bar.nested.attr2'
"val2"
```

## License

MIT
42 changes: 42 additions & 0 deletions editor/address.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package editor

import (
"strings"
)

func createAddressFromString(address string) []string {
var separator byte = '.'
var escapeString byte = '\\'

var result []string
var token []byte
for i := 0; i < len(address); i++ {
if address[i] == separator {
result = append(result, string(token))
token = token[:0]
} else if address[i] == escapeString && i+1 < len(address) {
i++
token = append(token, address[i])
} else {
token = append(token, address[i])
}
}
result = append(result, string(token))
return result
}

func createStringFromAddress(address []string) string {
separator := "."
escapeString := "\\"

result := ""

for i, s := range address {
if i > 0 {
result = result + separator
}
result = result + strings.ReplaceAll(s, separator, escapeString+separator)
}

return result
}
75 changes: 75 additions & 0 deletions editor/address_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package editor

import (
"testing"

"github.com/google/go-cmp/cmp"
)

func TestCreateAddressFromString(t *testing.T) {
cases := []struct {
name string
address string
want []string
}{
{
name: "simple address",
address: "b1",
want: []string{"b1"},
},
{
name: "attribute address",
address: "b1.l1.a1",
want: []string{"b1", "l1", "a1"},
},
{
name: "escaped address",
address: `b1.l\.1.a1`,
want: []string{"b1", "l.1", "a1"},
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := createAddressFromString(tc.address)

if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatalf("got:\n%s\nwant:\n%s\ndiff(-want +got):\n%v", got, tc.want, diff)
}
})
}
}

func TestCreateStringFromAddress(t *testing.T) {
cases := []struct {
name string
address []string
want string
}{
{
name: "simple address",
address: []string{"b1"},
want: "b1",
},
{
name: "simple address",
address: []string{"b1", "l1", "a1"},
want: "b1.l1.a1",
},
{
name: "simple address",
address: []string{"b1", `l.1`, "a1"},
want: `b1.l\.1.a1`,
},
}

for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := createStringFromAddress(tc.address)

if diff := cmp.Diff(tc.want, got); diff != "" {
t.Fatalf("got:\n%s\nwant:\n%s\ndiff(-want +got):\n%v", got, tc.want, diff)
}
})
}
}
5 changes: 2 additions & 3 deletions editor/filter_attribute_append.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package editor

import (
"fmt"
"strings"

"github.com/hashicorp/hcl/v2/hclwrite"
)
Expand Down Expand Up @@ -33,12 +32,12 @@ func (f *AttributeAppendFilter) Filter(inFile *hclwrite.File) (*hclwrite.File, e
attrName := f.address
body := inFile.Body()

a := strings.Split(f.address, ".")
a := createAddressFromString(f.address)
if len(a) > 1 {
// if address contains dots, the last element is an attribute name,
// and the rest is the address of the block.
attrName = a[len(a)-1]
blockAddr := strings.Join(a[:len(a)-1], ".")
blockAddr := createStringFromAddress(a[:len(a)-1])
blocks, err := findLongestMatchingBlocks(body, blockAddr)
if err != nil {
return nil, err
Expand Down
20 changes: 20 additions & 0 deletions editor/filter_attribute_append_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,26 @@ b1 "l1" {
ok: false,
want: ``,
},
{
name: "escaped address",
src: `
a0 = v0
b1 "l.1" {
a1 = v1
}
`,
address: `b1.l\.1.a2`,
value: "v2",
newline: false,
ok: true,
want: `
a0 = v0
b1 "l.1" {
a1 = v1
a2 = v2
}
`,
},
}

for _, tc := range cases {
Expand Down
18 changes: 18 additions & 0 deletions editor/filter_attribute_remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,24 @@ a0 = v0
b1 "l1" {
a1 = v1
}
`,
},
{
name: "escaped address",
src: `
a0 = v0
b1 "l.1" {
a1 = v1
a2 = v2
}
`,
address: `b1.l\.1.a1`,
ok: true,
want: `
a0 = v0
b1 "l.1" {
a2 = v2
}
`,
},
}
Expand Down
18 changes: 18 additions & 0 deletions editor/filter_attribute_set_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,24 @@ a0 = v0
b1 "l1" {
a1 = v1
}
`,
},
{
name: "escaped address",
src: `
a0 = v0
b1 "l.1" {
a1 = v1
}
`,
address: `b1.l\.1.a1`,
value: "v2",
ok: true,
want: `
a0 = v0
b1 "l.1" {
a1 = v2
}
`,
},
}
Expand Down
27 changes: 27 additions & 0 deletions editor/filter_block_append_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,33 @@ b1 {
b11 {
}
}
`,
},
{
name: "escaped address",
src: `
a0 = v0
b1 {
a2 = v2
}
b1 "l.1" {
}
`,
parent: `b1.l\.1`,
child: `b11.l\.1.l12`,
newline: false,
ok: true,
want: `
a0 = v0
b1 {
a2 = v2
}
b1 "l.1" {
b11 "l.1" "l12" {
}
}
`,
},
}
Expand Down
3 changes: 1 addition & 2 deletions editor/filter_block_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package editor

import (
"fmt"
"strings"

"github.com/hashicorp/hcl/v2/hclwrite"
)
Expand Down Expand Up @@ -59,7 +58,7 @@ func parseAddress(address string) (string, []string, error) {
return "", []string{}, fmt.Errorf("failed to parse address: %s", address)
}

a := strings.Split(address, ".")
a := createAddressFromString(address)
typeName := a[0]
labels := []string{}
if len(a) > 1 {
Expand Down
20 changes: 20 additions & 0 deletions editor/filter_block_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,26 @@ b1 {
want: `b3 {
a3 = v3
}
`,
},
{
name: "escaped address",
src: `
b1 "b.2" {
a1 = v1
b2 {
a1 = v2
}
}
`,
address: `b1.b\.2`,
ok: true,
want: `b1 "b.2" {
a1 = v1
b2 {
a1 = v2
}
}
`,
},
}
Expand Down
15 changes: 15 additions & 0 deletions editor/filter_block_remove_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,21 @@ b1 l1 l3 {
b1 l1 {
}
`,
},
{
name: "escaped address",
src: `
b1 {
}
b1 "l.1" {
}
`,
address: `b1.l\.1`,
ok: true,
want: `b1 {
}
`,
},
}
Expand Down
23 changes: 23 additions & 0 deletions editor/filter_block_rename_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,29 @@ b1 "l2" {
a2 = v2
}
b2 "l2" {
}
`,
},

{
name: "escaped address",
src: `a0 = v0
b1 "l.1" {
a2 = v2
}
b2 "l2" {
}
`,
from: `b1.l\.1`,
to: `b1.l\.2`,
ok: true,
want: `a0 = v0
b1 "l.2" {
a2 = v2
}
b2 "l2" {
}
`,
Expand Down
16 changes: 16 additions & 0 deletions editor/filter_body_get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,22 @@ b1 {
b2 {
a2 = v2
}
`,
},
{
name: "escaped address",
src: `
b1 {
a1 = v1
}
b1 "l.1" {
a2 = v2
}
`,
address: `b1.l\.1`,
ok: true,
want: `a2 = v2
`,
},
}
Expand Down
Loading

0 comments on commit fea2d8d

Please sign in to comment.