docker-archive / deploykit

A toolkit for creating and managing declarative, self-healing infrastructure.
Apache License 2.0
2.25k stars 262 forks source link

Terraform plugin’s `Properties` should be treated as a template #490

Closed kaufers closed 7 years ago

kaufers commented 7 years ago

The dynamic Infrakit instance ID needs to be template-able in the groups.json file. For example, if the instance was named instance-1493145652 then the {{.InstanceID}} should be resolve to 1493145652 in the groups definition. This allows us to reference the dynamic instance ID suffix in the group definition.

chungers commented 7 years ago

You can make the change here... In the beginning of the Provision method we have the ID... https://github.com/docker/infrakit/blob/master/examples/instance/terraform/plugin.go#L344

So I'd move this to the beginning of the method and then apply spec.Properties as a template, replace the spec.Properties with the rendered template and then decode it (at line 327) and continue as usual.

To render the template:

import "github.com/docker/infrakit/pkg/template"

// ....

t, _ := template.NewTemplate(spec.Properties.Bytes(), template.Options{})
rendered, _ := t.Render(map[string]interface{}{ "InstanceID" : id })

Once the template is rendered with the new context of the map, any expressions containing {{.InstanceID}} would be replaced by the generated id.

Then we replace the spec.Properties with the rendered template like so, and continue processing as before:

// now make the rendered view be the new spec.Properties
spec.Properties = types.AnyBytes(rendered)

// ...
// now decode it (as line 327) does:
tf := TFormat{}
err := spec.Properties.Decode(&tf)
kaufers commented 7 years ago

It seems that the templating is being done before the spec it send to the terraform instance plugin's Provision function when doing a manager group commit. The terraform instance plugin's Provision function then sees the value already rendered as <no value>.

This means that we cannot do something as simple as {{.InstanceID}} because of the multiple layers of templating.

kaufers commented 7 years ago

Instead I'll investigate it we can use something like {{ var "self/id" }} that will simply echo itself if the value is not known.

kaufers commented 7 years ago

Now that the multipass support has merged (#510), the instance plugin will see any unresolved variables and we can resolve {{ var "/self/instId" }} to the dynamically generated instance ID.

kaufers commented 7 years ago

@chungers this was fixed by https://github.com/docker/infrakit/pull/522