diff --git a/command/apply_destroy_test.go b/command/apply_destroy_test.go index 376c5e29e..c2d399e72 100644 --- a/command/apply_destroy_test.go +++ b/command/apply_destroy_test.go @@ -33,8 +33,8 @@ func TestApply_destroy(t *testing.T) { c := &ApplyCommand{ Destroy: true, Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -123,8 +123,8 @@ func TestApply_destroyLockedState(t *testing.T) { c := &ApplyCommand{ Destroy: true, Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -155,8 +155,8 @@ func TestApply_destroyPlan(t *testing.T) { c := &ApplyCommand{ Destroy: true, Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -199,8 +199,8 @@ func TestApply_destroyTargeted(t *testing.T) { c := &ApplyCommand{ Destroy: true, Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/apply_test.go b/command/apply_test.go index 5700ade69..0937eee07 100644 --- a/command/apply_test.go +++ b/command/apply_test.go @@ -28,8 +28,8 @@ func TestApply(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -74,8 +74,8 @@ func TestApply_lockedState(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -112,8 +112,8 @@ func TestApply_lockedStateWait(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -188,8 +188,8 @@ func TestApply_parallelism(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(provider), - Ui: ui, + testingOverrides: metaOverridesForProvider(provider), + Ui: ui, }, } @@ -241,8 +241,8 @@ func TestApply_configInvalid(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -276,8 +276,8 @@ func TestApply_defaultState(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -314,8 +314,8 @@ func TestApply_error(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -403,8 +403,8 @@ func TestApply_init(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -460,8 +460,8 @@ func TestApply_input(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -495,8 +495,8 @@ func TestApply_inputPartial(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -535,8 +535,8 @@ func TestApply_noArgs(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -584,8 +584,8 @@ func TestApply_plan(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -630,8 +630,8 @@ func TestApply_plan_backup(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -672,8 +672,8 @@ func TestApply_plan_noBackup(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -729,8 +729,8 @@ func TestApply_plan_remoteState(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -782,8 +782,8 @@ func TestApply_planWithVarFile(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -824,8 +824,8 @@ func TestApply_planVars(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -855,12 +855,10 @@ func TestApply_planNoModuleFiles(t *testing.T) { Module: testModule(t, "apply-plan-no-module"), }) - contextOpts := testCtxConfig(p) - apply := &ApplyCommand{ Meta: Meta{ - ContextOpts: contextOpts, - Ui: new(cli.MockUi), + testingOverrides: metaOverridesForProvider(p), + Ui: new(cli.MockUi), }, } args := []string{ @@ -895,8 +893,8 @@ func TestApply_refresh(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -961,8 +959,8 @@ func TestApply_shutdown(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, ShutdownCh: shutdownCh, @@ -1072,8 +1070,8 @@ func TestApply_state(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1145,8 +1143,8 @@ func TestApply_stateNoExist(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1164,8 +1162,8 @@ func TestApply_sensitiveOutput(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1198,8 +1196,8 @@ func TestApply_stateFuture(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1239,8 +1237,8 @@ func TestApply_statePast(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1260,8 +1258,8 @@ func TestApply_vars(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1303,8 +1301,8 @@ func TestApply_varFile(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1356,8 +1354,8 @@ func TestApply_varFileDefault(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1408,8 +1406,8 @@ func TestApply_varFileDefaultJSON(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1471,8 +1469,8 @@ func TestApply_backup(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1540,8 +1538,8 @@ func TestApply_disableBackup(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1608,8 +1606,8 @@ func TestApply_terraformEnv(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -1663,8 +1661,8 @@ func TestApply_terraformEnvNonDefault(t *testing.T) { ui := new(cli.MockUi) c := &ApplyCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/command_test.go b/command/command_test.go index 21a5a8d41..77cb3e741 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -69,8 +69,8 @@ func testFixturePath(name string) string { return filepath.Join(fixtureDir, name) } -func testCtxConfig(p terraform.ResourceProvider) *terraform.ContextOpts { - return &terraform.ContextOpts{ +func metaOverridesForProvider(p terraform.ResourceProvider) *testingOverrides { + return &testingOverrides{ Providers: map[string]terraform.ResourceProviderFactory{ "test": func() (terraform.ResourceProvider, error) { return p, nil @@ -79,8 +79,8 @@ func testCtxConfig(p terraform.ResourceProvider) *terraform.ContextOpts { } } -func testCtxConfigWithShell(p terraform.ResourceProvider, pr terraform.ResourceProvisioner) *terraform.ContextOpts { - return &terraform.ContextOpts{ +func metaOverridesForProviderAndProvisioner(p terraform.ResourceProvider, pr terraform.ResourceProvisioner) *testingOverrides { + return &testingOverrides{ Providers: map[string]terraform.ResourceProviderFactory{ "test": func() (terraform.ResourceProvider, error) { return p, nil diff --git a/command/console_test.go b/command/console_test.go index 0c9b0f8d4..c30ade9e3 100644 --- a/command/console_test.go +++ b/command/console_test.go @@ -25,8 +25,8 @@ func TestConsole_basic(t *testing.T) { ui := new(cli.MockUi) c := &ConsoleCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -61,8 +61,8 @@ func TestConsole_tfvars(t *testing.T) { ui := new(cli.MockUi) c := &ConsoleCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/debug_json2dot_test.go b/command/debug_json2dot_test.go index 689897ea0..75c1a60bd 100644 --- a/command/debug_json2dot_test.go +++ b/command/debug_json2dot_test.go @@ -30,8 +30,8 @@ func TestDebugJSON2Dot(t *testing.T) { ui := new(cli.MockUi) c := &DebugJSON2DotCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/fmt_test.go b/command/fmt_test.go index 191cd47ee..3fc34e196 100644 --- a/command/fmt_test.go +++ b/command/fmt_test.go @@ -22,8 +22,8 @@ func TestFmt_errorReporting(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -43,8 +43,8 @@ func TestFmt_tooManyArgs(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -82,8 +82,8 @@ func TestFmt_workingDirectory(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -108,8 +108,8 @@ func TestFmt_directoryArg(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -131,8 +131,8 @@ func TestFmt_stdinArg(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, input: input, } @@ -158,8 +158,8 @@ func TestFmt_nonDefaultOptions(t *testing.T) { ui := new(cli.MockUi) c := &FmtCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/get_test.go b/command/get_test.go index b93415192..69980db05 100644 --- a/command/get_test.go +++ b/command/get_test.go @@ -15,9 +15,9 @@ func TestGet(t *testing.T) { ui := new(cli.MockUi) c := &GetCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, - dataDir: tempDir(t), + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + dataDir: tempDir(t), }, } @@ -41,9 +41,9 @@ func TestGet_multipleArgs(t *testing.T) { ui := new(cli.MockUi) c := &GetCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, - dataDir: tempDir(t), + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + dataDir: tempDir(t), }, } @@ -69,9 +69,9 @@ func TestGet_noArgs(t *testing.T) { ui := new(cli.MockUi) c := &GetCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, - dataDir: tempDir(t), + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + dataDir: tempDir(t), }, } @@ -96,9 +96,9 @@ func TestGet_update(t *testing.T) { ui := new(cli.MockUi) c := &GetCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, - dataDir: tempDir(t), + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, + dataDir: tempDir(t), }, } diff --git a/command/graph_test.go b/command/graph_test.go index 6eabc29b3..cf6eaab2b 100644 --- a/command/graph_test.go +++ b/command/graph_test.go @@ -16,8 +16,8 @@ func TestGraph(t *testing.T) { ui := new(cli.MockUi) c := &GraphCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -38,8 +38,8 @@ func TestGraph_multipleArgs(t *testing.T) { ui := new(cli.MockUi) c := &GraphCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -65,8 +65,8 @@ func TestGraph_noArgs(t *testing.T) { ui := new(cli.MockUi) c := &GraphCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -105,8 +105,8 @@ func TestGraph_plan(t *testing.T) { ui := new(cli.MockUi) c := &GraphCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/import_test.go b/command/import_test.go index 82d2d5be9..5b8838ccb 100644 --- a/command/import_test.go +++ b/command/import_test.go @@ -15,8 +15,8 @@ func TestImport(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -55,8 +55,8 @@ func TestImport_providerConfig(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -111,8 +111,8 @@ func TestImport_providerConfigDisable(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -168,8 +168,8 @@ func TestImport_providerConfigWithVar(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -225,8 +225,8 @@ func TestImport_providerConfigWithVarDefault(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -281,8 +281,8 @@ func TestImport_providerConfigWithVarFile(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -335,7 +335,7 @@ func TestRefresh_badState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -366,7 +366,7 @@ func TestRefresh_cwd(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -438,7 +438,7 @@ func TestRefresh_defaultState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -510,7 +510,7 @@ func TestRefresh_futureState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -553,7 +553,7 @@ func TestRefresh_pastState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -612,7 +612,7 @@ func TestRefresh_outPath(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -687,7 +687,7 @@ func TestRefresh_var(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -717,7 +717,7 @@ func TestRefresh_varFile(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -752,7 +752,7 @@ func TestRefresh_varFileDefault(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -802,7 +802,7 @@ func TestRefresh_varsUnset(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -842,7 +842,7 @@ func TestRefresh_backup(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -927,7 +927,7 @@ func TestRefresh_disableBackup(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -992,7 +992,7 @@ func TestRefresh_displaysOutputs(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), + testingOverrides: metaOverridesForProvider(p), Ui: ui, }, } @@ -1021,8 +1021,8 @@ func TestImport_customProvider(t *testing.T) { ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/init_test.go b/command/init_test.go index eea5797c1..5cc5c008e 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -17,8 +17,8 @@ func TestInit(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -54,8 +54,8 @@ func TestInit_cwd(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -81,8 +81,8 @@ func TestInit_empty(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -96,8 +96,8 @@ func TestInit_multipleArgs(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -134,8 +134,8 @@ func TestInit_dstInSrc(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -162,8 +162,8 @@ func TestInit_get(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -189,8 +189,8 @@ func TestInit_copyGet(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -222,8 +222,8 @@ func TestInit_backend(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -248,8 +248,8 @@ func TestInit_backendUnset(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -273,8 +273,8 @@ func TestInit_backendUnset(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -301,8 +301,8 @@ func TestInit_backendConfigFile(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -333,8 +333,8 @@ func TestInit_backendConfigFileChange(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -360,8 +360,8 @@ func TestInit_backendConfigKV(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -387,8 +387,8 @@ func TestInit_copyBackendDst(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -426,8 +426,8 @@ func TestInit_backendReinitWithExtra(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -474,8 +474,8 @@ func TestInit_backendReinitConfigToExtra(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -518,8 +518,8 @@ func TestInit_inputFalse(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -546,7 +546,7 @@ func TestInit_remoteState(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), + testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, }, } @@ -582,7 +582,7 @@ func TestInit_remoteStateSubdir(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), + testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, }, } @@ -626,7 +626,7 @@ func TestInit_remoteStateWithLocal(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), + testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, }, } @@ -664,7 +664,7 @@ func TestInit_remoteStateWithRemote(t *testing.T) { ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), + testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, }, } diff --git a/command/meta.go b/command/meta.go index 0b9375f72..40d13aa1e 100644 --- a/command/meta.go +++ b/command/meta.go @@ -32,9 +32,10 @@ type Meta struct { // command with a Meta field. These are expected to be set externally // (not from within the command itself). - Color bool // True if output should be colored - ContextOpts *terraform.ContextOpts // Opts copied to initialize - Ui cli.Ui // Ui for output + Color bool // True if output should be colored + GlobalPluginDirs []string // Additional paths to search for plugins + PluginOverrides *PluginOverrides // legacy overrides from .terraformrc file + Ui cli.Ui // Ui for output // ExtraHooks are extra hooks to add to the context. ExtraHooks []terraform.Hook @@ -46,6 +47,9 @@ type Meta struct { // Modify the data directory location. Defaults to DefaultDataDir dataDir string + // Override certain behavior for tests within this package + testingOverrides *testingOverrides + //---------------------------------------------------------- // Private: do not set these //---------------------------------------------------------- @@ -109,6 +113,16 @@ type Meta struct { reconfigure bool } +type PluginOverrides struct { + Providers map[string]string + Provisioners map[string]string +} + +type testingOverrides struct { + Providers map[string]terraform.ResourceProviderFactory + Provisioners map[string]terraform.ResourceProvisionerFactory +} + // initStatePaths is used to initialize the default values for // statePath, stateOutPath, and backupPath func (m *Meta) initStatePaths() { @@ -199,14 +213,7 @@ func (m *Meta) StdinPiped() bool { // context with the settings from this Meta. func (m *Meta) contextOpts() *terraform.ContextOpts { var opts terraform.ContextOpts - if v := m.ContextOpts; v != nil { - opts = *v - } - opts.Hooks = []terraform.Hook{m.uiHook(), &terraform.DebugHook{}} - if m.ContextOpts != nil { - opts.Hooks = append(opts.Hooks, m.ContextOpts.Hooks...) - } opts.Hooks = append(opts.Hooks, m.ExtraHooks...) vs := make(map[string]interface{}) @@ -226,6 +233,17 @@ func (m *Meta) contextOpts() *terraform.ContextOpts { opts.Parallelism = m.parallelism opts.Shadow = m.shadow + // If testingOverrides are set, we'll skip the plugin discovery process + // and just work with what we've been given, thus allowing the tests + // to provide mock providers and provisioners. + if m.testingOverrides != nil { + opts.Providers = m.testingOverrides.Providers + opts.Provisioners = m.testingOverrides.Provisioners + } else { + opts.Providers = m.providerFactories() + opts.Provisioners = m.provisionerFactories() + } + opts.Meta = &terraform.ContextMeta{ Env: m.Env(), } diff --git a/command/output_test.go b/command/output_test.go index 01f5c034e..298cd8444 100644 --- a/command/output_test.go +++ b/command/output_test.go @@ -31,8 +31,8 @@ func TestOutput(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -79,8 +79,8 @@ func TestModuleOutput(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -129,8 +129,8 @@ func TestModuleOutputs(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -177,8 +177,8 @@ func TestOutput_nestedListAndMap(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -216,8 +216,8 @@ func TestOutput_json(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -256,8 +256,8 @@ func TestMissingModuleOutput(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -292,8 +292,8 @@ func TestOutput_badVar(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -330,8 +330,8 @@ func TestOutput_blank(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -355,8 +355,8 @@ func TestOutput_manyArgs(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -373,8 +373,8 @@ func TestOutput_noArgs(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -391,8 +391,8 @@ func TestOutput_noState(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -420,8 +420,8 @@ func TestOutput_noVars(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -480,8 +480,8 @@ func TestOutput_stateDefault(t *testing.T) { ui := new(cli.MockUi) c := &OutputCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/plan_test.go b/command/plan_test.go index 6fd7d20cf..c0f8f98d1 100644 --- a/command/plan_test.go +++ b/command/plan_test.go @@ -28,8 +28,8 @@ func TestPlan(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -61,8 +61,8 @@ func TestPlan_lockedState(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -89,8 +89,8 @@ func TestPlan_plan(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -128,8 +128,8 @@ func TestPlan_destroy(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -165,8 +165,8 @@ func TestPlan_noState(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -205,8 +205,8 @@ func TestPlan_outPath(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -262,8 +262,8 @@ func TestPlan_outPathNoChange(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -318,8 +318,8 @@ func TestPlan_outBackend(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -382,8 +382,8 @@ func TestPlan_outBackendLegacy(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -412,8 +412,8 @@ func TestPlan_refresh(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -450,8 +450,8 @@ func TestPlan_state(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -506,8 +506,8 @@ func TestPlan_stateDefault(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -535,8 +535,8 @@ func TestPlan_stateFuture(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -576,8 +576,8 @@ func TestPlan_statePast(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -608,8 +608,8 @@ func TestPlan_validate(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -632,8 +632,8 @@ func TestPlan_vars(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -676,8 +676,8 @@ func TestPlan_varsUnset(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -702,8 +702,8 @@ func TestPlan_varFile(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -752,8 +752,8 @@ func TestPlan_varFileDefault(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -795,8 +795,8 @@ func TestPlan_detailedExitcode(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -820,8 +820,8 @@ func TestPlan_detailedExitcode_emptyDiff(t *testing.T) { ui := new(cli.MockUi) c := &PlanCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/plugins.go b/command/plugins.go new file mode 100644 index 000000000..113378db0 --- /dev/null +++ b/command/plugins.go @@ -0,0 +1,163 @@ +package command + +import ( + "log" + "os/exec" + "strings" + + plugin "github.com/hashicorp/go-plugin" + tfplugin "github.com/hashicorp/terraform/plugin" + "github.com/hashicorp/terraform/plugin/discovery" + "github.com/hashicorp/terraform/terraform" +) + +func (m *Meta) providerFactories() map[string]terraform.ResourceProviderFactory { + var dirs []string + + // When searching the following directories, earlier entries get precedence + // if the same plugin version is found twice, but newer versions will + // always get preference below regardless of where they are coming from. + // TODO: Add auto-install dir, default vendor dir and optional override + // vendor dir(s). + dirs = append(dirs, ".") + dirs = append(dirs, m.GlobalPluginDirs...) + + plugins := discovery.FindPlugins("provider", dirs) + plugins, _ = plugins.ValidateVersions() + + // For now our goal is to just find the latest version of each plugin + // we have on the system, emulating our pre-versioning behavior. + // TODO: Reorganize how providers are handled so that we can use + // version constraints from configuration to select which plugins + // we will use when multiple are available. + + factories := make(map[string]terraform.ResourceProviderFactory) + + // Wire up the internal provisioners first. These might be overridden + // by discovered providers below. + for name := range InternalProviders { + client, err := internalPluginClient("provider", name) + if err != nil { + log.Printf("[WARN] failed to build command line for internal plugin %q: %s", name, err) + continue + } + factories[name] = providerFactory(client) + } + + byName := plugins.ByName() + for name, metas := range byName { + // Since we validated versions above and we partitioned the sets + // by name, we're guaranteed that the metas in our set all have + // valid versions and that there's at least one meta. + newest := metas.Newest() + client := newest.Client() + factories[name] = providerFactory(client) + } + + return factories +} + +func (m *Meta) provisionerFactories() map[string]terraform.ResourceProvisionerFactory { + var dirs []string + + // When searching the following directories, earlier entries get precedence + // if the same plugin version is found twice, but newer versions will + // always get preference below regardless of where they are coming from. + // + // NOTE: Currently we don't use versioning for provisioners, so the + // version handling here is just the minimum required to be able to use + // the plugin discovery package. All provisioner plugins should always + // be versionless, which we treat as version 0.0.0 here. + dirs = append(dirs, ".") + dirs = append(dirs, m.GlobalPluginDirs...) + + plugins := discovery.FindPlugins("provisioner", dirs) + plugins, _ = plugins.ValidateVersions() + + // For now our goal is to just find the latest version of each plugin + // we have on the system. All provisioners should be at version 0.0.0 + // currently, so there should actually only be one instance of each plugin + // name here, even though the discovery interface forces us to pretend + // that might not be true. + + factories := make(map[string]terraform.ResourceProvisionerFactory) + + // Wire up the internal provisioners first. These might be overridden + // by discovered provisioners below. + for name := range InternalProvisioners { + client, err := internalPluginClient("provisioner", name) + if err != nil { + log.Printf("[WARN] failed to build command line for internal plugin %q: %s", name, err) + continue + } + factories[name] = provisionerFactory(client) + } + + byName := plugins.ByName() + for name, metas := range byName { + // Since we validated versions above and we partitioned the sets + // by name, we're guaranteed that the metas in our set all have + // valid versions and that there's at least one meta. + newest := metas.Newest() + client := newest.Client() + factories[name] = provisionerFactory(client) + } + + return factories +} + +func internalPluginClient(kind, name string) (*plugin.Client, error) { + cmdLine, err := BuildPluginCommandString(kind, name) + if err != nil { + return nil, err + } + + // See the docstring for BuildPluginCommandString for why we need to do + // this split here. + cmdArgv := strings.Split(cmdLine, TFSPACE) + + cfg := &plugin.ClientConfig{ + Cmd: exec.Command(cmdArgv[0], cmdArgv[1:]...), + HandshakeConfig: tfplugin.Handshake, + Managed: true, + Plugins: tfplugin.PluginMap, + } + + return plugin.NewClient(cfg), nil +} + +func providerFactory(client *plugin.Client) terraform.ResourceProviderFactory { + return func() (terraform.ResourceProvider, error) { + // Request the RPC client so we can get the provider + // so we can build the actual RPC-implemented provider. + rpcClient, err := client.Client() + if err != nil { + return nil, err + } + + raw, err := rpcClient.Dispense(tfplugin.ProviderPluginName) + if err != nil { + return nil, err + } + + return raw.(terraform.ResourceProvider), nil + } +} + +func provisionerFactory(client *plugin.Client) terraform.ResourceProvisionerFactory { + return func() (terraform.ResourceProvisioner, error) { + // Request the RPC client so we can get the provisioner + // so we can build the actual RPC-implemented provisioner. + rpcClient, err := client.Client() + if err != nil { + return nil, err + } + + raw, err := rpcClient.Dispense(tfplugin.ProvisionerPluginName) + if err != nil { + return nil, err + } + + return raw.(terraform.ResourceProvisioner), nil + } +} diff --git a/command/push_test.go b/command/push_test.go index 4afeba3b3..473a31843 100644 --- a/command/push_test.go +++ b/command/push_test.go @@ -40,8 +40,8 @@ func TestPush_good(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -101,8 +101,8 @@ func TestPush_goodBackendInit(t *testing.T) { ui = new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -148,8 +148,8 @@ func TestPush_noUploadModules(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -168,8 +168,8 @@ func TestPush_noUploadModules(t *testing.T) { ui := new(cli.MockUi) c := &GetCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -238,8 +238,8 @@ func TestPush_input(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -297,8 +297,8 @@ func TestPush_inputPartial(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -367,8 +367,8 @@ func TestPush_localOverride(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -446,8 +446,8 @@ func TestPush_remoteOverride(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -537,8 +537,8 @@ func TestPush_preferAtlas(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -613,8 +613,8 @@ func TestPush_tfvars(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -688,8 +688,8 @@ func TestPush_name(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, client: client, @@ -716,8 +716,8 @@ func TestPush_noState(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -801,8 +801,8 @@ func TestPush_plan(t *testing.T) { ui := new(cli.MockUi) c := &PushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/refresh_test.go b/command/refresh_test.go index 12241e809..c53c84bd3 100644 --- a/command/refresh_test.go +++ b/command/refresh_test.go @@ -22,8 +22,8 @@ func TestRefresh(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -71,8 +71,8 @@ func TestRefresh_empty(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -105,8 +105,8 @@ func TestRefresh_lockedState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -145,8 +145,8 @@ func TestRefresh_cwd(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -217,8 +217,8 @@ func TestRefresh_defaultState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -290,8 +290,8 @@ func TestRefresh_futureState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -333,8 +333,8 @@ func TestRefresh_pastState(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -392,8 +392,8 @@ func TestRefresh_outPath(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -467,8 +467,8 @@ func TestRefresh_var(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -497,8 +497,8 @@ func TestRefresh_varFile(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -532,8 +532,8 @@ func TestRefresh_varFileDefault(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -582,8 +582,8 @@ func TestRefresh_varsUnset(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -622,8 +622,8 @@ func TestRefresh_backup(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -707,8 +707,8 @@ func TestRefresh_disableBackup(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -776,8 +776,8 @@ func TestRefresh_displaysOutputs(t *testing.T) { ui := new(cli.MockUi) c := &RefreshCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/show_test.go b/command/show_test.go index ad5c52f88..dfcb4ac7c 100644 --- a/command/show_test.go +++ b/command/show_test.go @@ -16,8 +16,8 @@ func TestShow(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -61,8 +61,8 @@ func TestShow_noArgs(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -93,8 +93,8 @@ func TestShow_noArgsNoState(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -112,8 +112,8 @@ func TestShow_plan(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -138,8 +138,8 @@ func TestShow_noArgsRemoteState(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } @@ -162,8 +162,8 @@ func TestShow_state(t *testing.T) { ui := new(cli.MockUi) c := &ShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(testProvider()), - Ui: ui, + testingOverrides: metaOverridesForProvider(testProvider()), + Ui: ui, }, } diff --git a/command/state_list_test.go b/command/state_list_test.go index 86c4f7194..4c484f09b 100644 --- a/command/state_list_test.go +++ b/command/state_list_test.go @@ -17,8 +17,8 @@ func TestStateList(t *testing.T) { ui := new(cli.MockUi) c := &StateListCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -48,8 +48,8 @@ func TestStateList_backendState(t *testing.T) { ui := new(cli.MockUi) c := &StateListCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -74,8 +74,8 @@ func TestStateList_noState(t *testing.T) { ui := new(cli.MockUi) c := &StateListCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/state_mv_test.go b/command/state_mv_test.go index d479b4ccb..983d67b8d 100644 --- a/command/state_mv_test.go +++ b/command/state_mv_test.go @@ -47,8 +47,8 @@ func TestStateMv(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -114,8 +114,8 @@ func TestStateMv_backupExplicit(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -169,8 +169,8 @@ func TestStateMv_stateOutNew(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -241,8 +241,8 @@ func TestStateMv_stateOutExisting(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -282,8 +282,8 @@ func TestStateMv_noState(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -343,8 +343,8 @@ func TestStateMv_stateOutNew_count(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -521,8 +521,8 @@ func TestStateMv_stateOutNew_largeCount(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -602,8 +602,8 @@ func TestStateMv_stateOutNew_nestedModule(t *testing.T) { ui := new(cli.MockUi) c := &StateMvCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/state_pull_test.go b/command/state_pull_test.go index ac022d726..c93f4e43c 100644 --- a/command/state_pull_test.go +++ b/command/state_pull_test.go @@ -21,8 +21,8 @@ func TestStatePull(t *testing.T) { ui := new(cli.MockUi) c := &StatePullCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -46,8 +46,8 @@ func TestStatePull_noState(t *testing.T) { ui := new(cli.MockUi) c := &StatePullCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/state_push_test.go b/command/state_push_test.go index 10f1718a9..2e2e8700f 100644 --- a/command/state_push_test.go +++ b/command/state_push_test.go @@ -23,8 +23,8 @@ func TestStatePush_empty(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -52,8 +52,8 @@ func TestStatePush_replaceMatch(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -88,8 +88,8 @@ func TestStatePush_replaceMatchStdin(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -117,8 +117,8 @@ func TestStatePush_lineageMismatch(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -146,8 +146,8 @@ func TestStatePush_serialNewer(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -175,8 +175,8 @@ func TestStatePush_serialOlder(t *testing.T) { ui := new(cli.MockUi) c := &StatePushCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/state_rm_test.go b/command/state_rm_test.go index bb3734502..22256366c 100644 --- a/command/state_rm_test.go +++ b/command/state_rm_test.go @@ -47,8 +47,8 @@ func TestStateRm(t *testing.T) { ui := new(cli.MockUi) c := &StateRmCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -113,8 +113,8 @@ func TestStateRm_backupExplicit(t *testing.T) { ui := new(cli.MockUi) c := &StateRmCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -147,8 +147,8 @@ func TestStateRm_noState(t *testing.T) { ui := new(cli.MockUi) c := &StateRmCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/state_show_test.go b/command/state_show_test.go index 9e0ede396..e2cd96d38 100644 --- a/command/state_show_test.go +++ b/command/state_show_test.go @@ -35,8 +35,8 @@ func TestStateShow(t *testing.T) { ui := new(cli.MockUi) c := &StateShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -93,8 +93,8 @@ func TestStateShow_multi(t *testing.T) { ui := new(cli.MockUi) c := &StateShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -115,8 +115,8 @@ func TestStateShow_noState(t *testing.T) { ui := new(cli.MockUi) c := &StateShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -135,8 +135,8 @@ func TestStateShow_emptyState(t *testing.T) { ui := new(cli.MockUi) c := &StateShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } @@ -164,8 +164,8 @@ func TestStateShow_emptyStateWithModule(t *testing.T) { ui := new(cli.MockUi) c := &StateShowCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/command/unlock_test.go b/command/unlock_test.go index 892947afb..342df3b67 100644 --- a/command/unlock_test.go +++ b/command/unlock_test.go @@ -35,8 +35,8 @@ func TestUnlock(t *testing.T) { ui := new(cli.MockUi) c := &UnlockCommand{ Meta: Meta{ - ContextOpts: testCtxConfig(p), - Ui: ui, + testingOverrides: metaOverridesForProvider(p), + Ui: ui, }, } diff --git a/commands.go b/commands.go index 409f4d85d..c4dca2d67 100644 --- a/commands.go +++ b/commands.go @@ -30,9 +30,10 @@ func init() { } meta := command.Meta{ - Color: true, - ContextOpts: &ContextOpts, - Ui: Ui, + Color: true, + GlobalPluginDirs: globalPluginDirs(), + PluginOverrides: &PluginOverrides, + Ui: Ui, } // The command list is included in the terraform -help diff --git a/config.go b/config.go index d0df909a9..d9391c3ce 100644 --- a/config.go +++ b/config.go @@ -6,17 +6,9 @@ import ( "io/ioutil" "log" "os" - "os/exec" - "path/filepath" - "strings" - "github.com/hashicorp/go-plugin" "github.com/hashicorp/hcl" "github.com/hashicorp/terraform/command" - tfplugin "github.com/hashicorp/terraform/plugin" - "github.com/hashicorp/terraform/terraform" - "github.com/kardianos/osext" - "github.com/mitchellh/cli" ) // Config is the structure of the configuration for the Terraform CLI. @@ -35,8 +27,9 @@ type Config struct { // can be overridden by user configurations. var BuiltinConfig Config -// ContextOpts are the global ContextOpts we use to initialize the CLI. -var ContextOpts terraform.ContextOpts +// PluginOverrides are paths that override discovered plugins, set from +// the config file. +var PluginOverrides command.PluginOverrides // ConfigFile returns the default path to the configuration file. // @@ -85,88 +78,6 @@ func LoadConfig(path string) (*Config, error) { return &result, nil } -// Discover plugins located on disk, and fall back on plugins baked into the -// Terraform binary. -// -// We look in the following places for plugins: -// -// 1. Terraform configuration path -// 2. Path where Terraform is installed -// 3. Path where Terraform is invoked -// -// Whichever file is discoverd LAST wins. -// -// Finally, we look at the list of plugins compiled into Terraform. If any of -// them has not been found on disk we use the internal version. This allows -// users to add / replace plugins without recompiling the main binary. -func (c *Config) Discover(ui cli.Ui) error { - // Look in ~/.terraform.d/plugins/ - dir, err := ConfigDir() - if err != nil { - log.Printf("[ERR] Error loading config directory: %s", err) - } else { - if err := c.discover(filepath.Join(dir, "plugins")); err != nil { - return err - } - } - - // Next, look in the same directory as the Terraform executable, usually - // /usr/local/bin. If found, this replaces what we found in the config path. - exePath, err := osext.Executable() - if err != nil { - log.Printf("[ERR] Error loading exe directory: %s", err) - } else { - if err := c.discover(filepath.Dir(exePath)); err != nil { - return err - } - } - - // Finally look in the cwd (where we are invoke Terraform). If found, this - // replaces anything we found in the config / install paths. - if err := c.discover("."); err != nil { - return err - } - - // Finally, if we have a plugin compiled into Terraform and we didn't find - // a replacement on disk, we'll just use the internal version. Only do this - // from the main process, or the log output will break the plugin handshake. - if os.Getenv("TF_PLUGIN_MAGIC_COOKIE") == "" { - for name, _ := range command.InternalProviders { - if path, found := c.Providers[name]; found { - // Allow these warnings to be suppressed via TF_PLUGIN_DEV=1 or similar - if os.Getenv("TF_PLUGIN_DEV") == "" { - ui.Warn(fmt.Sprintf("[WARN] %s overrides an internal plugin for %s-provider.\n"+ - " If you did not expect to see this message you will need to remove the old plugin.\n"+ - " See https://www.terraform.io/docs/internals/internal-plugins.html", path, name)) - } - } else { - cmd, err := command.BuildPluginCommandString("provider", name) - if err != nil { - return err - } - c.Providers[name] = cmd - } - } - for name, _ := range command.InternalProvisioners { - if path, found := c.Provisioners[name]; found { - if os.Getenv("TF_PLUGIN_DEV") == "" { - ui.Warn(fmt.Sprintf("[WARN] %s overrides an internal plugin for %s-provisioner.\n"+ - " If you did not expect to see this message you will need to remove the old plugin.\n"+ - " See https://www.terraform.io/docs/internals/internal-plugins.html", path, name)) - } - } else { - cmd, err := command.BuildPluginCommandString("provisioner", name) - if err != nil { - return err - } - c.Provisioners[name] = cmd - } - } - } - - return nil -} - // Merge merges two configurations and returns a third entirely // new configuration with the two merged. func (c1 *Config) Merge(c2 *Config) *Config { @@ -196,173 +107,3 @@ func (c1 *Config) Merge(c2 *Config) *Config { return &result } - -func (c *Config) discover(path string) error { - var err error - - if !filepath.IsAbs(path) { - path, err = filepath.Abs(path) - if err != nil { - return err - } - } - - err = c.discoverSingle( - filepath.Join(path, "terraform-provider-*"), &c.Providers) - if err != nil { - return err - } - - err = c.discoverSingle( - filepath.Join(path, "terraform-provisioner-*"), &c.Provisioners) - if err != nil { - return err - } - - return nil -} - -func (c *Config) discoverSingle(glob string, m *map[string]string) error { - matches, err := filepath.Glob(glob) - if err != nil { - return err - } - - if *m == nil { - *m = make(map[string]string) - } - - for _, match := range matches { - file := filepath.Base(match) - - // If the filename has a ".", trim up to there - if idx := strings.Index(file, "."); idx >= 0 { - file = file[:idx] - } - - // Look for foo-bar-baz. The plugin name is "baz" - parts := strings.SplitN(file, "-", 3) - if len(parts) != 3 { - continue - } - - log.Printf("[DEBUG] Discovered plugin: %s = %s", parts[2], match) - (*m)[parts[2]] = match - } - - return nil -} - -// ProviderFactories returns the mapping of prefixes to -// ResourceProviderFactory that can be used to instantiate a -// binary-based plugin. -func (c *Config) ProviderFactories() map[string]terraform.ResourceProviderFactory { - result := make(map[string]terraform.ResourceProviderFactory) - for k, v := range c.Providers { - result[k] = c.providerFactory(v) - } - - return result -} - -func (c *Config) providerFactory(path string) terraform.ResourceProviderFactory { - // Build the plugin client configuration and init the plugin - var config plugin.ClientConfig - config.Cmd = pluginCmd(path) - config.HandshakeConfig = tfplugin.Handshake - config.Managed = true - config.Plugins = tfplugin.PluginMap - client := plugin.NewClient(&config) - - return func() (terraform.ResourceProvider, error) { - // Request the RPC client so we can get the provider - // so we can build the actual RPC-implemented provider. - rpcClient, err := client.Client() - if err != nil { - return nil, err - } - - raw, err := rpcClient.Dispense(tfplugin.ProviderPluginName) - if err != nil { - return nil, err - } - - return raw.(terraform.ResourceProvider), nil - } -} - -// ProvisionerFactories returns the mapping of prefixes to -// ResourceProvisionerFactory that can be used to instantiate a -// binary-based plugin. -func (c *Config) ProvisionerFactories() map[string]terraform.ResourceProvisionerFactory { - result := make(map[string]terraform.ResourceProvisionerFactory) - for k, v := range c.Provisioners { - result[k] = c.provisionerFactory(v) - } - - return result -} - -func (c *Config) provisionerFactory(path string) terraform.ResourceProvisionerFactory { - // Build the plugin client configuration and init the plugin - var config plugin.ClientConfig - config.HandshakeConfig = tfplugin.Handshake - config.Cmd = pluginCmd(path) - config.Managed = true - config.Plugins = tfplugin.PluginMap - client := plugin.NewClient(&config) - - return func() (terraform.ResourceProvisioner, error) { - rpcClient, err := client.Client() - if err != nil { - return nil, err - } - - raw, err := rpcClient.Dispense(tfplugin.ProvisionerPluginName) - if err != nil { - return nil, err - } - - return raw.(terraform.ResourceProvisioner), nil - } -} - -func pluginCmd(path string) *exec.Cmd { - cmdPath := "" - - // If the path doesn't contain a separator, look in the same - // directory as the Terraform executable first. - if !strings.ContainsRune(path, os.PathSeparator) { - exePath, err := osext.Executable() - if err == nil { - temp := filepath.Join( - filepath.Dir(exePath), - filepath.Base(path)) - - if _, err := os.Stat(temp); err == nil { - cmdPath = temp - } - } - - // If we still haven't found the executable, look for it - // in the PATH. - if v, err := exec.LookPath(path); err == nil { - cmdPath = v - } - } - - // No plugin binary found, so try to use an internal plugin. - if strings.Contains(path, command.TFSPACE) { - parts := strings.Split(path, command.TFSPACE) - return exec.Command(parts[0], parts[1:]...) - } - - // If we still don't have a path, then just set it to the original - // given path. - if cmdPath == "" { - cmdPath = path - } - - // Build the command to execute the plugin - return exec.Command(cmdPath) -} diff --git a/main.go b/main.go index 237581200..ca4ec7c62 100644 --- a/main.go +++ b/main.go @@ -108,10 +108,6 @@ func wrappedMain() int { // Load the configuration config := BuiltinConfig - if err := config.Discover(Ui); err != nil { - Ui.Error(fmt.Sprintf("Error discovering plugins: %s", err)) - return 1 - } // Load the configuration file if we have one, that can be used to // define extra providers and provisioners. @@ -185,9 +181,9 @@ func wrappedMain() int { HelpWriter: os.Stdout, } - // Initialize the TFConfig settings for the commands... - ContextOpts.Providers = config.ProviderFactories() - ContextOpts.Provisioners = config.ProvisionerFactories() + // Pass in the overriding plugin paths from config + PluginOverrides.Providers = config.Providers + PluginOverrides.Provisioners = config.Provisioners exitCode, err := cliRunner.Run() if err != nil { diff --git a/plugins.go b/plugins.go new file mode 100644 index 000000000..9717724a0 --- /dev/null +++ b/plugins.go @@ -0,0 +1,37 @@ +package main + +import ( + "log" + "path/filepath" + + "github.com/kardianos/osext" +) + +// globalPluginDirs returns directories that should be searched for +// globally-installed plugins (not specific to the current configuration). +// +// Earlier entries in this slice get priority over later when multiple copies +// of the same plugin version are found, but newer versions always override +// older versions where both satisfy the provider version constraints. +func globalPluginDirs() []string { + var ret []string + + // Look in the same directory as the Terraform executable. + // If found, this replaces what we found in the config path. + exePath, err := osext.Executable() + if err != nil { + log.Printf("[ERROR] Error discovering exe directory: %s", err) + } else { + ret = append(ret, filepath.Dir(exePath)) + } + + // Look in ~/.terraform.d/plugins/ , or its equivalent on non-UNIX + dir, err := ConfigDir() + if err != nil { + log.Printf("[ERROR] Error finding global config directory: %s", err) + } else { + ret = append(ret, filepath.Join(dir, "plugins")) + } + + return ret +}