command/init: Support -plugin-dir again

This is a slightly different approach than we used to take for this
option: rather than disabling the installer and causing all future
commands to look elsewhere for plugins, we'll now leave the installer
enabled by constrain it to only look at the given directories.

This is overall simpler because it doesn't require any special tracking
of the plugin directories for subsequent commands. Instead, the selections
file generated by the installer will record the versions it selected from
the specified directories, and we'll link them in to the local cache just
as we would normally so that other commands don't need to do anything
special to select the right plugins in either case.
This commit is contained in:
Martin Atkins 2020-03-31 16:03:07 -07:00
parent f7072a8f29
commit c4fb22863c
2 changed files with 34 additions and 7 deletions

View File

@ -291,7 +291,7 @@ func (c *InitCommand) Run(args []string) int {
}
// Now that we have loaded all modules, check the module tree for missing providers.
providersOutput, providerDiags := c.getProviders(earlyConfig, state, flagUpgrade)
providersOutput, providerDiags := c.getProviders(earlyConfig, state, flagUpgrade, flagPluginPath)
diags = diags.Append(providerDiags)
if providerDiags.HasErrors() {
c.showDiagnostics(diags)
@ -422,7 +422,7 @@ the backend configuration is present and valid.
// Load the complete module tree, and fetch any missing providers.
// This method outputs its own Ui.
func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *states.State, upgrade bool) (output bool, diags tfdiags.Diagnostics) {
func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *states.State, upgrade bool, pluginDirs []string) (output bool, diags tfdiags.Diagnostics) {
// First we'll collect all the provider dependencies we can see in the
// configuration and the state.
reqs, moreDiags := earlyConfig.ProviderRequirements()
@ -435,11 +435,19 @@ func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *state
reqs = reqs.Merge(stateReqs)
}
// TODO: If the user gave at least one -plugin-dir option on the command
// line, we should construct a one-off getproviders.Source that consults
// only those directories and pass that to c.providerInstallerCustomSource
// instead.
inst := c.providerInstaller()
var inst *providercache.Installer
if len(pluginDirs) == 0 {
// By default we use a source that looks for providers in all of the
// standard locations, possibly customized by the user in CLI config.
inst = c.providerInstaller()
} else {
// If the user passes at least one -plugin-dir then that circumvents
// the usual sources and forces Terraform to consult only the given
// directories. Anything not available in one of those directories
// is not available for installation.
source := c.providerCustomLocalDirectorySource(pluginDirs)
inst = c.providerInstallerCustomSource(source)
}
// Because we're currently just streaming a series of events sequentially
// into the terminal, we're showing only a subset of the events to keep

View File

@ -61,6 +61,25 @@ func (m *Meta) providerInstallerCustomSource(source getproviders.Source) *provid
return inst
}
// providerCustomLocalDirectorySource produces a provider source that consults
// only the given local filesystem directories for plugins to install.
//
// This is used to implement the -plugin-dir option for "terraform init", where
// the result of this method is used instead of what would've been returned
// from m.providerInstallSource.
//
// If the given list of directories is empty then the resulting source will
// have no providers available for installation at all.
func (m *Meta) providerCustomLocalDirectorySource(dirs []string) getproviders.Source {
var ret getproviders.MultiSource
for _, dir := range dirs {
ret = append(ret, getproviders.MultiSourceSelector{
Source: getproviders.NewFilesystemMirrorSource(dir),
})
}
return ret
}
// providerLocalCacheDir returns an object representing the
// configuration-specific local cache directory. This is the
// only location consulted for provider plugin packages for Terraform