From 74afcb4a7fc7876a0f430ba3f5d6aa1232036d2e Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Wed, 14 Feb 2018 14:35:03 -0800 Subject: [PATCH] configs/configload: some loaders can't install modules Originally the hope was to use the afero filesystem abstraction for all loader operations, but since we install modules using go-getter we cannot (without a lot of refactoring) support vfs for installation. The vfs use-case is for reading configuration from plan zip files anyway, and so we have no real reason to support installation into a vfs. For now at least we will just add the possibility that a loader might not be install-capable. At the moment we have no non-install-capable loaders, but we'll add one later once we get to loading configuration from plan files. --- configs/configload/loader.go | 11 ++++++----- configs/configload/loader_install.go | 19 +++++++++++++++++++ configs/configload/module_mgr.go | 7 +++++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/configs/configload/loader.go b/configs/configload/loader.go index fba2441736..06ff27400c 100644 --- a/configs/configload/loader.go +++ b/configs/configload/loader.go @@ -59,11 +59,12 @@ func NewLoader(config *Config) (*Loader, error) { ret := &Loader{ parser: parser, modules: moduleMgr{ - FS: afero.Afero{fs}, - Dir: config.ModulesDir, - Services: config.Services, - Creds: config.Creds, - Registry: reg, + FS: afero.Afero{Fs: fs}, + CanInstall: true, + Dir: config.ModulesDir, + Services: config.Services, + Creds: config.Creds, + Registry: reg, }, } diff --git a/configs/configload/loader_install.go b/configs/configload/loader_install.go index 41ef4224d1..b3e0152391 100644 --- a/configs/configload/loader_install.go +++ b/configs/configload/loader_install.go @@ -38,7 +38,16 @@ import ( // may have wholly or partially completed. Modules must be loaded in order // to find their dependencies, so this function does many of the same checks // as LoadConfig as a side-effect. +// +// This function will panic if called on a loader that cannot install modules. +// Use CanInstallModules to determine if a loader can install modules, or +// refer to the documentation for that method for situations where module +// installation capability is guaranteed. func (l *Loader) InstallModules(rootDir string, upgrade bool, hooks InstallHooks) hcl.Diagnostics { + if !l.CanInstallModules() { + panic(fmt.Errorf("InstallModules called on loader that cannot install modules")) + } + rootMod, diags := l.parser.LoadConfigDir(rootDir) if rootMod == nil { return diags @@ -183,6 +192,16 @@ func (l *Loader) InstallModules(rootDir string, upgrade bool, hooks InstallHooks return diags } +// CanInstallModules returns true if InstallModules can be used with this +// loader. +// +// Loaders created with NewLoader can always install modules. Loaders created +// from plan files (where the configuration is embedded in the plan file itself) +// cannot install modules, because the plan file is read-only. +func (l *Loader) CanInstallModules() bool { + return l.modules.CanInstall +} + func (l *Loader) installLocalModule(req *configs.ModuleRequest, key string, hooks InstallHooks) (*configs.Module, hcl.Diagnostics) { var diags hcl.Diagnostics diff --git a/configs/configload/module_mgr.go b/configs/configload/module_mgr.go index 5856c2ec02..ef17fda7a7 100644 --- a/configs/configload/module_mgr.go +++ b/configs/configload/module_mgr.go @@ -10,6 +10,13 @@ import ( type moduleMgr struct { FS afero.Afero + // CanInstall is true for a module manager that can support installation. + // + // This must be set only if FS is an afero.OsFs, because the installer + // (which uses go-getter) is not aware of the virtual filesystem + // abstraction and will always write into the "real" filesystem. + CanInstall bool + // Dir is the path where descendent modules are (or will be) installed. Dir string