diff --git a/terraform/context.go b/terraform/context.go index 7e6480562..b859d67d8 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -34,7 +34,6 @@ type Context struct { provisioners map[string]ResourceProvisionerFactory variables map[string]string uiInput UIInput - uiOutput UIOutput l sync.Mutex // Lock acquired during any task parCh chan struct{} // Semaphore used to limit parallelism @@ -56,7 +55,6 @@ type ContextOpts struct { Variables map[string]string UIInput UIInput - UIOutput UIOutput } // NewContext creates a new context. @@ -90,7 +88,6 @@ func NewContext(opts *ContextOpts) *Context { provisioners: opts.Provisioners, variables: opts.Variables, uiInput: opts.UIInput, - uiOutput: opts.UIOutput, parCh: parCh, sh: sh, @@ -1313,9 +1310,10 @@ func (c *walkContext) applyProvisioners(r *Resource, is *InstanceState) error { handleHook(h.PreProvision(r.Info, prov.Type)) } - output := PrefixUIOutput{ - Prefix: r.Id + ": ", - UIOutput: c.Context.uiOutput, + output := ProvisionerUIOutput{ + Info: r.Info, + Type: prov.Type, + Hooks: c.Context.hooks, } err := prov.Provisioner.Apply(&output, is, prov.Config) if err != nil { diff --git a/terraform/hook.go b/terraform/hook.go index 8d4c83d4c..47f17c495 100644 --- a/terraform/hook.go +++ b/terraform/hook.go @@ -37,6 +37,7 @@ type Hook interface { PostProvisionResource(*InstanceInfo, *InstanceState) (HookAction, error) PreProvision(*InstanceInfo, string) (HookAction, error) PostProvision(*InstanceInfo, string) (HookAction, error) + ProvisionOutput(*InstanceInfo, string, string) // PreRefresh and PostRefresh are called before and after a single // resource state is refreshed, respectively. @@ -81,6 +82,10 @@ func (*NilHook) PostProvision(*InstanceInfo, string) (HookAction, error) { return HookActionContinue, nil } +func (*NilHook) ProvisionOutput( + *InstanceInfo, string, string) { +} + func (*NilHook) PreRefresh(*InstanceInfo, *InstanceState) (HookAction, error) { return HookActionContinue, nil } diff --git a/terraform/hook_mock.go b/terraform/hook_mock.go index 63ae011b7..b2b6a6e6f 100644 --- a/terraform/hook_mock.go +++ b/terraform/hook_mock.go @@ -53,6 +53,11 @@ type MockHook struct { PostProvisionReturn HookAction PostProvisionError error + ProvisionOutputCalled bool + ProvisionOutputInfo *InstanceInfo + ProvisionOutputProvisionerId string + ProvisionOutputMessage string + PostRefreshCalled bool PostRefreshInfo *InstanceInfo PostRefreshState *InstanceState @@ -124,6 +129,16 @@ func (h *MockHook) PostProvision(n *InstanceInfo, provId string) (HookAction, er return h.PostProvisionReturn, h.PostProvisionError } +func (h *MockHook) ProvisionOutput( + n *InstanceInfo, + provId string, + msg string) { + h.ProvisionOutputCalled = true + h.ProvisionOutputInfo = n + h.ProvisionOutputProvisionerId = provId + h.ProvisionOutputMessage = msg +} + func (h *MockHook) PreRefresh(n *InstanceInfo, s *InstanceState) (HookAction, error) { h.PreRefreshCalled = true h.PreRefreshInfo = n diff --git a/terraform/hook_stop.go b/terraform/hook_stop.go index 148f9c63c..0dc1ad7b4 100644 --- a/terraform/hook_stop.go +++ b/terraform/hook_stop.go @@ -42,6 +42,9 @@ func (h *stopHook) PostProvision(*InstanceInfo, string) (HookAction, error) { return h.hook() } +func (h *stopHook) ProvisionOutput(*InstanceInfo, string, string) { +} + func (h *stopHook) PreRefresh(*InstanceInfo, *InstanceState) (HookAction, error) { return h.hook() } diff --git a/terraform/ui_output_callback.go b/terraform/ui_output_callback.go new file mode 100644 index 000000000..147515b95 --- /dev/null +++ b/terraform/ui_output_callback.go @@ -0,0 +1,5 @@ +package terraform + +type CallbackUIOutput struct { + OutputFun func(string) +} diff --git a/terraform/ui_output_prefix.go b/terraform/ui_output_prefix.go deleted file mode 100644 index e814f6e8e..000000000 --- a/terraform/ui_output_prefix.go +++ /dev/null @@ -1,17 +0,0 @@ -package terraform - -import ( - "fmt" -) - -// PrefixUIOutput is an implementation of UIOutput that prefixes the output -// with a string. -type PrefixUIOutput struct { - Prefix string - UIOutput UIOutput -} - -func (i *PrefixUIOutput) Output(v string) { - v = fmt.Sprintf("%s%s", i.Prefix, v) - i.UIOutput.Output(v) -} diff --git a/terraform/ui_output_prefix_test.go b/terraform/ui_output_prefix_test.go deleted file mode 100644 index 093500f99..000000000 --- a/terraform/ui_output_prefix_test.go +++ /dev/null @@ -1,22 +0,0 @@ -package terraform - -import ( - "testing" -) - -func TestPrefixUIOutput_impl(t *testing.T) { - var _ UIOutput = new(PrefixUIOutput) -} - -func testPrefixUIOutput(t *testing.T) { - output := new(MockUIOutput) - prefix := &PrefixUIOutput{ - Prefix: "foo", - UIOutput: output, - } - - prefix.Output("foo") - if output.OutputMessage != "foofoo" { - t.Fatalf("bad: %#v", output) - } -} diff --git a/terraform/ui_output_provisioner.go b/terraform/ui_output_provisioner.go new file mode 100644 index 000000000..878a03122 --- /dev/null +++ b/terraform/ui_output_provisioner.go @@ -0,0 +1,15 @@ +package terraform + +// ProvisionerUIOutput is an implementation of UIOutput that calls a hook +// for the output so that the hooks can handle it. +type ProvisionerUIOutput struct { + Info *InstanceInfo + Type string + Hooks []Hook +} + +func (o *ProvisionerUIOutput) Output(msg string) { + for _, h := range o.Hooks { + h.ProvisionOutput(o.Info, o.Type, msg) + } +} diff --git a/terraform/ui_output_provisioner_test.go b/terraform/ui_output_provisioner_test.go new file mode 100644 index 000000000..dc1d00c21 --- /dev/null +++ b/terraform/ui_output_provisioner_test.go @@ -0,0 +1,30 @@ +package terraform + +import ( + "testing" +) + +func TestProvisionerUIOutput_impl(t *testing.T) { + var _ UIOutput = new(ProvisionerUIOutput) +} + +func TestProvisionerUIOutputOutput(t *testing.T) { + hook := new(MockHook) + output := &ProvisionerUIOutput{ + Info: nil, + Type: "foo", + Hooks: []Hook{hook}, + } + + output.Output("bar") + + if !hook.ProvisionOutputCalled { + t.Fatal("should be called") + } + if hook.ProvisionOutputProvisionerId != "foo" { + t.Fatalf("bad: %#v", hook.ProvisionOutputProvisionerId) + } + if hook.ProvisionOutputMessage != "bar" { + t.Fatalf("bad: %#v", hook.ProvisionOutputMessage) + } +}