github.com/rebelkathi/terraform-@v0.11.12-beta1/command/init.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"sort"
     8  	"strings"
     9  
    10  	"github.com/posener/complete"
    11  
    12  	multierror "github.com/hashicorp/go-multierror"
    13  	"github.com/hashicorp/terraform/backend"
    14  	"github.com/hashicorp/terraform/config"
    15  	"github.com/hashicorp/terraform/config/module"
    16  	"github.com/hashicorp/terraform/helper/variables"
    17  	"github.com/hashicorp/terraform/plugin"
    18  	"github.com/hashicorp/terraform/plugin/discovery"
    19  	"github.com/hashicorp/terraform/terraform"
    20  )
    21  
    22  // InitCommand is a Command implementation that takes a Terraform
    23  // module and clones it to the working directory.
    24  type InitCommand struct {
    25  	Meta
    26  
    27  	// getPlugins is for the -get-plugins flag
    28  	getPlugins bool
    29  
    30  	// providerInstaller is used to download and install providers that
    31  	// aren't found locally. This uses a discovery.ProviderInstaller instance
    32  	// by default, but it can be overridden here as a way to mock fetching
    33  	// providers for tests.
    34  	providerInstaller discovery.Installer
    35  }
    36  
    37  func (c *InitCommand) Run(args []string) int {
    38  	var flagFromModule string
    39  	var flagBackend, flagGet, flagUpgrade bool
    40  	var flagConfigExtra map[string]interface{}
    41  	var flagPluginPath FlagStringSlice
    42  	var flagVerifyPlugins bool
    43  
    44  	args, err := c.Meta.process(args, false)
    45  	if err != nil {
    46  		return 1
    47  	}
    48  	cmdFlags := c.flagSet("init")
    49  	cmdFlags.BoolVar(&flagBackend, "backend", true, "")
    50  	cmdFlags.Var((*variables.FlagAny)(&flagConfigExtra), "backend-config", "")
    51  	cmdFlags.StringVar(&flagFromModule, "from-module", "", "copy the source of the given module into the directory before init")
    52  	cmdFlags.BoolVar(&flagGet, "get", true, "")
    53  	cmdFlags.BoolVar(&c.getPlugins, "get-plugins", true, "")
    54  	cmdFlags.BoolVar(&c.forceInitCopy, "force-copy", false, "suppress prompts about copying state data")
    55  	cmdFlags.BoolVar(&c.Meta.stateLock, "lock", true, "lock state")
    56  	cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
    57  	cmdFlags.BoolVar(&c.reconfigure, "reconfigure", false, "reconfigure")
    58  	cmdFlags.BoolVar(&flagUpgrade, "upgrade", false, "")
    59  	cmdFlags.Var(&flagPluginPath, "plugin-dir", "plugin directory")
    60  	cmdFlags.BoolVar(&flagVerifyPlugins, "verify-plugins", true, "verify plugins")
    61  
    62  	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
    63  	if err := cmdFlags.Parse(args); err != nil {
    64  		return 1
    65  	}
    66  
    67  	if len(flagPluginPath) > 0 {
    68  		c.pluginPath = flagPluginPath
    69  		c.getPlugins = false
    70  	}
    71  
    72  	// set providerInstaller if we don't have a test version already
    73  	if c.providerInstaller == nil {
    74  		c.providerInstaller = &discovery.ProviderInstaller{
    75  			Dir:                   c.pluginDir(),
    76  			Cache:                 c.pluginCache(),
    77  			PluginProtocolVersion: plugin.Handshake.ProtocolVersion,
    78  			SkipVerify:            !flagVerifyPlugins,
    79  			Ui:                    c.Ui,
    80  		}
    81  	}
    82  
    83  	// Validate the arg count
    84  	args = cmdFlags.Args()
    85  	if len(args) > 1 {
    86  		c.Ui.Error("The init command expects at most one argument.\n")
    87  		cmdFlags.Usage()
    88  		return 1
    89  	}
    90  
    91  	if err := c.storePluginPath(c.pluginPath); err != nil {
    92  		c.Ui.Error(fmt.Sprintf("Error saving -plugin-path values: %s", err))
    93  		return 1
    94  	}
    95  
    96  	// Get our pwd. We don't always need it but always getting it is easier
    97  	// than the logic to determine if it is or isn't needed.
    98  	pwd, err := os.Getwd()
    99  	if err != nil {
   100  		c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
   101  		return 1
   102  	}
   103  
   104  	// If an argument is provided then it overrides our working directory.
   105  	path := pwd
   106  	if len(args) == 1 {
   107  		path = args[0]
   108  	}
   109  
   110  	// This will track whether we outputted anything so that we know whether
   111  	// to output a newline before the success message
   112  	var header bool
   113  
   114  	if flagFromModule != "" {
   115  		src := flagFromModule
   116  
   117  		empty, err := config.IsEmptyDir(path)
   118  		if err != nil {
   119  			c.Ui.Error(fmt.Sprintf("Error validating destination directory: %s", err))
   120  			return 1
   121  		}
   122  		if !empty {
   123  			c.Ui.Error(strings.TrimSpace(errInitCopyNotEmpty))
   124  			return 1
   125  		}
   126  
   127  		c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
   128  			"[reset][bold]Copying configuration[reset] from %q...", src,
   129  		)))
   130  		header = true
   131  
   132  		s := module.NewStorage("", c.Services)
   133  		if err := s.GetModule(path, src); err != nil {
   134  			c.Ui.Error(fmt.Sprintf("Error copying source module: %s", err))
   135  			return 1
   136  		}
   137  	}
   138  
   139  	// If our directory is empty, then we're done. We can't get or setup
   140  	// the backend with an empty directory.
   141  	empty, err := config.IsEmptyDir(path)
   142  	if err != nil {
   143  		c.Ui.Error(fmt.Sprintf("Error checking configuration: %s", err))
   144  		return 1
   145  	}
   146  	if empty {
   147  		c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitEmpty)))
   148  		return 0
   149  	}
   150  
   151  	var back backend.Backend
   152  
   153  	// If we're performing a get or loading the backend, then we perform
   154  	// some extra tasks.
   155  	if flagGet || flagBackend {
   156  		conf, err := c.Config(path)
   157  		if err != nil {
   158  			// Since this may be the user's first ever interaction with Terraform,
   159  			// we'll provide some additional context in this case.
   160  			c.Ui.Error(strings.TrimSpace(errInitConfigError))
   161  			c.showDiagnostics(err)
   162  			return 1
   163  		}
   164  
   165  		// If we requested downloading modules and have modules in the config
   166  		if flagGet && len(conf.Modules) > 0 {
   167  			header = true
   168  
   169  			getMode := module.GetModeGet
   170  			if flagUpgrade {
   171  				getMode = module.GetModeUpdate
   172  				c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
   173  					"[reset][bold]Upgrading modules...")))
   174  			} else {
   175  				c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
   176  					"[reset][bold]Initializing modules...")))
   177  			}
   178  
   179  			if err := getModules(&c.Meta, path, getMode); err != nil {
   180  				c.Ui.Error(fmt.Sprintf(
   181  					"Error downloading modules: %s", err))
   182  				return 1
   183  			}
   184  		}
   185  
   186  		// If we're requesting backend configuration or looking for required
   187  		// plugins, load the backend
   188  		if flagBackend {
   189  			header = true
   190  
   191  			// Only output that we're initializing a backend if we have
   192  			// something in the config. We can be UNSETTING a backend as well
   193  			// in which case we choose not to show this.
   194  			if conf.Terraform != nil && conf.Terraform.Backend != nil {
   195  				c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
   196  					"\n[reset][bold]Initializing the backend...")))
   197  			}
   198  
   199  			opts := &BackendOpts{
   200  				Config:      conf,
   201  				ConfigExtra: flagConfigExtra,
   202  				Init:        true,
   203  			}
   204  			if back, err = c.Backend(opts); err != nil {
   205  				c.Ui.Error(err.Error())
   206  				return 1
   207  			}
   208  		}
   209  	}
   210  
   211  	if back == nil {
   212  		// If we didn't initialize a backend then we'll try to at least
   213  		// instantiate one. This might fail if it wasn't already initalized
   214  		// by a previous run, so we must still expect that "back" may be nil
   215  		// in code that follows.
   216  		back, err = c.Backend(nil)
   217  		if err != nil {
   218  			// This is fine. We'll proceed with no backend, then.
   219  			back = nil
   220  		}
   221  	}
   222  
   223  	var state *terraform.State
   224  
   225  	// If we have a functional backend (either just initialized or initialized
   226  	// on a previous run) we'll use the current state as a potential source
   227  	// of provider dependencies.
   228  	if back != nil {
   229  		sMgr, err := back.State(c.Workspace())
   230  		if err != nil {
   231  			c.Ui.Error(fmt.Sprintf("Error loading state: %s", err))
   232  			return 1
   233  		}
   234  
   235  		if err := sMgr.RefreshState(); err != nil {
   236  			c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err))
   237  			return 1
   238  		}
   239  
   240  		state = sMgr.State()
   241  	}
   242  
   243  	if v := os.Getenv(ProviderSkipVerifyEnvVar); v != "" {
   244  		c.ignorePluginChecksum = true
   245  	}
   246  
   247  	// Now that we have loaded all modules, check the module tree for missing providers.
   248  	err = c.getProviders(path, state, flagUpgrade)
   249  	if err != nil {
   250  		// this function provides its own output
   251  		log.Printf("[ERROR] %s", err)
   252  		return 1
   253  	}
   254  
   255  	// If we outputted information, then we need to output a newline
   256  	// so that our success message is nicely spaced out from prior text.
   257  	if header {
   258  		c.Ui.Output("")
   259  	}
   260  
   261  	c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitSuccess)))
   262  	if !c.RunningInAutomation {
   263  		// If we're not running in an automation wrapper, give the user
   264  		// some more detailed next steps that are appropriate for interactive
   265  		// shell usage.
   266  		c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitSuccessCLI)))
   267  	}
   268  
   269  	return 0
   270  }
   271  
   272  // Load the complete module tree, and fetch any missing providers.
   273  // This method outputs its own Ui.
   274  func (c *InitCommand) getProviders(path string, state *terraform.State, upgrade bool) error {
   275  	mod, diags := c.Module(path)
   276  	if diags.HasErrors() {
   277  		c.showDiagnostics(diags)
   278  		return diags.Err()
   279  	}
   280  
   281  	if err := terraform.CheckStateVersion(state); err != nil {
   282  		diags = diags.Append(err)
   283  		c.showDiagnostics(diags)
   284  		return err
   285  	}
   286  
   287  	if err := terraform.CheckRequiredVersion(mod); err != nil {
   288  		diags = diags.Append(err)
   289  		c.showDiagnostics(diags)
   290  		return err
   291  	}
   292  
   293  	var available discovery.PluginMetaSet
   294  	if upgrade {
   295  		// If we're in upgrade mode, we ignore any auto-installed plugins
   296  		// in "available", causing us to reinstall and possibly upgrade them.
   297  		available = c.providerPluginManuallyInstalledSet()
   298  	} else {
   299  		available = c.providerPluginSet()
   300  	}
   301  
   302  	requirements := terraform.ModuleTreeDependencies(mod, state).AllPluginRequirements()
   303  	if len(requirements) == 0 {
   304  		// nothing to initialize
   305  		return nil
   306  	}
   307  
   308  	c.Ui.Output(c.Colorize().Color(
   309  		"\n[reset][bold]Initializing provider plugins...",
   310  	))
   311  
   312  	missing := c.missingPlugins(available, requirements)
   313  
   314  	var errs error
   315  	if c.getPlugins {
   316  		if len(missing) > 0 {
   317  			c.Ui.Output(fmt.Sprintf("- Checking for available provider plugins on %s...",
   318  				discovery.GetReleaseHost()))
   319  		}
   320  
   321  		for provider, reqd := range missing {
   322  			_, err := c.providerInstaller.Get(provider, reqd.Versions)
   323  
   324  			if err != nil {
   325  				switch err {
   326  				case discovery.ErrorNoSuchProvider:
   327  					c.Ui.Error(fmt.Sprintf(errProviderNotFound, provider, DefaultPluginVendorDir))
   328  				case discovery.ErrorNoSuitableVersion:
   329  					if reqd.Versions.Unconstrained() {
   330  						// This should never happen, but might crop up if we catch
   331  						// the releases server in a weird state where the provider's
   332  						// directory is present but does not yet contain any
   333  						// versions. We'll treat it like ErrorNoSuchProvider, then.
   334  						c.Ui.Error(fmt.Sprintf(errProviderNotFound, provider, DefaultPluginVendorDir))
   335  					} else {
   336  						c.Ui.Error(fmt.Sprintf(errProviderVersionsUnsuitable, provider, reqd.Versions))
   337  					}
   338  				case discovery.ErrorNoVersionCompatible:
   339  					// FIXME: This error message is sub-awesome because we don't
   340  					// have enough information here to tell the user which versions
   341  					// we considered and which versions might be compatible.
   342  					constraint := reqd.Versions.String()
   343  					if constraint == "" {
   344  						constraint = "(any version)"
   345  					}
   346  					c.Ui.Error(fmt.Sprintf(errProviderIncompatible, provider, constraint))
   347  				default:
   348  					c.Ui.Error(fmt.Sprintf(errProviderInstallError, provider, err.Error(), DefaultPluginVendorDir))
   349  				}
   350  
   351  				errs = multierror.Append(errs, err)
   352  			}
   353  		}
   354  
   355  		if errs != nil {
   356  			return errs
   357  		}
   358  	} else if len(missing) > 0 {
   359  		// we have missing providers, but aren't going to try and download them
   360  		var lines []string
   361  		for provider, reqd := range missing {
   362  			if reqd.Versions.Unconstrained() {
   363  				lines = append(lines, fmt.Sprintf("* %s (any version)\n", provider))
   364  			} else {
   365  				lines = append(lines, fmt.Sprintf("* %s (%s)\n", provider, reqd.Versions))
   366  			}
   367  			errs = multierror.Append(errs, fmt.Errorf("missing provider %q", provider))
   368  		}
   369  		sort.Strings(lines)
   370  		c.Ui.Error(fmt.Sprintf(errMissingProvidersNoInstall, strings.Join(lines, ""), DefaultPluginVendorDir))
   371  		return errs
   372  	}
   373  
   374  	// With all the providers downloaded, we'll generate our lock file
   375  	// that ensures the provider binaries remain unchanged until we init
   376  	// again. If anything changes, other commands that use providers will
   377  	// fail with an error instructing the user to re-run this command.
   378  	available = c.providerPluginSet() // re-discover to see newly-installed plugins
   379  
   380  	// internal providers were already filtered out, since we don't need to get them.
   381  	chosen := choosePlugins(available, nil, requirements)
   382  
   383  	digests := map[string][]byte{}
   384  	for name, meta := range chosen {
   385  		digest, err := meta.SHA256()
   386  		if err != nil {
   387  			c.Ui.Error(fmt.Sprintf("failed to read provider plugin %s: %s", meta.Path, err))
   388  			return err
   389  		}
   390  		digests[name] = digest
   391  		if c.ignorePluginChecksum {
   392  			digests[name] = nil
   393  		}
   394  	}
   395  	err := c.providerPluginsLock().Write(digests)
   396  	if err != nil {
   397  		c.Ui.Error(fmt.Sprintf("failed to save provider manifest: %s", err))
   398  		return err
   399  	}
   400  
   401  	{
   402  		// Purge any auto-installed plugins that aren't being used.
   403  		purged, err := c.providerInstaller.PurgeUnused(chosen)
   404  		if err != nil {
   405  			// Failure to purge old plugins is not a fatal error
   406  			c.Ui.Warn(fmt.Sprintf("failed to purge unused plugins: %s", err))
   407  		}
   408  		if purged != nil {
   409  			for meta := range purged {
   410  				log.Printf("[DEBUG] Purged unused %s plugin %s", meta.Name, meta.Path)
   411  			}
   412  		}
   413  	}
   414  
   415  	// If any providers have "floating" versions (completely unconstrained)
   416  	// we'll suggest the user constrain with a pessimistic constraint to
   417  	// avoid implicitly adopting a later major release.
   418  	constraintSuggestions := make(map[string]discovery.ConstraintStr)
   419  	for name, meta := range chosen {
   420  		req := requirements[name]
   421  		if req == nil {
   422  			// should never happen, but we don't want to crash here, so we'll
   423  			// be cautious.
   424  			continue
   425  		}
   426  
   427  		if req.Versions.Unconstrained() && meta.Version != discovery.VersionZero {
   428  			// meta.Version.MustParse is safe here because our "chosen" metas
   429  			// were already filtered for validity of versions.
   430  			constraintSuggestions[name] = meta.Version.MustParse().MinorUpgradeConstraintStr()
   431  		}
   432  	}
   433  	if len(constraintSuggestions) != 0 {
   434  		names := make([]string, 0, len(constraintSuggestions))
   435  		for name := range constraintSuggestions {
   436  			names = append(names, name)
   437  		}
   438  		sort.Strings(names)
   439  
   440  		c.Ui.Output(outputInitProvidersUnconstrained)
   441  		for _, name := range names {
   442  			c.Ui.Output(fmt.Sprintf("* provider.%s: version = %q", name, constraintSuggestions[name]))
   443  		}
   444  	}
   445  
   446  	return nil
   447  }
   448  
   449  func (c *InitCommand) AutocompleteArgs() complete.Predictor {
   450  	return complete.PredictDirs("")
   451  }
   452  
   453  func (c *InitCommand) AutocompleteFlags() complete.Flags {
   454  	return complete.Flags{
   455  		"-backend":        completePredictBoolean,
   456  		"-backend-config": complete.PredictFiles("*.tfvars"), // can also be key=value, but we can't "predict" that
   457  		"-force-copy":     complete.PredictNothing,
   458  		"-from-module":    completePredictModuleSource,
   459  		"-get":            completePredictBoolean,
   460  		"-get-plugins":    completePredictBoolean,
   461  		"-input":          completePredictBoolean,
   462  		"-lock":           completePredictBoolean,
   463  		"-lock-timeout":   complete.PredictAnything,
   464  		"-no-color":       complete.PredictNothing,
   465  		"-plugin-dir":     complete.PredictDirs(""),
   466  		"-reconfigure":    complete.PredictNothing,
   467  		"-upgrade":        completePredictBoolean,
   468  		"-verify-plugins": completePredictBoolean,
   469  	}
   470  }
   471  
   472  func (c *InitCommand) Help() string {
   473  	helpText := `
   474  Usage: terraform init [options] [DIR]
   475  
   476    Initialize a new or existing Terraform working directory by creating
   477    initial files, loading any remote state, downloading modules, etc.
   478  
   479    This is the first command that should be run for any new or existing
   480    Terraform configuration per machine. This sets up all the local data
   481    necessary to run Terraform that is typically not committed to version
   482    control.
   483  
   484    This command is always safe to run multiple times. Though subsequent runs
   485    may give errors, this command will never delete your configuration or
   486    state. Even so, if you have important information, please back it up prior
   487    to running this command, just in case.
   488  
   489    If no arguments are given, the configuration in this working directory
   490    is initialized.
   491  
   492  Options:
   493  
   494    -backend=true        Configure the backend for this configuration.
   495  
   496    -backend-config=path This can be either a path to an HCL file with key/value
   497                         assignments (same format as terraform.tfvars) or a
   498                         'key=value' format. This is merged with what is in the
   499                         configuration file. This can be specified multiple
   500                         times. The backend type must be in the configuration
   501                         itself.
   502  
   503    -force-copy          Suppress prompts about copying state data. This is
   504                         equivalent to providing a "yes" to all confirmation
   505                         prompts.
   506  
   507    -from-module=SOURCE  Copy the contents of the given module into the target
   508                         directory before initialization.
   509  
   510    -get=true            Download any modules for this configuration.
   511  
   512    -get-plugins=true    Download any missing plugins for this configuration.
   513  
   514    -input=true          Ask for input if necessary. If false, will error if
   515                         input was required.
   516  
   517    -lock=true           Lock the state file when locking is supported.
   518  
   519    -lock-timeout=0s     Duration to retry a state lock.
   520  
   521    -no-color            If specified, output won't contain any color.
   522  
   523    -plugin-dir          Directory containing plugin binaries. This overrides all
   524                         default search paths for plugins, and prevents the 
   525                         automatic installation of plugins. This flag can be used
   526                         multiple times.
   527  
   528    -reconfigure         Reconfigure the backend, ignoring any saved
   529                         configuration.
   530  
   531    -upgrade=false       If installing modules (-get) or plugins (-get-plugins),
   532                         ignore previously-downloaded objects and install the
   533                         latest version allowed within configured constraints.
   534  
   535    -verify-plugins=true Verify the authenticity and integrity of automatically
   536                         downloaded plugins.
   537  `
   538  	return strings.TrimSpace(helpText)
   539  }
   540  
   541  func (c *InitCommand) Synopsis() string {
   542  	return "Initialize a Terraform working directory"
   543  }
   544  
   545  const errInitConfigError = `
   546  There are some problems with the configuration, described below.
   547  
   548  The Terraform configuration must be valid before initialization so that
   549  Terraform can determine which modules and providers need to be installed.
   550  `
   551  
   552  const errInitCopyNotEmpty = `
   553  The working directory already contains files. The -from-module option requires
   554  an empty directory into which a copy of the referenced module will be placed.
   555  
   556  To initialize the configuration already in this working directory, omit the
   557  -from-module option.
   558  `
   559  
   560  const outputInitEmpty = `
   561  [reset][bold]Terraform initialized in an empty directory![reset]
   562  
   563  The directory has no Terraform configuration files. You may begin working
   564  with Terraform immediately by creating Terraform configuration files.
   565  `
   566  
   567  const outputInitSuccess = `
   568  [reset][bold][green]Terraform has been successfully initialized![reset][green]
   569  `
   570  
   571  const outputInitSuccessCLI = `[reset][green]
   572  You may now begin working with Terraform. Try running "terraform plan" to see
   573  any changes that are required for your infrastructure. All Terraform commands
   574  should now work.
   575  
   576  If you ever set or change modules or backend configuration for Terraform,
   577  rerun this command to reinitialize your working directory. If you forget, other
   578  commands will detect it and remind you to do so if necessary.
   579  `
   580  
   581  const outputInitProvidersUnconstrained = `
   582  The following providers do not have any version constraints in configuration,
   583  so the latest version was installed.
   584  
   585  To prevent automatic upgrades to new major versions that may contain breaking
   586  changes, it is recommended to add version = "..." constraints to the
   587  corresponding provider blocks in configuration, with the constraint strings
   588  suggested below.
   589  `
   590  
   591  const errProviderNotFound = `
   592  [reset][bold][red]Provider %[1]q not available for installation.[reset][red]
   593  
   594  A provider named %[1]q could not be found in the official repository.
   595  
   596  This may result from mistyping the provider name, or the given provider may
   597  be a third-party provider that cannot be installed automatically.
   598  
   599  In the latter case, the plugin must be installed manually by locating and
   600  downloading a suitable distribution package and placing the plugin's executable
   601  file in the following directory:
   602      %[2]s
   603  
   604  Terraform detects necessary plugins by inspecting the configuration and state.
   605  To view the provider versions requested by each module, run
   606  "terraform providers".
   607  `
   608  
   609  const errProviderVersionsUnsuitable = `
   610  [reset][bold][red]No provider %[1]q plugins meet the constraint %[2]q.[reset][red]
   611  
   612  The version constraint is derived from the "version" argument within the
   613  provider %[1]q block in configuration. Child modules may also apply
   614  provider version constraints. To view the provider versions requested by each
   615  module in the current configuration, run "terraform providers".
   616  
   617  To proceed, the version constraints for this provider must be relaxed by
   618  either adjusting or removing the "version" argument in the provider blocks
   619  throughout the configuration.
   620  `
   621  
   622  const errProviderIncompatible = `
   623  [reset][bold][red]No available provider %[1]q plugins are compatible with this Terraform version.[reset][red]
   624  
   625  From time to time, new Terraform major releases can change the requirements for
   626  plugins such that older plugins become incompatible.
   627  
   628  Terraform checked all of the plugin versions matching the given constraint:
   629      %[2]s
   630  
   631  Unfortunately, none of the suitable versions are compatible with this version
   632  of Terraform. If you have recently upgraded Terraform, it may be necessary to
   633  move to a newer major release of this provider. Alternatively, if you are
   634  attempting to upgrade the provider to a new major version you may need to
   635  also upgrade Terraform to support the new version.
   636  
   637  Consult the documentation for this provider for more information on
   638  compatibility between provider versions and Terraform versions.
   639  `
   640  
   641  const errProviderInstallError = `
   642  [reset][bold][red]Error installing provider %[1]q: %[2]s.[reset][red]
   643  
   644  Terraform analyses the configuration and state and automatically downloads
   645  plugins for the providers used. However, when attempting to download this
   646  plugin an unexpected error occured.
   647  
   648  This may be caused if for some reason Terraform is unable to reach the
   649  plugin repository. The repository may be unreachable if access is blocked
   650  by a firewall.
   651  
   652  If automatic installation is not possible or desirable in your environment,
   653  you may alternatively manually install plugins by downloading a suitable
   654  distribution package and placing the plugin's executable file in the
   655  following directory:
   656      %[3]s
   657  `
   658  
   659  const errMissingProvidersNoInstall = `
   660  [reset][bold][red]Missing required providers.[reset][red]
   661  
   662  The following provider constraints are not met by the currently-installed
   663  provider plugins:
   664  
   665  %[1]s
   666  Terraform can automatically download and install plugins to meet the given
   667  constraints, but this step was skipped due to the use of -get-plugins=false
   668  and/or -plugin-dir on the command line.
   669  
   670  If automatic installation is not possible or desirable in your environment,
   671  you may manually install plugins by downloading a suitable distribution package
   672  and placing the plugin's executable file in one of the directories given in
   673  by -plugin-dir on the command line, or in the following directory if custom
   674  plugin directories are not set:
   675      %[2]s
   676  `