Skip to content

Commit

Permalink
hcl: avoid to interpolate resource with itself
Browse files Browse the repository at this point in the history
in this commit, we add a way to avoid the resource to interpolation itself
with the interpolation array.

let's suppose a resource has the same `ID` and the same `name`, name will be interpolated
with the resource. TF does not allow this kind of syntax.

We need to walk through the resources in order to find out if we try to interpolate
the resource itself.
  • Loading branch information
tormath1 committed Feb 11, 2020
1 parent 588435c commit ae5c763
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 11 deletions.
35 changes: 24 additions & 11 deletions hcl/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,17 +128,30 @@ func (w *Writer) Sync() error {
// with TF interpolation
func (w *Writer) Interpolate(i map[string]string) error {
resources := w.Config["resource"]
b, err := json.Marshal(resources)
if err != nil {
return errors.Wrap(err, "unable to convert resources to JSON")
}
for key, value := range i {
b = bytes.ReplaceAll(b, []byte(key), []byte(value))
}
var config map[string]map[string]interface{}
if err := json.Unmarshal(b, &config); err != nil {
return errors.Wrap(err, "unable to convert JSON to resource array")
// walk through the resources
// first loop: the resource types (e.g aws_security_group)
for rt, body := range resources.(map[string]map[string]interface{}) {
// second loop: the resource names (e.g "YefiF")
for name, resource := range body {
b, err := json.Marshal(resource)
if err != nil {
return errors.Wrap(err, "unable to convert resources to JSON")
}
for key, value := range i {
// if the value of the interpolation is ${resource_type.name.id}
// and we are inside the component `resource_type.name` we continue
// to the next iteration
if strings.Contains(value, rt) {
continue
}
b = bytes.ReplaceAll(b, []byte(key), []byte(value))
}
var interpolatedResource map[string]interface{}
if err := json.Unmarshal(b, &interpolatedResource); err != nil {
return errors.Wrap(err, "unable to convert JSON to resource array")
}
resources.(map[string]map[string]interface{})[rt][name] = interpolatedResource
}
}
w.Config["resource"] = config
return nil
}
31 changes: 31 additions & 0 deletions hcl/writer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,37 @@ func TestHCLWriter_Interpolate(t *testing.T) {
id = "interpolated"
}
resource "type" "name" {
network = "${aType.aName.id}"
}
`
)
i["to-be-interpolated"] = "${aType.aName.id}"
hw.Write("type.name", value)
hw.Write("aType.aName", network)

hw.Interpolate(i)
hw.Sync()

assert.Equal(t, hcl, b.String())
})
t.Run("SuccessAvoidInterpolation", func(t *testing.T) {
var (
b = &bytes.Buffer{}
hw = hcl.NewWriter(b)
value = map[string]interface{}{
"network": "to-be-interpolated",
}
network = map[string]interface{}{
"id": "interpolated",
"name": "to-be-interpolated",
}
i = make(map[string]string)
hcl = `resource "aType" "aName" {
id = "interpolated"
name = "to-be-interpolated"
}
resource "type" "name" {
network = "${aType.aName.id}"
}
Expand Down

0 comments on commit ae5c763

Please sign in to comment.