Merge pull request #27760 from hashicorp/alisdair/command-views-ui-hook
cli: Migrate Terraform UI hook to command views
This commit is contained in:
commit
1ae3d30383
|
@ -183,6 +183,10 @@ type Operation struct {
|
||||||
// configuration from ConfigDir.
|
// configuration from ConfigDir.
|
||||||
ConfigLoader *configload.Loader
|
ConfigLoader *configload.Loader
|
||||||
|
|
||||||
|
// Hooks can be used to perform actions triggered by various events during
|
||||||
|
// the operation's lifecycle.
|
||||||
|
Hooks []terraform.Hook
|
||||||
|
|
||||||
// Plan is a plan that was passed as an argument. This is valid for
|
// Plan is a plan that was passed as an argument. This is valid for
|
||||||
// plan and apply arguments but may not work for all backends.
|
// plan and apply arguments but may not work for all backends.
|
||||||
PlanFile *planfile.Reader
|
PlanFile *planfile.Reader
|
||||||
|
|
|
@ -40,12 +40,7 @@ func (b *Local) opApply(
|
||||||
}
|
}
|
||||||
|
|
||||||
stateHook := new(StateHook)
|
stateHook := new(StateHook)
|
||||||
if b.ContextOpts == nil {
|
op.Hooks = append(op.Hooks, stateHook)
|
||||||
b.ContextOpts = new(terraform.ContextOpts)
|
|
||||||
}
|
|
||||||
old := b.ContextOpts.Hooks
|
|
||||||
defer func() { b.ContextOpts.Hooks = old }()
|
|
||||||
b.ContextOpts.Hooks = append(b.ContextOpts.Hooks, stateHook)
|
|
||||||
|
|
||||||
// Get our context
|
// Get our context
|
||||||
tfCtx, _, opState, contextDiags := b.context(op)
|
tfCtx, _, opState, contextDiags := b.context(op)
|
||||||
|
|
|
@ -77,6 +77,7 @@ func (b *Local) context(op *backend.Operation) (*terraform.Context, *configload.
|
||||||
opts.Destroy = op.Destroy
|
opts.Destroy = op.Destroy
|
||||||
opts.Targets = op.Targets
|
opts.Targets = op.Targets
|
||||||
opts.UIInput = op.UIIn
|
opts.UIInput = op.UIIn
|
||||||
|
opts.Hooks = op.Hooks
|
||||||
|
|
||||||
opts.SkipRefresh = op.Type != backend.OperationTypeRefresh && !op.PlanRefresh
|
opts.SkipRefresh = op.Type != backend.OperationTypeRefresh && !op.PlanRefresh
|
||||||
if opts.SkipRefresh {
|
if opts.SkipRefresh {
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/command/arguments"
|
"github.com/hashicorp/terraform/command/arguments"
|
||||||
"github.com/hashicorp/terraform/command/views"
|
"github.com/hashicorp/terraform/command/views"
|
||||||
"github.com/hashicorp/terraform/plans/planfile"
|
"github.com/hashicorp/terraform/plans/planfile"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -110,7 +111,6 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
|
|
||||||
// Set up our count hook that keeps track of resource changes
|
// Set up our count hook that keeps track of resource changes
|
||||||
countHook := new(CountHook)
|
countHook := new(CountHook)
|
||||||
c.ExtraHooks = append(c.ExtraHooks, countHook)
|
|
||||||
|
|
||||||
// Load the backend
|
// Load the backend
|
||||||
var be backend.Enhanced
|
var be backend.Enhanced
|
||||||
|
@ -171,6 +171,7 @@ func (c *ApplyCommand) Run(args []string) int {
|
||||||
opReq.AutoApprove = autoApprove
|
opReq.AutoApprove = autoApprove
|
||||||
opReq.ConfigDir = configPath
|
opReq.ConfigDir = configPath
|
||||||
opReq.Destroy = c.Destroy
|
opReq.Destroy = c.Destroy
|
||||||
|
opReq.Hooks = []terraform.Hook{countHook, c.uiHook()}
|
||||||
opReq.PlanFile = planFile
|
opReq.PlanFile = planFile
|
||||||
opReq.PlanRefresh = refresh
|
opReq.PlanRefresh = refresh
|
||||||
opReq.ShowDiagnostics = c.showDiagnostics
|
opReq.ShowDiagnostics = c.showDiagnostics
|
||||||
|
|
|
@ -941,10 +941,12 @@ func TestApply_planNoModuleFiles(t *testing.T) {
|
||||||
p := applyFixtureProvider()
|
p := applyFixtureProvider()
|
||||||
planPath := applyFixturePlanFile(t)
|
planPath := applyFixturePlanFile(t)
|
||||||
|
|
||||||
|
view, _ := testView(t)
|
||||||
apply := &ApplyCommand{
|
apply := &ApplyCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: new(cli.MockUi),
|
Ui: new(cli.MockUi),
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
args := []string{
|
args := []string{
|
||||||
|
|
|
@ -189,6 +189,7 @@ func (c *ImportCommand) Run(args []string) int {
|
||||||
c.showDiagnostics(diags)
|
c.showDiagnostics(diags)
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
opReq.Hooks = []terraform.Hook{c.uiHook()}
|
||||||
{
|
{
|
||||||
var moreDiags tfdiags.Diagnostics
|
var moreDiags tfdiags.Diagnostics
|
||||||
opReq.Variables, moreDiags = c.collectVariableValues()
|
opReq.Variables, moreDiags = c.collectVariableValues()
|
||||||
|
|
|
@ -24,10 +24,12 @@ func TestImport(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -77,10 +79,12 @@ func TestImport_providerConfig(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,9 +174,11 @@ func TestImport_remoteState(t *testing.T) {
|
||||||
|
|
||||||
// init our backend
|
// init our backend
|
||||||
ui := cli.NewMockUi()
|
ui := cli.NewMockUi()
|
||||||
|
view, _ := testView(t)
|
||||||
m := Meta{
|
m := Meta{
|
||||||
testingOverrides: metaOverridesForProvider(testProvider()),
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ProviderSource: providerSource,
|
ProviderSource: providerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +198,7 @@ func TestImport_remoteState(t *testing.T) {
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,9 +287,11 @@ func TestImport_initializationErrorShouldUnlock(t *testing.T) {
|
||||||
|
|
||||||
// init our backend
|
// init our backend
|
||||||
ui := cli.NewMockUi()
|
ui := cli.NewMockUi()
|
||||||
|
view, _ := testView(t)
|
||||||
m := Meta{
|
m := Meta{
|
||||||
testingOverrides: metaOverridesForProvider(testProvider()),
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ProviderSource: providerSource,
|
ProviderSource: providerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -305,6 +314,7 @@ func TestImport_initializationErrorShouldUnlock(t *testing.T) {
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,10 +349,12 @@ func TestImport_providerConfigWithVar(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,10 +429,12 @@ func TestImport_providerConfigWithDataSource(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,10 +494,12 @@ func TestImport_providerConfigWithVarDefault(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -557,10 +573,12 @@ func TestImport_providerConfigWithVarFile(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -635,10 +653,12 @@ func TestImport_allowMissingResourceConfig(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,10 +710,12 @@ func TestImport_emptyConfig(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -720,10 +742,12 @@ func TestImport_missingResourceConfig(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -750,10 +774,12 @@ func TestImport_missingModuleConfig(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,9 +827,11 @@ func TestImportModuleVarFile(t *testing.T) {
|
||||||
|
|
||||||
// init to install the module
|
// init to install the module
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
m := Meta{
|
m := Meta{
|
||||||
testingOverrides: metaOverridesForProvider(testProvider()),
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ProviderSource: providerSource,
|
ProviderSource: providerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -820,6 +848,7 @@ func TestImportModuleVarFile(t *testing.T) {
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
args := []string{
|
args := []string{
|
||||||
|
@ -873,9 +902,11 @@ func TestImportModuleInputVariableEvaluation(t *testing.T) {
|
||||||
|
|
||||||
// init to install the module
|
// init to install the module
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
m := Meta{
|
m := Meta{
|
||||||
testingOverrides: metaOverridesForProvider(testProvider()),
|
testingOverrides: metaOverridesForProvider(testProvider()),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ProviderSource: providerSource,
|
ProviderSource: providerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,6 +923,7 @@ func TestImportModuleInputVariableEvaluation(t *testing.T) {
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
args := []string{
|
args := []string{
|
||||||
|
@ -912,10 +944,12 @@ func TestImport_dataResource(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,10 +976,12 @@ func TestImport_invalidResourceAddr(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -972,10 +1008,12 @@ func TestImport_targetIsModule(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &ImportCommand{
|
c := &ImportCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/backend/local"
|
"github.com/hashicorp/terraform/backend/local"
|
||||||
|
"github.com/hashicorp/terraform/command/arguments"
|
||||||
"github.com/hashicorp/terraform/command/format"
|
"github.com/hashicorp/terraform/command/format"
|
||||||
"github.com/hashicorp/terraform/command/views"
|
"github.com/hashicorp/terraform/command/views"
|
||||||
"github.com/hashicorp/terraform/command/webbrowser"
|
"github.com/hashicorp/terraform/command/webbrowser"
|
||||||
|
@ -69,9 +70,6 @@ type Meta struct {
|
||||||
GlobalPluginDirs []string // Additional paths to search for plugins
|
GlobalPluginDirs []string // Additional paths to search for plugins
|
||||||
Ui cli.Ui // Ui for output
|
Ui cli.Ui // Ui for output
|
||||||
|
|
||||||
// ExtraHooks are extra hooks to add to the context.
|
|
||||||
ExtraHooks []terraform.Hook
|
|
||||||
|
|
||||||
// Services provides access to remote endpoint information for
|
// Services provides access to remote endpoint information for
|
||||||
// "terraform-native' services running at a specific user-facing hostname.
|
// "terraform-native' services running at a specific user-facing hostname.
|
||||||
Services *disco.Disco
|
Services *disco.Disco
|
||||||
|
@ -434,8 +432,6 @@ func (m *Meta) contextOpts() (*terraform.ContextOpts, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var opts terraform.ContextOpts
|
var opts terraform.ContextOpts
|
||||||
opts.Hooks = []terraform.Hook{m.uiHook()}
|
|
||||||
opts.Hooks = append(opts.Hooks, m.ExtraHooks...)
|
|
||||||
|
|
||||||
opts.Targets = m.targets
|
opts.Targets = m.targets
|
||||||
opts.UIInput = m.UIInput()
|
opts.UIInput = m.UIInput()
|
||||||
|
@ -621,15 +617,21 @@ func (m *Meta) process(args []string) []string {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reconfigure the view. This is necessary for commands which use both
|
||||||
|
// views.View and cli.Ui during the migration phase.
|
||||||
|
if m.View != nil {
|
||||||
|
m.View.Configure(&arguments.View{
|
||||||
|
CompactWarnings: m.compactWarnings,
|
||||||
|
NoColor: !m.Color,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
// uiHook returns the UiHook to use with the context.
|
// uiHook returns the UiHook to use with the context.
|
||||||
func (m *Meta) uiHook() *UiHook {
|
func (m *Meta) uiHook() *views.UiHook {
|
||||||
return &UiHook{
|
return views.NewUiHook(m.View)
|
||||||
Colorize: m.Colorize(),
|
|
||||||
Ui: m.Ui,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// confirm asks a yes/no confirmation.
|
// confirm asks a yes/no confirmation.
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/configs"
|
"github.com/hashicorp/terraform/configs"
|
||||||
"github.com/hashicorp/terraform/plans"
|
"github.com/hashicorp/terraform/plans"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -82,6 +83,7 @@ func (c *PlanCommand) Run(args []string) int {
|
||||||
opReq := c.Operation(b)
|
opReq := c.Operation(b)
|
||||||
opReq.ConfigDir = configPath
|
opReq.ConfigDir = configPath
|
||||||
opReq.Destroy = destroy
|
opReq.Destroy = destroy
|
||||||
|
opReq.Hooks = []terraform.Hook{c.uiHook()}
|
||||||
opReq.PlanOutPath = outPath
|
opReq.PlanOutPath = outPath
|
||||||
opReq.PlanRefresh = refresh
|
opReq.PlanRefresh = refresh
|
||||||
opReq.ShowDiagnostics = c.showDiagnostics
|
opReq.ShowDiagnostics = c.showDiagnostics
|
||||||
|
|
|
@ -32,10 +32,12 @@ func TestPlan(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,10 +61,12 @@ func TestPlan_lockedState(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,10 +89,12 @@ func TestPlan_plan(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,10 +132,12 @@ func TestPlan_destroy(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -158,10 +166,12 @@ func TestPlan_noState(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,10 +203,12 @@ func TestPlan_outPath(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,10 +258,12 @@ func TestPlan_outPathNoChange(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,10 +338,12 @@ func TestPlan_outBackend(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui := cli.NewMockUi()
|
ui := cli.NewMockUi()
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,10 +392,12 @@ func TestPlan_refreshFalse(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -407,10 +425,12 @@ func TestPlan_state(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -450,10 +470,12 @@ func TestPlan_stateDefault(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -505,10 +527,12 @@ func TestPlan_validate(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -532,10 +556,12 @@ func TestPlan_vars(t *testing.T) {
|
||||||
|
|
||||||
p := planVarsFixtureProvider()
|
p := planVarsFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -577,10 +603,12 @@ func TestPlan_varsUnset(t *testing.T) {
|
||||||
|
|
||||||
p := planVarsFixtureProvider()
|
p := planVarsFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,10 +668,12 @@ func TestPlan_providerArgumentUnset(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -667,10 +697,12 @@ func TestPlan_varFile(t *testing.T) {
|
||||||
|
|
||||||
p := planVarsFixtureProvider()
|
p := planVarsFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,10 +739,12 @@ func TestPlan_varFileDefault(t *testing.T) {
|
||||||
|
|
||||||
p := planVarsFixtureProvider()
|
p := planVarsFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,10 +779,12 @@ func TestPlan_varFileWithDecls(t *testing.T) {
|
||||||
|
|
||||||
p := planVarsFixtureProvider()
|
p := planVarsFixtureProvider()
|
||||||
ui := cli.NewMockUi()
|
ui := cli.NewMockUi()
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,10 +809,12 @@ func TestPlan_detailedExitcode(t *testing.T) {
|
||||||
|
|
||||||
p := planFixtureProvider()
|
p := planFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -794,10 +832,12 @@ func TestPlan_detailedExitcode_emptyDiff(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -819,10 +859,12 @@ func TestPlan_shutdown(t *testing.T) {
|
||||||
|
|
||||||
p := testProvider()
|
p := testProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ShutdownCh: shutdownCh,
|
ShutdownCh: shutdownCh,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -884,10 +926,12 @@ func TestPlan_init_required(t *testing.T) {
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
// Running plan without setting testingOverrides is similar to plan without init
|
// Running plan without setting testingOverrides is similar to plan without init
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -927,10 +971,12 @@ func TestPlan_targeted(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,9 +1007,11 @@ func TestPlan_targetFlagsDiags(t *testing.T) {
|
||||||
defer testChdir(t, td)()
|
defer testChdir(t, td)()
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
c := &PlanCommand{
|
c := &PlanCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/arguments"
|
"github.com/hashicorp/terraform/command/arguments"
|
||||||
"github.com/hashicorp/terraform/command/views"
|
"github.com/hashicorp/terraform/command/views"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -75,6 +76,7 @@ func (c *RefreshCommand) Run(args []string) int {
|
||||||
// Build the operation
|
// Build the operation
|
||||||
opReq := c.Operation(b)
|
opReq := c.Operation(b)
|
||||||
opReq.ConfigDir = configPath
|
opReq.ConfigDir = configPath
|
||||||
|
opReq.Hooks = []terraform.Hook{c.uiHook()}
|
||||||
opReq.ShowDiagnostics = c.showDiagnostics
|
opReq.ShowDiagnostics = c.showDiagnostics
|
||||||
opReq.Type = backend.OperationTypeRefresh
|
opReq.Type = backend.OperationTypeRefresh
|
||||||
|
|
||||||
|
|
|
@ -791,7 +791,7 @@ func TestRefresh_targeted(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
view, _ := testView(t)
|
view, done := testView(t)
|
||||||
c := &RefreshCommand{
|
c := &RefreshCommand{
|
||||||
Meta: Meta{
|
Meta: Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
|
@ -808,7 +808,7 @@ func TestRefresh_targeted(t *testing.T) {
|
||||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
got := ui.OutputWriter.String()
|
got := done(t).Stdout()
|
||||||
if want := "test_instance.foo: Refreshing"; !strings.Contains(got, want) {
|
if want := "test_instance.foo: Refreshing"; !strings.Contains(got, want) {
|
||||||
t.Fatalf("expected output to contain %q, got:\n%s", want, got)
|
t.Fatalf("expected output to contain %q, got:\n%s", want, got)
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,9 +255,11 @@ func TestShow_json_output(t *testing.T) {
|
||||||
|
|
||||||
p := showFixtureProvider()
|
p := showFixtureProvider()
|
||||||
ui := new(cli.MockUi)
|
ui := new(cli.MockUi)
|
||||||
|
view, _ := testView(t)
|
||||||
m := Meta{
|
m := Meta{
|
||||||
testingOverrides: metaOverridesForProvider(p),
|
testingOverrides: metaOverridesForProvider(p),
|
||||||
Ui: ui,
|
Ui: ui,
|
||||||
|
View: view,
|
||||||
ProviderSource: providerSource,
|
ProviderSource: providerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package command
|
package views
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
@ -9,8 +9,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"github.com/mitchellh/colorstring"
|
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
@ -24,17 +22,24 @@ import (
|
||||||
const defaultPeriodicUiTimer = 10 * time.Second
|
const defaultPeriodicUiTimer = 10 * time.Second
|
||||||
const maxIdLen = 80
|
const maxIdLen = 80
|
||||||
|
|
||||||
|
func NewUiHook(view *View) *UiHook {
|
||||||
|
return &UiHook{
|
||||||
|
view: view,
|
||||||
|
periodicUiTimer: defaultPeriodicUiTimer,
|
||||||
|
resources: make(map[string]uiResourceState),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type UiHook struct {
|
type UiHook struct {
|
||||||
terraform.NilHook
|
terraform.NilHook
|
||||||
|
|
||||||
Colorize *colorstring.Colorize
|
view *View
|
||||||
Ui cli.Ui
|
viewLock sync.Mutex
|
||||||
PeriodicUiTimer time.Duration
|
|
||||||
|
periodicUiTimer time.Duration
|
||||||
|
|
||||||
l sync.Mutex
|
|
||||||
once sync.Once
|
|
||||||
resources map[string]uiResourceState
|
resources map[string]uiResourceState
|
||||||
ui cli.Ui
|
resourcesLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ terraform.Hook = (*UiHook)(nil)
|
var _ terraform.Hook = (*UiHook)(nil)
|
||||||
|
@ -63,8 +68,6 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
|
func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation, action plans.Action, priorState, plannedNewState cty.Value) (terraform.HookAction, error) {
|
||||||
h.once.Do(h.init)
|
|
||||||
|
|
||||||
dispAddr := addr.String()
|
dispAddr := addr.String()
|
||||||
if gen != states.CurrentGen {
|
if gen != states.CurrentGen {
|
||||||
dispAddr = fmt.Sprintf("%s (%s)", dispAddr, gen)
|
dispAddr = fmt.Sprintf("%s (%s)", dispAddr, gen)
|
||||||
|
@ -89,7 +92,7 @@ func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation,
|
||||||
default:
|
default:
|
||||||
// We don't expect any other actions in here, so anything else is a
|
// We don't expect any other actions in here, so anything else is a
|
||||||
// bug in the caller but we'll ignore it in order to be robust.
|
// bug in the caller but we'll ignore it in order to be robust.
|
||||||
h.ui.Output(fmt.Sprintf("(Unknown action %s for %s)", action, dispAddr))
|
h.println(fmt.Sprintf("(Unknown action %s for %s)", action, dispAddr))
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,7 +106,7 @@ func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation,
|
||||||
idValue = ""
|
idValue = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s%s[reset]",
|
"[reset][bold]%s: %s%s[reset]",
|
||||||
dispAddr,
|
dispAddr,
|
||||||
operation,
|
operation,
|
||||||
|
@ -121,9 +124,9 @@ func (h *UiHook) PreApply(addr addrs.AbsResourceInstance, gen states.Generation,
|
||||||
done: make(chan struct{}),
|
done: make(chan struct{}),
|
||||||
}
|
}
|
||||||
|
|
||||||
h.l.Lock()
|
h.resourcesLock.Lock()
|
||||||
h.resources[key] = uiState
|
h.resources[key] = uiState
|
||||||
h.l.Unlock()
|
h.resourcesLock.Unlock()
|
||||||
|
|
||||||
// Start goroutine that shows progress
|
// Start goroutine that shows progress
|
||||||
go h.stillApplying(uiState)
|
go h.stillApplying(uiState)
|
||||||
|
@ -138,7 +141,7 @@ func (h *UiHook) stillApplying(state uiResourceState) {
|
||||||
case <-state.DoneCh:
|
case <-state.DoneCh:
|
||||||
return
|
return
|
||||||
|
|
||||||
case <-time.After(h.PeriodicUiTimer):
|
case <-time.After(h.periodicUiTimer):
|
||||||
// Timer up, show status
|
// Timer up, show status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +164,7 @@ func (h *UiHook) stillApplying(state uiResourceState) {
|
||||||
idSuffix = fmt.Sprintf("%s=%s, ", state.IDKey, truncateId(state.IDValue, maxIdLen))
|
idSuffix = fmt.Sprintf("%s=%s, ", state.IDKey, truncateId(state.IDValue, maxIdLen))
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s [%s%s elapsed][reset]",
|
"[reset][bold]%s: %s [%s%s elapsed][reset]",
|
||||||
state.DispAddr,
|
state.DispAddr,
|
||||||
msg,
|
msg,
|
||||||
|
@ -172,17 +175,16 @@ func (h *UiHook) stillApplying(state uiResourceState) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, applyerr error) (terraform.HookAction, error) {
|
func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation, newState cty.Value, applyerr error) (terraform.HookAction, error) {
|
||||||
|
|
||||||
id := addr.String()
|
id := addr.String()
|
||||||
|
|
||||||
h.l.Lock()
|
h.resourcesLock.Lock()
|
||||||
state := h.resources[id]
|
state := h.resources[id]
|
||||||
if state.DoneCh != nil {
|
if state.DoneCh != nil {
|
||||||
close(state.DoneCh)
|
close(state.DoneCh)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(h.resources, id)
|
delete(h.resources, id)
|
||||||
h.l.Unlock()
|
h.resourcesLock.Unlock()
|
||||||
|
|
||||||
var stateIdSuffix string
|
var stateIdSuffix string
|
||||||
if k, v := format.ObjectValueID(newState); k != "" && v != "" {
|
if k, v := format.ObjectValueID(newState); k != "" && v != "" {
|
||||||
|
@ -208,21 +210,17 @@ func (h *UiHook) PostApply(addr addrs.AbsResourceInstance, gen states.Generation
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
colorized := h.Colorize.Color(fmt.Sprintf(
|
colorized := h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: %s after %s%s[reset]",
|
"[reset][bold]%s: %s after %s%s[reset]",
|
||||||
addr, msg, time.Now().Round(time.Second).Sub(state.Start), stateIdSuffix))
|
addr, msg, time.Now().Round(time.Second).Sub(state.Start), stateIdSuffix))
|
||||||
|
|
||||||
h.ui.Output(colorized)
|
h.println(colorized)
|
||||||
|
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PreDiff(addr addrs.AbsResourceInstance, gen states.Generation, priorState, proposedNewState cty.Value) (terraform.HookAction, error) {
|
|
||||||
return terraform.HookActionContinue, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *UiHook) PreProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string) (terraform.HookAction, error) {
|
func (h *UiHook) PreProvisionInstanceStep(addr addrs.AbsResourceInstance, typeName string) (terraform.HookAction, error) {
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: Provisioning with '%s'...[reset]",
|
"[reset][bold]%s: Provisioning with '%s'...[reset]",
|
||||||
addr, typeName,
|
addr, typeName,
|
||||||
)))
|
)))
|
||||||
|
@ -231,7 +229,7 @@ func (h *UiHook) PreProvisionInstanceStep(addr addrs.AbsResourceInstance, typeNa
|
||||||
|
|
||||||
func (h *UiHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, msg string) {
|
func (h *UiHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string, msg string) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
buf.WriteString(h.Colorize.Color("[reset]"))
|
buf.WriteString(h.view.colorize.Color("[reset]"))
|
||||||
|
|
||||||
prefix := fmt.Sprintf("%s (%s): ", addr, typeName)
|
prefix := fmt.Sprintf("%s (%s): ", addr, typeName)
|
||||||
s := bufio.NewScanner(strings.NewReader(msg))
|
s := bufio.NewScanner(strings.NewReader(msg))
|
||||||
|
@ -243,27 +241,23 @@ func (h *UiHook) ProvisionOutput(addr addrs.AbsResourceInstance, typeName string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(strings.TrimSpace(buf.String()))
|
h.println(strings.TrimSpace(buf.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (terraform.HookAction, error) {
|
func (h *UiHook) PreRefresh(addr addrs.AbsResourceInstance, gen states.Generation, priorState cty.Value) (terraform.HookAction, error) {
|
||||||
h.once.Do(h.init)
|
|
||||||
|
|
||||||
var stateIdSuffix string
|
var stateIdSuffix string
|
||||||
if k, v := format.ObjectValueID(priorState); k != "" && v != "" {
|
if k, v := format.ObjectValueID(priorState); k != "" && v != "" {
|
||||||
stateIdSuffix = fmt.Sprintf(" [%s=%s]", k, v)
|
stateIdSuffix = fmt.Sprintf(" [%s=%s]", k, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][bold]%s: Refreshing state...%s",
|
"[reset][bold]%s: Refreshing state...%s",
|
||||||
addr, stateIdSuffix)))
|
addr, stateIdSuffix)))
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PreImportState(addr addrs.AbsResourceInstance, importID string) (terraform.HookAction, error) {
|
func (h *UiHook) PreImportState(addr addrs.AbsResourceInstance, importID string) (terraform.HookAction, error) {
|
||||||
h.once.Do(h.init)
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
|
||||||
"[reset][bold]%s: Importing from ID %q...",
|
"[reset][bold]%s: Importing from ID %q...",
|
||||||
addr, importID,
|
addr, importID,
|
||||||
)))
|
)))
|
||||||
|
@ -271,12 +265,10 @@ func (h *UiHook) PreImportState(addr addrs.AbsResourceInstance, importID string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) PostImportState(addr addrs.AbsResourceInstance, imported []providers.ImportedResource) (terraform.HookAction, error) {
|
func (h *UiHook) PostImportState(addr addrs.AbsResourceInstance, imported []providers.ImportedResource) (terraform.HookAction, error) {
|
||||||
h.once.Do(h.init)
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
|
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
|
||||||
"[reset][bold][green]%s: Import prepared!", addr)))
|
"[reset][bold][green]%s: Import prepared!", addr)))
|
||||||
for _, s := range imported {
|
for _, s := range imported {
|
||||||
h.ui.Output(h.Colorize.Color(fmt.Sprintf(
|
h.println(h.view.colorize.Color(fmt.Sprintf(
|
||||||
"[reset][green] Prepared %s for import",
|
"[reset][green] Prepared %s for import",
|
||||||
s.TypeName,
|
s.TypeName,
|
||||||
)))
|
)))
|
||||||
|
@ -285,19 +277,11 @@ func (h *UiHook) PostImportState(addr addrs.AbsResourceInstance, imported []prov
|
||||||
return terraform.HookActionContinue, nil
|
return terraform.HookActionContinue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *UiHook) init() {
|
// Wrap calls to the view so that concurrent calls do not interleave println.
|
||||||
if h.Colorize == nil {
|
func (h *UiHook) println(s string) {
|
||||||
panic("colorize not given")
|
h.viewLock.Lock()
|
||||||
}
|
defer h.viewLock.Unlock()
|
||||||
if h.PeriodicUiTimer == 0 {
|
h.view.streams.Println(s)
|
||||||
h.PeriodicUiTimer = defaultPeriodicUiTimer
|
|
||||||
}
|
|
||||||
|
|
||||||
h.resources = make(map[string]uiResourceState)
|
|
||||||
|
|
||||||
// Wrap the ui so that it is safe for concurrency regardless of the
|
|
||||||
// underlying reader/writer that is in place.
|
|
||||||
h.ui = &cli.ConcurrentUi{Ui: h.Ui}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// scanLines is basically copied from the Go standard library except
|
// scanLines is basically copied from the Go standard library except
|
|
@ -1,4 +1,4 @@
|
||||||
package command
|
package views
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -6,28 +6,20 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/cli"
|
|
||||||
"github.com/mitchellh/colorstring"
|
|
||||||
"github.com/zclconf/go-cty/cty"
|
"github.com/zclconf/go-cty/cty"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
"github.com/hashicorp/terraform/internal/terminal"
|
||||||
"github.com/hashicorp/terraform/plans"
|
"github.com/hashicorp/terraform/plans"
|
||||||
"github.com/hashicorp/terraform/states"
|
"github.com/hashicorp/terraform/states"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestUiHookPreApply_periodicTimer(t *testing.T) {
|
func TestUiHookPreApply_periodicTimer(t *testing.T) {
|
||||||
ui := cli.NewMockUi()
|
streams, done := terminal.StreamsForTesting(t)
|
||||||
h := &UiHook{
|
view := NewView(streams)
|
||||||
Colorize: &colorstring.Colorize{
|
h := NewUiHook(view)
|
||||||
Colors: colorstring.DefaultColors,
|
h.periodicUiTimer = 1 * time.Second
|
||||||
Disable: true,
|
|
||||||
Reset: true,
|
|
||||||
},
|
|
||||||
Ui: ui,
|
|
||||||
PeriodicUiTimer: 1 * time.Second,
|
|
||||||
}
|
|
||||||
h.init()
|
|
||||||
h.resources = map[string]uiResourceState{
|
h.resources = map[string]uiResourceState{
|
||||||
"data.aws_availability_zones.available": uiResourceState{
|
"data.aws_availability_zones.available": uiResourceState{
|
||||||
Op: uiResourceDestroy,
|
Op: uiResourceDestroy,
|
||||||
|
@ -75,29 +67,23 @@ data.aws_availability_zones.available: Still destroying... [id=2017-03-05 10:56:
|
||||||
data.aws_availability_zones.available: Still destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC, 2s elapsed]
|
data.aws_availability_zones.available: Still destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC, 2s elapsed]
|
||||||
data.aws_availability_zones.available: Still destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC, 3s elapsed]
|
data.aws_availability_zones.available: Still destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC, 3s elapsed]
|
||||||
`
|
`
|
||||||
output := ui.OutputWriter.String()
|
result := done(t)
|
||||||
|
output := result.Stdout()
|
||||||
if output != expectedOutput {
|
if output != expectedOutput {
|
||||||
t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output)
|
t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedErrOutput := ""
|
expectedErrOutput := ""
|
||||||
errOutput := ui.ErrorWriter.String()
|
errOutput := result.Stderr()
|
||||||
if errOutput != expectedErrOutput {
|
if errOutput != expectedErrOutput {
|
||||||
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUiHookPreApply_destroy(t *testing.T) {
|
func TestUiHookPreApply_destroy(t *testing.T) {
|
||||||
ui := cli.NewMockUi()
|
streams, done := terminal.StreamsForTesting(t)
|
||||||
h := &UiHook{
|
view := NewView(streams)
|
||||||
Colorize: &colorstring.Colorize{
|
h := NewUiHook(view)
|
||||||
Colors: colorstring.DefaultColors,
|
|
||||||
Disable: true,
|
|
||||||
Reset: true,
|
|
||||||
},
|
|
||||||
Ui: ui,
|
|
||||||
}
|
|
||||||
h.init()
|
|
||||||
h.resources = map[string]uiResourceState{
|
h.resources = map[string]uiResourceState{
|
||||||
"data.aws_availability_zones.available": uiResourceState{
|
"data.aws_availability_zones.available": uiResourceState{
|
||||||
Op: uiResourceDestroy,
|
Op: uiResourceDestroy,
|
||||||
|
@ -138,30 +124,24 @@ func TestUiHookPreApply_destroy(t *testing.T) {
|
||||||
close(uiState.DoneCh)
|
close(uiState.DoneCh)
|
||||||
<-uiState.done
|
<-uiState.done
|
||||||
|
|
||||||
|
result := done(t)
|
||||||
expectedOutput := "data.aws_availability_zones.available: Destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC]\n"
|
expectedOutput := "data.aws_availability_zones.available: Destroying... [id=2017-03-05 10:56:59.298784526 +0000 UTC]\n"
|
||||||
output := ui.OutputWriter.String()
|
output := result.Stdout()
|
||||||
if output != expectedOutput {
|
if output != expectedOutput {
|
||||||
t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output)
|
t.Fatalf("Output didn't match.\nExpected: %q\nGiven: %q", expectedOutput, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedErrOutput := ""
|
expectedErrOutput := ""
|
||||||
errOutput := ui.ErrorWriter.String()
|
errOutput := result.Stderr()
|
||||||
if errOutput != expectedErrOutput {
|
if errOutput != expectedErrOutput {
|
||||||
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUiHookPostApply_emptyState(t *testing.T) {
|
func TestUiHookPostApply_emptyState(t *testing.T) {
|
||||||
ui := cli.NewMockUi()
|
streams, done := terminal.StreamsForTesting(t)
|
||||||
h := &UiHook{
|
view := NewView(streams)
|
||||||
Colorize: &colorstring.Colorize{
|
h := NewUiHook(view)
|
||||||
Colors: colorstring.DefaultColors,
|
|
||||||
Disable: true,
|
|
||||||
Reset: true,
|
|
||||||
},
|
|
||||||
Ui: ui,
|
|
||||||
}
|
|
||||||
h.init()
|
|
||||||
h.resources = map[string]uiResourceState{
|
h.resources = map[string]uiResourceState{
|
||||||
"data.google_compute_zones.available": uiResourceState{
|
"data.google_compute_zones.available": uiResourceState{
|
||||||
Op: uiResourceDestroy,
|
Op: uiResourceDestroy,
|
||||||
|
@ -187,15 +167,16 @@ func TestUiHookPostApply_emptyState(t *testing.T) {
|
||||||
if action != terraform.HookActionContinue {
|
if action != terraform.HookActionContinue {
|
||||||
t.Fatalf("Expected hook to continue, given: %#v", action)
|
t.Fatalf("Expected hook to continue, given: %#v", action)
|
||||||
}
|
}
|
||||||
|
result := done(t)
|
||||||
|
|
||||||
expectedRegexp := "^data.google_compute_zones.available: Destruction complete after -?[a-z0-9µ.]+\n$"
|
expectedRegexp := "^data.google_compute_zones.available: Destruction complete after -?[a-z0-9µ.]+\n$"
|
||||||
output := ui.OutputWriter.String()
|
output := result.Stdout()
|
||||||
if matched, _ := regexp.MatchString(expectedRegexp, output); !matched {
|
if matched, _ := regexp.MatchString(expectedRegexp, output); !matched {
|
||||||
t.Fatalf("Output didn't match regexp.\nExpected: %q\nGiven: %q", expectedRegexp, output)
|
t.Fatalf("Output didn't match regexp.\nExpected: %q\nGiven: %q", expectedRegexp, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedErrOutput := ""
|
expectedErrOutput := ""
|
||||||
errOutput := ui.ErrorWriter.String()
|
errOutput := result.Stderr()
|
||||||
if errOutput != expectedErrOutput {
|
if errOutput != expectedErrOutput {
|
||||||
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
t.Fatalf("Error output didn't match.\nExpected: %q\nGiven: %q", expectedErrOutput, errOutput)
|
||||||
}
|
}
|
Loading…
Reference in New Issue