2014-09-27 01:03:39 +02:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
2020-03-24 22:51:55 +01:00
|
|
|
"context"
|
2014-09-27 01:03:39 +02:00
|
|
|
"fmt"
|
2020-05-13 14:48:11 +02:00
|
|
|
"log"
|
2014-09-27 01:03:39 +02:00
|
|
|
"os"
|
2020-04-03 23:55:04 +02:00
|
|
|
"sort"
|
2014-09-27 01:03:39 +02:00
|
|
|
"strings"
|
|
|
|
|
2019-09-10 00:58:44 +02:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
"github.com/hashicorp/terraform-config-inspect/tfconfig"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
"github.com/posener/complete"
|
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
|
2019-09-09 22:59:50 +02:00
|
|
|
"github.com/hashicorp/terraform/addrs"
|
2017-05-03 17:02:47 +02:00
|
|
|
"github.com/hashicorp/terraform/backend"
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
backendInit "github.com/hashicorp/terraform/backend/init"
|
2018-03-28 00:31:05 +02:00
|
|
|
"github.com/hashicorp/terraform/configs"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
"github.com/hashicorp/terraform/configs/configschema"
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/earlyconfig"
|
2020-03-24 22:51:55 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/getproviders"
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/initwd"
|
2020-03-24 22:51:55 +01:00
|
|
|
"github.com/hashicorp/terraform/internal/providercache"
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
"github.com/hashicorp/terraform/states"
|
2018-03-28 00:31:05 +02:00
|
|
|
"github.com/hashicorp/terraform/tfdiags"
|
2020-05-11 19:49:12 +02:00
|
|
|
tfversion "github.com/hashicorp/terraform/version"
|
2014-09-27 01:03:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
// InitCommand is a Command implementation that takes a Terraform
|
|
|
|
// module and clones it to the working directory.
|
|
|
|
type InitCommand struct {
|
|
|
|
Meta
|
2017-05-04 19:01:05 +02:00
|
|
|
|
2017-06-15 21:23:16 +02:00
|
|
|
// getPlugins is for the -get-plugins flag
|
|
|
|
getPlugins bool
|
2014-09-27 01:03:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InitCommand) Run(args []string) int {
|
2017-07-29 00:23:29 +02:00
|
|
|
var flagFromModule string
|
2017-06-15 21:23:16 +02:00
|
|
|
var flagBackend, flagGet, flagUpgrade bool
|
2017-06-15 20:26:12 +02:00
|
|
|
var flagPluginPath FlagStringSlice
|
2017-06-20 17:46:33 +02:00
|
|
|
var flagVerifyPlugins bool
|
2018-03-28 00:31:05 +02:00
|
|
|
flagConfigExtra := newRawFlags("-backend-config")
|
2017-03-21 20:05:51 +01:00
|
|
|
|
2020-04-01 21:01:08 +02:00
|
|
|
args = c.Meta.process(args)
|
2018-11-21 15:35:27 +01:00
|
|
|
cmdFlags := c.Meta.extendedFlagSet("init")
|
2017-01-19 05:50:45 +01:00
|
|
|
cmdFlags.BoolVar(&flagBackend, "backend", true, "")
|
2018-03-28 00:31:05 +02:00
|
|
|
cmdFlags.Var(flagConfigExtra, "backend-config", "")
|
2017-07-29 00:23:29 +02:00
|
|
|
cmdFlags.StringVar(&flagFromModule, "from-module", "", "copy the source of the given module into the directory before init")
|
2017-01-19 05:50:45 +01:00
|
|
|
cmdFlags.BoolVar(&flagGet, "get", true, "")
|
2017-06-15 21:23:16 +02:00
|
|
|
cmdFlags.BoolVar(&c.getPlugins, "get-plugins", true, "")
|
2017-03-21 20:05:51 +01:00
|
|
|
cmdFlags.BoolVar(&c.forceInitCopy, "force-copy", false, "suppress prompts about copying state data")
|
2017-04-01 22:19:59 +02:00
|
|
|
cmdFlags.BoolVar(&c.Meta.stateLock, "lock", true, "lock state")
|
|
|
|
cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
|
2017-04-20 23:26:50 +02:00
|
|
|
cmdFlags.BoolVar(&c.reconfigure, "reconfigure", false, "reconfigure")
|
2017-06-12 23:14:40 +02:00
|
|
|
cmdFlags.BoolVar(&flagUpgrade, "upgrade", false, "")
|
2017-06-15 20:26:12 +02:00
|
|
|
cmdFlags.Var(&flagPluginPath, "plugin-dir", "plugin directory")
|
2017-06-20 17:46:33 +02:00
|
|
|
cmdFlags.BoolVar(&flagVerifyPlugins, "verify-plugins", true, "verify plugins")
|
2014-09-27 01:03:39 +02:00
|
|
|
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
|
|
|
|
if err := cmdFlags.Parse(args); err != nil {
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2018-03-28 00:31:05 +02:00
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
|
2017-06-15 21:23:16 +02:00
|
|
|
if len(flagPluginPath) > 0 {
|
|
|
|
c.pluginPath = flagPluginPath
|
|
|
|
c.getPlugins = false
|
|
|
|
}
|
2017-06-15 20:26:12 +02:00
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
// Validate the arg count
|
2014-09-27 01:03:39 +02:00
|
|
|
args = cmdFlags.Args()
|
2017-06-02 22:13:11 +02:00
|
|
|
if len(args) > 1 {
|
|
|
|
c.Ui.Error("The init command expects at most one argument.\n")
|
2014-09-27 01:03:39 +02:00
|
|
|
cmdFlags.Usage()
|
|
|
|
return 1
|
2017-01-19 05:50:45 +01:00
|
|
|
}
|
|
|
|
|
2017-06-15 20:26:12 +02:00
|
|
|
if err := c.storePluginPath(c.pluginPath); err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error saving -plugin-path values: %s", err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
// Get our pwd. We don't always need it but always getting it is easier
|
|
|
|
// than the logic to determine if it is or isn't needed.
|
|
|
|
pwd, err := os.Getwd()
|
|
|
|
if err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error getting pwd: %s", err))
|
2014-09-27 01:03:39 +02:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2017-07-29 00:23:29 +02:00
|
|
|
// If an argument is provided then it overrides our working directory.
|
2017-06-02 22:13:11 +02:00
|
|
|
path := pwd
|
|
|
|
if len(args) == 1 {
|
|
|
|
path = args[0]
|
2014-09-27 01:03:39 +02:00
|
|
|
}
|
2016-01-20 02:13:19 +01:00
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
// This will track whether we outputted anything so that we know whether
|
|
|
|
// to output a newline before the success message
|
|
|
|
var header bool
|
|
|
|
|
2017-07-29 00:23:29 +02:00
|
|
|
if flagFromModule != "" {
|
|
|
|
src := flagFromModule
|
|
|
|
|
2019-07-18 19:07:10 +02:00
|
|
|
empty, err := configs.IsEmptyDir(path)
|
2017-07-29 00:23:29 +02:00
|
|
|
if err != nil {
|
|
|
|
c.Ui.Error(fmt.Sprintf("Error validating destination directory: %s", err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
if !empty {
|
|
|
|
c.Ui.Error(strings.TrimSpace(errInitCopyNotEmpty))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Ui.Output(c.Colorize().Color(fmt.Sprintf(
|
|
|
|
"[reset][bold]Copying configuration[reset] from %q...", src,
|
|
|
|
)))
|
|
|
|
header = true
|
|
|
|
|
2018-03-28 00:31:05 +02:00
|
|
|
hooks := uiModuleInstallHooks{
|
|
|
|
Ui: c.Ui,
|
|
|
|
ShowLocalPaths: false, // since they are in a weird location for init
|
|
|
|
}
|
|
|
|
|
|
|
|
initDiags := c.initDirFromModule(path, src, hooks)
|
|
|
|
diags = diags.Append(initDiags)
|
|
|
|
if initDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
2017-07-29 00:23:29 +02:00
|
|
|
return 1
|
|
|
|
}
|
2018-03-28 02:22:51 +02:00
|
|
|
|
|
|
|
c.Ui.Output("")
|
2017-07-29 00:23:29 +02:00
|
|
|
}
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
// If our directory is empty, then we're done. We can't get or setup
|
|
|
|
// the backend with an empty directory.
|
2019-07-18 19:07:10 +02:00
|
|
|
empty, err := configs.IsEmptyDir(path)
|
2018-10-31 16:45:03 +01:00
|
|
|
if err != nil {
|
2018-03-28 00:31:05 +02:00
|
|
|
diags = diags.Append(fmt.Errorf("Error checking configuration: %s", err))
|
2014-09-27 01:03:39 +02:00
|
|
|
return 1
|
2018-10-31 16:45:03 +01:00
|
|
|
}
|
|
|
|
if empty {
|
2017-01-19 05:50:45 +01:00
|
|
|
c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitEmpty)))
|
|
|
|
return 0
|
2014-09-27 01:03:39 +02:00
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
// Before we do anything else, we'll try loading configuration with both
|
|
|
|
// our "normal" and "early" configuration codepaths. If early succeeds
|
|
|
|
// while normal fails, that strongly suggests that the configuration is
|
2020-03-19 13:01:16 +01:00
|
|
|
// using syntax that worked in 0.11 but no longer in v0.12.
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
rootMod, confDiags := c.loadSingleModule(path)
|
|
|
|
rootModEarly, earlyConfDiags := c.loadSingleModuleEarly(path)
|
|
|
|
if confDiags.HasErrors() {
|
|
|
|
if earlyConfDiags.HasErrors() {
|
|
|
|
// If both parsers produced errors then we'll assume the config
|
|
|
|
// is _truly_ invalid and produce error messages as normal.
|
2017-10-05 21:00:45 +02:00
|
|
|
// Since this may be the user's first ever interaction with Terraform,
|
|
|
|
// we'll provide some additional context in this case.
|
|
|
|
c.Ui.Error(strings.TrimSpace(errInitConfigError))
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
diags = diags.Append(confDiags)
|
2018-03-28 00:31:05 +02:00
|
|
|
c.showDiagnostics(diags)
|
2014-10-10 02:16:17 +02:00
|
|
|
return 1
|
|
|
|
}
|
2020-03-19 13:01:16 +01:00
|
|
|
// If _only_ the main loader produced errors then that suggests the
|
|
|
|
// configuration is written in 0.11-style syntax. We will return an
|
|
|
|
// error suggesting the user upgrade their config manually or with
|
|
|
|
// Terraform v0.12
|
|
|
|
c.Ui.Error(strings.TrimSpace(errInitConfigErrorMaybeLegacySyntax))
|
2020-05-05 16:08:05 +02:00
|
|
|
c.showDiagnostics(confDiags)
|
2020-03-19 13:01:16 +01:00
|
|
|
return 1
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
}
|
2020-03-19 13:01:16 +01:00
|
|
|
|
|
|
|
// If _only_ the early loader encountered errors then that's unusual
|
|
|
|
// (it should generally be a superset of the normal loader) but we'll
|
|
|
|
// return those errors anyway since otherwise we'll probably get
|
|
|
|
// some weird behavior downstream. Errors from the early loader are
|
|
|
|
// generally not as high-quality since it has less context to work with.
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
if earlyConfDiags.HasErrors() {
|
|
|
|
c.Ui.Error(strings.TrimSpace(errInitConfigError))
|
2020-03-19 13:01:16 +01:00
|
|
|
// Errors from the early loader are generally not as high-quality since
|
|
|
|
// it has less context to work with.
|
|
|
|
diags = diags.Append(confDiags)
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
2017-01-19 05:50:45 +01:00
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
if flagGet {
|
|
|
|
modsOutput, modsDiags := c.getModules(path, rootModEarly, flagUpgrade)
|
|
|
|
diags = diags.Append(modsDiags)
|
|
|
|
if modsDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
if modsOutput {
|
2017-01-19 05:50:45 +01:00
|
|
|
header = true
|
2014-10-01 01:05:40 +02:00
|
|
|
}
|
2017-01-19 05:50:45 +01:00
|
|
|
}
|
2014-10-10 02:16:17 +02:00
|
|
|
|
2020-03-19 13:01:16 +01:00
|
|
|
// With all of the modules (hopefully) installed, we can now try to load the
|
|
|
|
// whole configuration tree.
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
//
|
|
|
|
// Just as above, we'll try loading both with the early and normal config
|
2020-03-19 13:01:16 +01:00
|
|
|
// loaders here. Subsequent work will only use the early config, but loading
|
|
|
|
// both gives us an opportunity to prefer the better error messages from the
|
|
|
|
// normal loader if both fail.
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
earlyConfig, earlyConfDiags := c.loadConfigEarly(path)
|
2020-03-19 13:01:16 +01:00
|
|
|
if earlyConfDiags.HasErrors() {
|
2018-11-10 00:08:39 +01:00
|
|
|
c.Ui.Error(strings.TrimSpace(errInitConfigError))
|
2020-03-19 13:01:16 +01:00
|
|
|
diags = diags.Append(earlyConfDiags)
|
2018-11-10 00:08:39 +01:00
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
2020-03-19 13:01:16 +01:00
|
|
|
|
|
|
|
_, confDiags = c.loadConfig(path)
|
2020-05-12 14:39:12 +02:00
|
|
|
diags = diags.Append(confDiags)
|
2020-03-19 13:01:16 +01:00
|
|
|
if confDiags.HasErrors() {
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
c.Ui.Error(strings.TrimSpace(errInitConfigError))
|
2018-11-10 00:08:39 +01:00
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
2020-03-19 13:01:16 +01:00
|
|
|
// Before we go further, we'll check to make sure none of the modules in the
|
|
|
|
// configuration declare that they don't support this Terraform version, so
|
|
|
|
// we can produce a version-related error message rather than
|
|
|
|
// potentially-confusing downstream errors.
|
|
|
|
versionDiags := initwd.CheckCoreVersionRequirements(earlyConfig)
|
|
|
|
diags = diags.Append(versionDiags)
|
|
|
|
if versionDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
var back backend.Backend
|
|
|
|
if flagBackend {
|
2020-03-19 13:01:16 +01:00
|
|
|
|
|
|
|
be, backendOutput, backendDiags := c.initBackend(rootMod, flagConfigExtra)
|
|
|
|
diags = diags.Append(backendDiags)
|
|
|
|
if backendDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
if backendOutput {
|
|
|
|
header = true
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
}
|
2020-03-19 13:01:16 +01:00
|
|
|
back = be
|
2020-01-07 21:07:06 +01:00
|
|
|
} else {
|
|
|
|
// load the previously-stored backend config
|
|
|
|
be, backendDiags := c.Meta.backendFromState()
|
|
|
|
diags = diags.Append(backendDiags)
|
|
|
|
if backendDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
back = be
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
}
|
|
|
|
|
2017-06-21 19:32:13 +02:00
|
|
|
if back == nil {
|
|
|
|
// If we didn't initialize a backend then we'll try to at least
|
2019-05-29 19:58:04 +02:00
|
|
|
// instantiate one. This might fail if it wasn't already initialized
|
2017-06-21 19:32:13 +02:00
|
|
|
// by a previous run, so we must still expect that "back" may be nil
|
|
|
|
// in code that follows.
|
2018-03-28 00:31:05 +02:00
|
|
|
var backDiags tfdiags.Diagnostics
|
|
|
|
back, backDiags = c.Backend(nil)
|
|
|
|
if backDiags.HasErrors() {
|
2017-06-21 19:32:13 +02:00
|
|
|
// This is fine. We'll proceed with no backend, then.
|
|
|
|
back = nil
|
|
|
|
}
|
2017-06-15 21:23:16 +02:00
|
|
|
}
|
2017-05-03 17:02:47 +02:00
|
|
|
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
var state *states.State
|
2017-06-21 19:32:13 +02:00
|
|
|
|
|
|
|
// If we have a functional backend (either just initialized or initialized
|
|
|
|
// on a previous run) we'll use the current state as a potential source
|
|
|
|
// of provider dependencies.
|
|
|
|
if back != nil {
|
terraform: Ugly huge change to weave in new State and Plan types
Due to how often the state and plan types are referenced throughout
Terraform, there isn't a great way to switch them out gradually. As a
consequence, this huge commit gets us from the old world to a _compilable_
new world, but still has a large number of known test failures due to
key functionality being stubbed out.
The stubs here are for anything that interacts with providers, since we
now need to do the follow-up work to similarly replace the old
terraform.ResourceProvider interface with its replacement in the new
"providers" package. That work, along with work to fix the remaining
failing tests, will follow in subsequent commits.
The aim here was to replace all references to terraform.State and its
downstream types with states.State, terraform.Plan with plans.Plan,
state.State with statemgr.State, and switch to the new implementations of
the state and plan file formats. However, due to the number of times those
types are used, this also ended up affecting numerous other parts of core
such as terraform.Hook, the backend.Backend interface, and most of the CLI
commands.
Just as with 5861dbf3fc49b19587a31816eb06f511ab861bb4 before, I apologize
in advance to the person who inevitably just found this huge commit while
spelunking through the commit history.
2018-08-14 23:24:45 +02:00
|
|
|
sMgr, err := back.StateMgr(c.Workspace())
|
2017-06-21 19:32:13 +02:00
|
|
|
if err != nil {
|
2018-10-31 16:45:03 +01:00
|
|
|
c.Ui.Error(fmt.Sprintf("Error loading state: %s", err))
|
2017-06-21 19:32:13 +02:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := sMgr.RefreshState(); err != nil {
|
2018-10-31 16:45:03 +01:00
|
|
|
c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err))
|
2017-06-21 19:32:13 +02:00
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
state = sMgr.State()
|
2017-06-15 21:23:16 +02:00
|
|
|
}
|
2017-05-03 17:02:47 +02:00
|
|
|
|
2017-07-03 19:59:13 +02:00
|
|
|
if v := os.Getenv(ProviderSkipVerifyEnvVar); v != "" {
|
|
|
|
c.ignorePluginChecksum = true
|
|
|
|
}
|
|
|
|
|
2017-06-21 19:32:13 +02:00
|
|
|
// Now that we have loaded all modules, check the module tree for missing providers.
|
2020-04-01 01:03:07 +02:00
|
|
|
providersOutput, providerDiags := c.getProviders(earlyConfig, state, flagUpgrade, flagPluginPath)
|
2018-03-28 02:22:51 +02:00
|
|
|
diags = diags.Append(providerDiags)
|
|
|
|
if providerDiags.HasErrors() {
|
|
|
|
c.showDiagnostics(diags)
|
2017-06-15 21:23:16 +02:00
|
|
|
return 1
|
2017-05-03 17:02:47 +02:00
|
|
|
}
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
if providersOutput {
|
|
|
|
header = true
|
|
|
|
}
|
2017-05-03 17:02:47 +02:00
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
// If we outputted information, then we need to output a newline
|
|
|
|
// so that our success message is nicely spaced out from prior text.
|
|
|
|
if header {
|
|
|
|
c.Ui.Output("")
|
2014-10-01 01:05:40 +02:00
|
|
|
}
|
2017-01-19 05:50:45 +01:00
|
|
|
|
2018-03-28 02:22:51 +02:00
|
|
|
// If we accumulated any warnings along the way that weren't accompanied
|
|
|
|
// by errors then we'll output them here so that the success message is
|
|
|
|
// still the final thing shown.
|
|
|
|
c.showDiagnostics(diags)
|
2017-01-19 05:50:45 +01:00
|
|
|
c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitSuccess)))
|
2017-09-09 02:14:37 +02:00
|
|
|
if !c.RunningInAutomation {
|
|
|
|
// If we're not running in an automation wrapper, give the user
|
|
|
|
// some more detailed next steps that are appropriate for interactive
|
|
|
|
// shell usage.
|
|
|
|
c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitSuccessCLI)))
|
|
|
|
}
|
2014-09-27 01:03:39 +02:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
func (c *InitCommand) getModules(path string, earlyRoot *tfconfig.Module, upgrade bool) (output bool, diags tfdiags.Diagnostics) {
|
|
|
|
if len(earlyRoot.ModuleCalls) == 0 {
|
|
|
|
// Nothing to do
|
|
|
|
return false, nil
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
if upgrade {
|
|
|
|
c.Ui.Output(c.Colorize().Color(fmt.Sprintf("[reset][bold]Upgrading modules...")))
|
|
|
|
} else {
|
|
|
|
c.Ui.Output(c.Colorize().Color(fmt.Sprintf("[reset][bold]Initializing modules...")))
|
|
|
|
}
|
|
|
|
|
|
|
|
hooks := uiModuleInstallHooks{
|
|
|
|
Ui: c.Ui,
|
|
|
|
ShowLocalPaths: true,
|
|
|
|
}
|
|
|
|
instDiags := c.installModules(path, upgrade, hooks)
|
|
|
|
diags = diags.Append(instDiags)
|
|
|
|
|
|
|
|
// Since module installer has modified the module manifest on disk, we need
|
|
|
|
// to refresh the cache of it in the loader.
|
|
|
|
if c.configLoader != nil {
|
|
|
|
if err := c.configLoader.RefreshModules(); err != nil {
|
|
|
|
// Should never happen
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Failed to read module manifest",
|
|
|
|
fmt.Sprintf("After installing modules, Terraform could not re-read the manifest of installed modules. This is a bug in Terraform. %s.", err),
|
|
|
|
))
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
|
|
|
}
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
|
|
|
|
return true, diags
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InitCommand) initBackend(root *configs.Module, extraConfig rawFlags) (be backend.Backend, output bool, diags tfdiags.Diagnostics) {
|
|
|
|
c.Ui.Output(c.Colorize().Color(fmt.Sprintf("\n[reset][bold]Initializing the backend...")))
|
|
|
|
|
|
|
|
var backendConfig *configs.Backend
|
|
|
|
var backendConfigOverride hcl.Body
|
|
|
|
if root.Backend != nil {
|
|
|
|
backendType := root.Backend.Type
|
|
|
|
bf := backendInit.Backend(backendType)
|
|
|
|
if bf == nil {
|
|
|
|
diags = diags.Append(&hcl.Diagnostic{
|
|
|
|
Severity: hcl.DiagError,
|
|
|
|
Summary: "Unsupported backend type",
|
|
|
|
Detail: fmt.Sprintf("There is no backend type named %q.", backendType),
|
|
|
|
Subject: &root.Backend.TypeRange,
|
|
|
|
})
|
|
|
|
return nil, true, diags
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
b := bf()
|
|
|
|
backendSchema := b.ConfigSchema()
|
|
|
|
backendConfig = root.Backend
|
2018-03-28 00:31:05 +02:00
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
var overrideDiags tfdiags.Diagnostics
|
|
|
|
backendConfigOverride, overrideDiags = c.backendConfigOverrideBody(extraConfig, backendSchema)
|
|
|
|
diags = diags.Append(overrideDiags)
|
|
|
|
if overrideDiags.HasErrors() {
|
|
|
|
return nil, true, diags
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
2019-07-23 14:08:28 +02:00
|
|
|
} else {
|
|
|
|
// If the user supplied a -backend-config on the CLI but no backend
|
|
|
|
// block was found in the configuration, it's likely - but not
|
|
|
|
// necessarily - a mistake. Return a warning.
|
|
|
|
if !extraConfig.Empty() {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Warning,
|
|
|
|
"Missing backend configuration",
|
|
|
|
`-backend-config was used without a "backend" block in the configuration.
|
|
|
|
|
|
|
|
If you intended to override the default local backend configuration,
|
|
|
|
no action is required, but you may add an explicit backend block to your
|
|
|
|
configuration to clear this warning:
|
|
|
|
|
|
|
|
terraform {
|
|
|
|
backend "local" {}
|
|
|
|
}
|
|
|
|
|
|
|
|
However, if you intended to override a defined backend, please verify that
|
|
|
|
the backend configuration is present and valid.
|
|
|
|
`,
|
|
|
|
))
|
|
|
|
}
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
opts := &BackendOpts{
|
|
|
|
Config: backendConfig,
|
|
|
|
ConfigOverride: backendConfigOverride,
|
|
|
|
Init: true,
|
|
|
|
}
|
2019-02-26 00:37:20 +01:00
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
back, backDiags := c.Backend(opts)
|
|
|
|
diags = diags.Append(backDiags)
|
|
|
|
return back, true, diags
|
2018-03-28 00:31:05 +02:00
|
|
|
}
|
|
|
|
|
2017-06-09 18:42:45 +02:00
|
|
|
// Load the complete module tree, and fetch any missing providers.
|
|
|
|
// This method outputs its own Ui.
|
2020-04-01 01:03:07 +02:00
|
|
|
func (c *InitCommand) getProviders(earlyConfig *earlyconfig.Config, state *states.State, upgrade bool, pluginDirs []string) (output bool, diags tfdiags.Diagnostics) {
|
2020-03-24 22:51:55 +01:00
|
|
|
// First we'll collect all the provider dependencies we can see in the
|
|
|
|
// configuration and the state.
|
2020-03-26 23:42:03 +01:00
|
|
|
reqs, moreDiags := earlyConfig.ProviderRequirements()
|
|
|
|
diags = diags.Append(moreDiags)
|
|
|
|
if moreDiags.HasErrors() {
|
2020-03-24 22:51:55 +01:00
|
|
|
return false, diags
|
|
|
|
}
|
|
|
|
if state != nil {
|
2020-03-26 23:42:03 +01:00
|
|
|
stateReqs := state.ProviderRequirements()
|
|
|
|
reqs = reqs.Merge(stateReqs)
|
2020-03-24 22:51:55 +01:00
|
|
|
}
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
|
2020-04-01 01:03:07 +02:00
|
|
|
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)
|
2020-05-13 14:48:11 +02:00
|
|
|
|
|
|
|
// The default (or configured) search paths are logged earlier, in provider_source.go
|
|
|
|
// Log that those are being overridden by the `-plugin-dir` command line options
|
2020-05-14 20:04:13 +02:00
|
|
|
log.Println("[DEBUG] init: overriding provider plugin search paths")
|
2020-05-13 14:48:11 +02:00
|
|
|
log.Printf("[DEBUG] will search for provider plugins in %s", pluginDirs)
|
2020-04-01 01:03:07 +02:00
|
|
|
}
|
2017-06-19 16:23:58 +02:00
|
|
|
|
2020-03-14 01:04:14 +01:00
|
|
|
// 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
|
|
|
|
// things relatively concise. Later it'd be nice to have a progress UI
|
|
|
|
// where statuses update in-place, but we can't do that as long as we
|
|
|
|
// are shimming our vt100 output to the legacy console API on Windows.
|
|
|
|
evts := &providercache.InstallerEvents{
|
|
|
|
PendingProviders: func(reqs map[addrs.Provider]getproviders.VersionConstraints) {
|
|
|
|
c.Ui.Output(c.Colorize().Color(
|
|
|
|
"\n[reset][bold]Initializing provider plugins...",
|
|
|
|
))
|
|
|
|
},
|
|
|
|
ProviderAlreadyInstalled: func(provider addrs.Provider, selectedVersion getproviders.Version) {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- Using previously-installed %s v%s", provider.ForDisplay(), selectedVersion))
|
2020-03-14 01:04:14 +01:00
|
|
|
},
|
2020-04-02 01:44:50 +02:00
|
|
|
BuiltInProviderAvailable: func(provider addrs.Provider) {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- %s is built in to Terraform", provider.ForDisplay()))
|
2020-04-02 01:44:50 +02:00
|
|
|
},
|
|
|
|
BuiltInProviderFailure: func(provider addrs.Provider, err error) {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Invalid dependency on built-in provider",
|
2020-04-03 14:37:40 +02:00
|
|
|
fmt.Sprintf("Cannot use %s: %s.", provider.ForDisplay(), err),
|
2020-04-02 01:44:50 +02:00
|
|
|
))
|
|
|
|
},
|
2020-03-14 01:04:14 +01:00
|
|
|
QueryPackagesBegin: func(provider addrs.Provider, versionConstraints getproviders.VersionConstraints) {
|
|
|
|
if len(versionConstraints) > 0 {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- Finding %s versions matching %q...", provider.ForDisplay(), getproviders.VersionConstraintsString(versionConstraints)))
|
2020-03-14 01:04:14 +01:00
|
|
|
} else {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- Finding latest version of %s...", provider.ForDisplay()))
|
2020-03-14 01:04:14 +01:00
|
|
|
}
|
|
|
|
},
|
|
|
|
LinkFromCacheBegin: func(provider addrs.Provider, version getproviders.Version, cacheRoot string) {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- Using %s v%s from the shared cache directory", provider.ForDisplay(), version))
|
2020-03-14 01:04:14 +01:00
|
|
|
},
|
|
|
|
FetchPackageBegin: func(provider addrs.Provider, version getproviders.Version, location getproviders.PackageLocation) {
|
2020-04-03 14:37:40 +02:00
|
|
|
c.Ui.Info(fmt.Sprintf("- Installing %s v%s...", provider.ForDisplay(), version))
|
2020-03-14 01:04:14 +01:00
|
|
|
},
|
|
|
|
QueryPackagesFailure: func(provider addrs.Provider, err error) {
|
2020-05-14 20:04:13 +02:00
|
|
|
switch errorTy := err.(type) {
|
|
|
|
case getproviders.ErrProviderNotFound:
|
|
|
|
sources := errorTy.Sources
|
|
|
|
displaySources := make([]string, len(sources))
|
|
|
|
for i, source := range sources {
|
|
|
|
displaySources[i] = fmt.Sprintf("- %s", source)
|
|
|
|
}
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Failed to query available provider packages",
|
2020-05-20 16:20:13 +02:00
|
|
|
fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s\n\n%s",
|
2020-05-14 20:04:13 +02:00
|
|
|
provider.ForDisplay(), err, strings.Join(displaySources, "\n"),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
default:
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Failed to query available provider packages",
|
2020-05-20 16:20:13 +02:00
|
|
|
fmt.Sprintf("Could not retrieve the list of available versions for provider %s: %s",
|
2020-05-14 20:04:13 +02:00
|
|
|
provider.ForDisplay(), err,
|
|
|
|
),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
|
2020-03-14 01:04:14 +01:00
|
|
|
},
|
|
|
|
LinkFromCacheFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Failed to install provider from shared cache",
|
2020-04-03 14:37:40 +02:00
|
|
|
fmt.Sprintf("Error while importing %s v%s from the shared cache directory: %s.", provider.ForDisplay(), version, err),
|
2020-03-14 01:04:14 +01:00
|
|
|
))
|
|
|
|
},
|
|
|
|
FetchPackageFailure: func(provider addrs.Provider, version getproviders.Version, err error) {
|
2020-05-11 19:49:12 +02:00
|
|
|
switch err := err.(type) {
|
|
|
|
case getproviders.ErrProtocolNotSupported:
|
|
|
|
closestAvailable := err.Suggestion
|
|
|
|
switch {
|
|
|
|
case closestAvailable == getproviders.UnspecifiedVersion:
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Incompatible provider version",
|
|
|
|
fmt.Sprintf(errProviderVersionIncompatible, provider.String()),
|
|
|
|
))
|
|
|
|
case version.GreaterThan(closestAvailable):
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Incompatible provider version",
|
|
|
|
fmt.Sprintf(providerProtocolTooNew, provider.ForDisplay(),
|
|
|
|
version, tfversion.String(), closestAvailable, closestAvailable,
|
|
|
|
getproviders.VersionConstraintsString(reqs[provider]),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
default: // version is less than closestAvailable
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Incompatible provider version",
|
|
|
|
fmt.Sprintf(providerProtocolTooOld, provider.ForDisplay(),
|
|
|
|
version, tfversion.String(), closestAvailable, closestAvailable,
|
|
|
|
getproviders.VersionConstraintsString(reqs[provider]),
|
|
|
|
),
|
|
|
|
))
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Failed to install provider",
|
|
|
|
fmt.Sprintf("Error while installing %s v%s: %s", provider.ForDisplay(), version, err),
|
|
|
|
))
|
|
|
|
}
|
2020-03-14 01:04:14 +01:00
|
|
|
},
|
internal: Verify provider signatures on install
Providers installed from the registry are accompanied by a list of
checksums (the "SHA256SUMS" file), which is cryptographically signed to
allow package authentication. The process of verifying this has multiple
steps:
- First we must verify that the SHA256 hash of the package archive
matches the expected hash. This could be done for local installations
too, in the future.
- Next we ensure that the expected hash returned as part of the registry
API response matches an entry in the checksum list.
- Finally we verify the cryptographic signature of the checksum list,
using the public keys provided by the registry.
Each of these steps is implemented as a separate PackageAuthentication
type. The local archive installation mechanism uses only the archive
checksum authenticator, and the HTTP installation uses all three in the
order given.
The package authentication system now also returns a result value, which
is used by command/init to display the result of the authentication
process.
There are three tiers of signature, each of which is presented
differently to the user:
- Signatures from the embedded HashiCorp public key indicate that the
provider is officially supported by HashiCorp;
- If the signing key is not from HashiCorp, it may have an associated
trust signature, which indicates that the provider is from one of
HashiCorp's trusted partners;
- Otherwise, if the signature is valid, this is a community provider.
2020-04-08 22:22:07 +02:00
|
|
|
FetchPackageSuccess: func(provider addrs.Provider, version getproviders.Version, localDir string, authResult *getproviders.PackageAuthenticationResult) {
|
|
|
|
var warning string
|
|
|
|
if authResult != nil {
|
|
|
|
warning = authResult.Warning
|
|
|
|
}
|
|
|
|
if warning != "" {
|
|
|
|
warning = c.Colorize().Color(fmt.Sprintf("\n [reset][yellow]Warning: %s[reset]", warning))
|
|
|
|
}
|
|
|
|
|
|
|
|
c.Ui.Info(fmt.Sprintf("- Installed %s v%s (%s)%s", provider.ForDisplay(), version, authResult, warning))
|
|
|
|
},
|
2020-03-14 01:04:14 +01:00
|
|
|
}
|
|
|
|
|
2020-03-24 22:51:55 +01:00
|
|
|
mode := providercache.InstallNewProvidersOnly
|
|
|
|
if upgrade {
|
|
|
|
mode = providercache.InstallUpgrades
|
|
|
|
}
|
2020-03-14 01:04:14 +01:00
|
|
|
// TODO: Use a context that will be cancelled when the Terraform
|
|
|
|
// process receives SIGINT.
|
|
|
|
ctx := evts.OnContext(context.TODO())
|
2020-04-03 23:55:04 +02:00
|
|
|
selected, err := inst.EnsureProviderVersions(ctx, reqs, mode)
|
2020-03-24 22:51:55 +01:00
|
|
|
if err != nil {
|
2020-03-14 01:04:14 +01:00
|
|
|
// The errors captured in "err" should be redundant with what we
|
|
|
|
// received via the InstallerEvents callbacks above, so we'll
|
|
|
|
// just return those as long as we have some.
|
|
|
|
if !diags.HasErrors() {
|
|
|
|
diags = diags.Append(err)
|
|
|
|
}
|
|
|
|
return true, diags
|
2020-03-24 22:51:55 +01:00
|
|
|
}
|
2017-06-19 16:23:58 +02:00
|
|
|
|
2020-04-03 23:55:04 +02:00
|
|
|
// If any providers have "floating" versions (completely unconstrained)
|
|
|
|
// we'll suggest the user constrain with a pessimistic constraint to
|
|
|
|
// avoid implicitly adopting a later major release.
|
|
|
|
constraintSuggestions := make(map[string]string)
|
|
|
|
for addr, version := range selected {
|
|
|
|
req := reqs[addr]
|
2017-05-25 02:35:46 +02:00
|
|
|
|
2020-04-03 23:55:04 +02:00
|
|
|
if len(req) == 0 {
|
|
|
|
constraintSuggestions[addr.ForDisplay()] = "~> " + version.String()
|
2017-06-13 03:32:42 +02:00
|
|
|
}
|
2020-04-03 23:55:04 +02:00
|
|
|
}
|
|
|
|
if len(constraintSuggestions) != 0 {
|
|
|
|
names := make([]string, 0, len(constraintSuggestions))
|
|
|
|
for name := range constraintSuggestions {
|
|
|
|
names = append(names, name)
|
2017-06-02 02:57:43 +02:00
|
|
|
}
|
2020-04-03 23:55:04 +02:00
|
|
|
sort.Strings(names)
|
2017-06-02 02:57:43 +02:00
|
|
|
|
2020-04-03 23:55:04 +02:00
|
|
|
c.Ui.Output(outputInitProvidersUnconstrained)
|
|
|
|
for _, name := range names {
|
|
|
|
c.Ui.Output(fmt.Sprintf("* %s: version = %q", name, constraintSuggestions[name]))
|
2017-06-02 02:57:43 +02:00
|
|
|
}
|
2020-04-03 23:55:04 +02:00
|
|
|
}
|
2017-06-02 02:57:43 +02:00
|
|
|
|
2020-04-03 23:55:04 +02:00
|
|
|
return true, diags
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// backendConfigOverrideBody interprets the raw values of -backend-config
|
|
|
|
// arguments into a hcl Body that should override the backend settings given
|
|
|
|
// in the configuration.
|
|
|
|
//
|
|
|
|
// If the result is nil then no override needs to be provided.
|
|
|
|
//
|
|
|
|
// If the returned diagnostics contains errors then the returned body may be
|
|
|
|
// incomplete or invalid.
|
|
|
|
func (c *InitCommand) backendConfigOverrideBody(flags rawFlags, schema *configschema.Block) (hcl.Body, tfdiags.Diagnostics) {
|
|
|
|
items := flags.AllItems()
|
|
|
|
if len(items) == 0 {
|
|
|
|
return nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
var ret hcl.Body
|
|
|
|
var diags tfdiags.Diagnostics
|
|
|
|
synthVals := make(map[string]cty.Value)
|
|
|
|
|
|
|
|
mergeBody := func(newBody hcl.Body) {
|
|
|
|
if ret == nil {
|
|
|
|
ret = newBody
|
|
|
|
} else {
|
|
|
|
ret = configs.MergeBodies(ret, newBody)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
flushVals := func() {
|
|
|
|
if len(synthVals) == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
newBody := configs.SynthBody("-backend-config=...", synthVals)
|
|
|
|
mergeBody(newBody)
|
|
|
|
synthVals = make(map[string]cty.Value)
|
|
|
|
}
|
|
|
|
|
2019-05-29 19:58:04 +02:00
|
|
|
if len(items) == 1 && items[0].Value == "" {
|
|
|
|
// Explicitly remove all -backend-config options.
|
|
|
|
// We do this by setting an empty but non-nil ConfigOverrides.
|
|
|
|
return configs.SynthBody("-backend-config=''", synthVals), diags
|
|
|
|
}
|
|
|
|
|
command: "terraform init" can partially initialize for 0.12upgrade
There are a few constructs from 0.11 and prior that cause 0.12 parsing to
fail altogether, which previously created a chicken/egg problem because
we need to install the providers in order to run "terraform 0.12upgrade"
and thus fix the problem.
This changes "terraform init" to use the new "early configuration" loader
for module and provider installation. This is built on the more permissive
parser in the terraform-config-inspect package, and so it allows us to
read out the top-level blocks from the configuration while accepting
legacy HCL syntax.
In the long run this will let us do version compatibility detection before
attempting a "real" config load, giving us better error messages for any
future syntax additions, but in the short term the key thing is that it
allows us to install the dependencies even if the configuration isn't
fully valid.
Because backend init still requires full configuration, this introduces a
new mode of terraform init where it detects heuristically if it seems like
we need to do a configuration upgrade and does a partial init if so,
before finally directing the user to run "terraform 0.12upgrade" before
running any other commands.
The heuristic here is based on two assumptions:
- If the "early" loader finds no errors but the normal loader does, the
configuration is likely to be valid for Terraform 0.11 but not 0.12.
- If there's already a version constraint in the configuration that
excludes Terraform versions prior to v0.12 then the configuration is
probably _already_ upgraded and so it's just a normal syntax error,
even if the early loader didn't detect it.
Once the upgrade process is removed in 0.13.0 (users will be required to
go stepwise 0.11 -> 0.12 -> 0.13 to upgrade after that), some of this can
be simplified to remove that special mode, but the idea of doing the
dependency version checks against the liberal parser will remain valuable
to increase our chances of reporting version-based incompatibilities
rather than syntax errors as we add new features in future.
2019-01-14 20:11:00 +01:00
|
|
|
for _, item := range items {
|
|
|
|
eq := strings.Index(item.Value, "=")
|
|
|
|
|
|
|
|
if eq == -1 {
|
|
|
|
// The value is interpreted as a filename.
|
|
|
|
newBody, fileDiags := c.loadHCLFile(item.Value)
|
|
|
|
diags = diags.Append(fileDiags)
|
|
|
|
flushVals() // deal with any accumulated individual values first
|
|
|
|
mergeBody(newBody)
|
|
|
|
} else {
|
|
|
|
name := item.Value[:eq]
|
|
|
|
rawValue := item.Value[eq+1:]
|
|
|
|
attrS := schema.Attributes[name]
|
|
|
|
if attrS == nil {
|
|
|
|
diags = diags.Append(tfdiags.Sourceless(
|
|
|
|
tfdiags.Error,
|
|
|
|
"Invalid backend configuration argument",
|
|
|
|
fmt.Sprintf("The backend configuration argument %q given on the command line is not expected for the selected backend type.", name),
|
|
|
|
))
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
value, valueDiags := configValueFromCLI(item.String(), rawValue, attrS.Type)
|
|
|
|
diags = diags.Append(valueDiags)
|
|
|
|
if valueDiags.HasErrors() {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
synthVals[name] = value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
flushVals()
|
|
|
|
|
|
|
|
return ret, diags
|
2017-05-03 17:02:47 +02:00
|
|
|
}
|
|
|
|
|
2017-09-26 03:09:43 +02:00
|
|
|
func (c *InitCommand) AutocompleteArgs() complete.Predictor {
|
|
|
|
return complete.PredictDirs("")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InitCommand) AutocompleteFlags() complete.Flags {
|
|
|
|
return complete.Flags{
|
|
|
|
"-backend": completePredictBoolean,
|
|
|
|
"-backend-config": complete.PredictFiles("*.tfvars"), // can also be key=value, but we can't "predict" that
|
|
|
|
"-force-copy": complete.PredictNothing,
|
|
|
|
"-from-module": completePredictModuleSource,
|
|
|
|
"-get": completePredictBoolean,
|
|
|
|
"-get-plugins": completePredictBoolean,
|
|
|
|
"-input": completePredictBoolean,
|
|
|
|
"-lock": completePredictBoolean,
|
|
|
|
"-lock-timeout": complete.PredictAnything,
|
|
|
|
"-no-color": complete.PredictNothing,
|
|
|
|
"-plugin-dir": complete.PredictDirs(""),
|
|
|
|
"-reconfigure": complete.PredictNothing,
|
|
|
|
"-upgrade": completePredictBoolean,
|
|
|
|
"-verify-plugins": completePredictBoolean,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 01:03:39 +02:00
|
|
|
func (c *InitCommand) Help() string {
|
|
|
|
helpText := `
|
2017-06-02 22:13:11 +02:00
|
|
|
Usage: terraform init [options] [DIR]
|
2017-01-19 05:50:45 +01:00
|
|
|
|
2017-06-03 01:59:52 +02:00
|
|
|
Initialize a new or existing Terraform working directory by creating
|
2017-01-19 05:50:45 +01:00
|
|
|
initial files, loading any remote state, downloading modules, etc.
|
|
|
|
|
|
|
|
This is the first command that should be run for any new or existing
|
|
|
|
Terraform configuration per machine. This sets up all the local data
|
2017-04-26 16:10:04 +02:00
|
|
|
necessary to run Terraform that is typically not committed to version
|
2017-01-19 05:50:45 +01:00
|
|
|
control.
|
|
|
|
|
|
|
|
This command is always safe to run multiple times. Though subsequent runs
|
2017-06-03 01:59:52 +02:00
|
|
|
may give errors, this command will never delete your configuration or
|
|
|
|
state. Even so, if you have important information, please back it up prior
|
|
|
|
to running this command, just in case.
|
2014-09-27 01:03:39 +02:00
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
If no arguments are given, the configuration in this working directory
|
|
|
|
is initialized.
|
2014-09-27 01:03:39 +02:00
|
|
|
|
2014-10-01 01:05:40 +02:00
|
|
|
Options:
|
|
|
|
|
2017-06-03 01:59:52 +02:00
|
|
|
-backend=true Configure the backend for this configuration.
|
2014-12-05 04:06:47 +01:00
|
|
|
|
2017-03-17 07:27:05 +01:00
|
|
|
-backend-config=path This can be either a path to an HCL file with key/value
|
|
|
|
assignments (same format as terraform.tfvars) or a
|
|
|
|
'key=value' format. This is merged with what is in the
|
|
|
|
configuration file. This can be specified multiple
|
|
|
|
times. The backend type must be in the configuration
|
|
|
|
itself.
|
2014-10-01 01:05:40 +02:00
|
|
|
|
2017-04-20 23:26:50 +02:00
|
|
|
-force-copy Suppress prompts about copying state data. This is
|
|
|
|
equivalent to providing a "yes" to all confirmation
|
|
|
|
prompts.
|
|
|
|
|
2017-07-29 00:23:29 +02:00
|
|
|
-from-module=SOURCE Copy the contents of the given module into the target
|
|
|
|
directory before initialization.
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
-get=true Download any modules for this configuration.
|
|
|
|
|
2017-05-03 17:02:47 +02:00
|
|
|
-get-plugins=true Download any missing plugins for this configuration.
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
-input=true Ask for input if necessary. If false, will error if
|
|
|
|
input was required.
|
|
|
|
|
2017-04-01 22:19:59 +02:00
|
|
|
-lock=true Lock the state file when locking is supported.
|
|
|
|
|
|
|
|
-lock-timeout=0s Duration to retry a state lock.
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
-no-color If specified, output won't contain any color.
|
2015-06-22 14:14:01 +02:00
|
|
|
|
2017-06-15 21:23:16 +02:00
|
|
|
-plugin-dir Directory containing plugin binaries. This overrides all
|
|
|
|
default search paths for plugins, and prevents the
|
|
|
|
automatic installation of plugins. This flag can be used
|
|
|
|
multiple times.
|
|
|
|
|
2017-06-20 17:46:33 +02:00
|
|
|
-reconfigure Reconfigure the backend, ignoring any saved
|
|
|
|
configuration.
|
2017-06-12 23:14:40 +02:00
|
|
|
|
|
|
|
-upgrade=false If installing modules (-get) or plugins (-get-plugins),
|
|
|
|
ignore previously-downloaded objects and install the
|
|
|
|
latest version allowed within configured constraints.
|
2017-06-20 17:46:33 +02:00
|
|
|
|
|
|
|
-verify-plugins=true Verify the authenticity and integrity of automatically
|
|
|
|
downloaded plugins.
|
2014-09-27 01:03:39 +02:00
|
|
|
`
|
|
|
|
return strings.TrimSpace(helpText)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InitCommand) Synopsis() string {
|
2017-07-29 00:23:29 +02:00
|
|
|
return "Initialize a Terraform working directory"
|
2014-09-27 01:03:39 +02:00
|
|
|
}
|
2017-01-19 05:50:45 +01:00
|
|
|
|
2017-10-05 21:00:45 +02:00
|
|
|
const errInitConfigError = `
|
|
|
|
There are some problems with the configuration, described below.
|
|
|
|
|
|
|
|
The Terraform configuration must be valid before initialization so that
|
|
|
|
Terraform can determine which modules and providers need to be installed.
|
|
|
|
`
|
|
|
|
|
2020-03-19 13:01:16 +01:00
|
|
|
const errInitConfigErrorMaybeLegacySyntax = `
|
|
|
|
There are some problems with the configuration, described below.
|
|
|
|
|
|
|
|
Terraform found syntax errors in the configuration that prevented full
|
|
|
|
initialization. If you've recently upgraded to Terraform v0.13 from Terraform
|
|
|
|
v0.11, this may be because your configuration uses syntax constructs that are no
|
|
|
|
longer valid, and so must be updated before full initialization is possible.
|
|
|
|
|
|
|
|
Manually update your configuration syntax, or install Terraform v0.12 and run
|
|
|
|
terraform init for this configuration at a shell prompt for more information
|
|
|
|
on how to update it for Terraform v0.12+ compatibility.
|
|
|
|
`
|
|
|
|
|
2017-01-19 05:50:45 +01:00
|
|
|
const errInitCopyNotEmpty = `
|
2017-07-29 00:23:29 +02:00
|
|
|
The working directory already contains files. The -from-module option requires
|
|
|
|
an empty directory into which a copy of the referenced module will be placed.
|
2017-01-19 05:50:45 +01:00
|
|
|
|
2017-07-29 00:23:29 +02:00
|
|
|
To initialize the configuration already in this working directory, omit the
|
|
|
|
-from-module option.
|
2017-01-19 05:50:45 +01:00
|
|
|
`
|
|
|
|
|
|
|
|
const outputInitEmpty = `
|
|
|
|
[reset][bold]Terraform initialized in an empty directory![reset]
|
|
|
|
|
|
|
|
The directory has no Terraform configuration files. You may begin working
|
|
|
|
with Terraform immediately by creating Terraform configuration files.
|
|
|
|
`
|
|
|
|
|
|
|
|
const outputInitSuccess = `
|
|
|
|
[reset][bold][green]Terraform has been successfully initialized![reset][green]
|
2017-09-09 02:14:37 +02:00
|
|
|
`
|
2017-01-19 05:50:45 +01:00
|
|
|
|
2017-09-09 02:14:37 +02:00
|
|
|
const outputInitSuccessCLI = `[reset][green]
|
2017-01-19 05:50:45 +01:00
|
|
|
You may now begin working with Terraform. Try running "terraform plan" to see
|
|
|
|
any changes that are required for your infrastructure. All Terraform commands
|
|
|
|
should now work.
|
|
|
|
|
|
|
|
If you ever set or change modules or backend configuration for Terraform,
|
2017-06-03 01:59:52 +02:00
|
|
|
rerun this command to reinitialize your working directory. If you forget, other
|
2017-01-19 05:50:45 +01:00
|
|
|
commands will detect it and remind you to do so if necessary.
|
|
|
|
`
|
2017-06-02 02:57:43 +02:00
|
|
|
|
|
|
|
const outputInitProvidersUnconstrained = `
|
|
|
|
The following providers do not have any version constraints in configuration,
|
|
|
|
so the latest version was installed.
|
|
|
|
|
|
|
|
To prevent automatic upgrades to new major versions that may contain breaking
|
2020-04-03 23:55:04 +02:00
|
|
|
changes, we recommend adding version constraints in a required_providers block
|
|
|
|
in your configuration, with the constraint strings suggested below.
|
2017-06-02 02:57:43 +02:00
|
|
|
`
|
2017-06-09 18:42:45 +02:00
|
|
|
|
2019-03-27 19:20:15 +01:00
|
|
|
const errDiscoveryServiceUnreachable = `
|
|
|
|
[reset][bold][red]Registry service unreachable.[reset][red]
|
|
|
|
|
|
|
|
This may indicate a network issue, or an issue with the requested Terraform Registry.
|
|
|
|
`
|
|
|
|
|
2017-06-09 18:42:45 +02:00
|
|
|
const errProviderNotFound = `
|
2017-06-20 03:49:37 +02:00
|
|
|
[reset][bold][red]Provider %[1]q not available for installation.[reset][red]
|
|
|
|
|
2018-11-09 01:12:11 +01:00
|
|
|
A provider named %[1]q could not be found in the Terraform Registry.
|
2017-06-20 03:49:37 +02:00
|
|
|
|
|
|
|
This may result from mistyping the provider name, or the given provider may
|
|
|
|
be a third-party provider that cannot be installed automatically.
|
|
|
|
|
|
|
|
In the latter case, the plugin must be installed manually by locating and
|
|
|
|
downloading a suitable distribution package and placing the plugin's executable
|
|
|
|
file in the following directory:
|
|
|
|
%[2]s
|
|
|
|
|
|
|
|
Terraform detects necessary plugins by inspecting the configuration and state.
|
|
|
|
To view the provider versions requested by each module, run
|
|
|
|
"terraform providers".
|
|
|
|
`
|
|
|
|
|
|
|
|
const errProviderVersionsUnsuitable = `
|
|
|
|
[reset][bold][red]No provider %[1]q plugins meet the constraint %[2]q.[reset][red]
|
|
|
|
|
|
|
|
The version constraint is derived from the "version" argument within the
|
|
|
|
provider %[1]q block in configuration. Child modules may also apply
|
|
|
|
provider version constraints. To view the provider versions requested by each
|
|
|
|
module in the current configuration, run "terraform providers".
|
|
|
|
|
|
|
|
To proceed, the version constraints for this provider must be relaxed by
|
|
|
|
either adjusting or removing the "version" argument in the provider blocks
|
|
|
|
throughout the configuration.
|
|
|
|
`
|
|
|
|
|
|
|
|
const errProviderIncompatible = `
|
|
|
|
[reset][bold][red]No available provider %[1]q plugins are compatible with this Terraform version.[reset][red]
|
|
|
|
|
|
|
|
From time to time, new Terraform major releases can change the requirements for
|
|
|
|
plugins such that older plugins become incompatible.
|
|
|
|
|
|
|
|
Terraform checked all of the plugin versions matching the given constraint:
|
|
|
|
%[2]s
|
|
|
|
|
|
|
|
Unfortunately, none of the suitable versions are compatible with this version
|
|
|
|
of Terraform. If you have recently upgraded Terraform, it may be necessary to
|
|
|
|
move to a newer major release of this provider. Alternatively, if you are
|
|
|
|
attempting to upgrade the provider to a new major version you may need to
|
|
|
|
also upgrade Terraform to support the new version.
|
|
|
|
|
|
|
|
Consult the documentation for this provider for more information on
|
|
|
|
compatibility between provider versions and Terraform versions.
|
|
|
|
`
|
|
|
|
|
|
|
|
const errProviderInstallError = `
|
|
|
|
[reset][bold][red]Error installing provider %[1]q: %[2]s.[reset][red]
|
|
|
|
|
|
|
|
Terraform analyses the configuration and state and automatically downloads
|
|
|
|
plugins for the providers used. However, when attempting to download this
|
2019-03-21 20:38:51 +01:00
|
|
|
plugin an unexpected error occurred.
|
2017-06-20 03:49:37 +02:00
|
|
|
|
|
|
|
This may be caused if for some reason Terraform is unable to reach the
|
|
|
|
plugin repository. The repository may be unreachable if access is blocked
|
|
|
|
by a firewall.
|
|
|
|
|
|
|
|
If automatic installation is not possible or desirable in your environment,
|
|
|
|
you may alternatively manually install plugins by downloading a suitable
|
|
|
|
distribution package and placing the plugin's executable file in the
|
|
|
|
following directory:
|
|
|
|
%[3]s
|
|
|
|
`
|
|
|
|
|
|
|
|
const errMissingProvidersNoInstall = `
|
|
|
|
[reset][bold][red]Missing required providers.[reset][red]
|
2017-06-09 18:42:45 +02:00
|
|
|
|
2017-06-20 03:49:37 +02:00
|
|
|
The following provider constraints are not met by the currently-installed
|
|
|
|
provider plugins:
|
2017-06-09 18:42:45 +02:00
|
|
|
|
2017-06-20 03:49:37 +02:00
|
|
|
%[1]s
|
|
|
|
Terraform can automatically download and install plugins to meet the given
|
|
|
|
constraints, but this step was skipped due to the use of -get-plugins=false
|
|
|
|
and/or -plugin-dir on the command line.
|
2017-06-09 18:42:45 +02:00
|
|
|
|
2017-06-20 03:49:37 +02:00
|
|
|
If automatic installation is not possible or desirable in your environment,
|
|
|
|
you may manually install plugins by downloading a suitable distribution package
|
|
|
|
and placing the plugin's executable file in one of the directories given in
|
|
|
|
by -plugin-dir on the command line, or in the following directory if custom
|
|
|
|
plugin directories are not set:
|
|
|
|
%[2]s
|
2017-06-09 18:42:45 +02:00
|
|
|
`
|
2019-03-21 20:38:51 +01:00
|
|
|
|
|
|
|
const errChecksumVerification = `
|
|
|
|
[reset][bold][red]Error verifying checksum for provider %[1]q[reset][red]
|
|
|
|
The checksum for provider distribution from the Terraform Registry
|
|
|
|
did not match the source. This may mean that the distributed files
|
|
|
|
were changed after this version was released to the Registry.
|
|
|
|
`
|
|
|
|
|
|
|
|
const errSignatureVerification = `
|
2020-02-22 02:03:26 +01:00
|
|
|
[reset][bold][red]Error:[reset][bold] Untrusted signing key for provider %[1]q[reset]
|
|
|
|
|
|
|
|
This provider package is not signed with the HashiCorp signing key, and is
|
|
|
|
therefore incompatible with Terraform v%[2]s.
|
|
|
|
|
|
|
|
A later version of Terraform may have introduced other signing keys that would
|
|
|
|
accept this provider. Alternatively, an earlier version of this provider may
|
|
|
|
be compatible with Terraform v%[2]s.
|
2019-03-21 20:38:51 +01:00
|
|
|
`
|
2020-05-11 19:49:12 +02:00
|
|
|
|
|
|
|
// providerProtocolTooOld is a message sent to the CLI UI if the provider's
|
|
|
|
// supported protocol versions are too old for the user's version of terraform,
|
|
|
|
// but a newer version of the provider is compatible.
|
|
|
|
const providerProtocolTooOld = `Provider %q v%s is not compatible with Terraform %s.
|
|
|
|
Provider version %s is the latest compatible version. Select it with the following version constraint:
|
|
|
|
version = %q
|
|
|
|
|
|
|
|
Terraform checked all of the plugin versions matching the given constraint:
|
|
|
|
%s
|
|
|
|
|
|
|
|
Consult the documentation for this provider for more information on compatibility between provider and Terraform versions.
|
|
|
|
`
|
|
|
|
|
|
|
|
// providerProtocolTooNew is a message sent to the CLI UI if the provider's
|
|
|
|
// supported protocol versions are too new for the user's version of terraform,
|
|
|
|
// and the user could either upgrade terraform or choose an older version of the
|
|
|
|
// provider.
|
|
|
|
const providerProtocolTooNew = `Provider %q v%s is not compatible with Terraform %s.
|
|
|
|
You need to downgrade to v%s or earlier. Select it with the following constraint:
|
|
|
|
version = %q
|
|
|
|
|
|
|
|
Terraform checked all of the plugin versions matching the given constraint:
|
|
|
|
%s
|
|
|
|
|
|
|
|
Consult the documentation for this provider for more information on compatibility between provider and Terraform versions.
|
|
|
|
Alternatively, upgrade to the latest version of Terraform for compatibility with newer provider releases.
|
|
|
|
`
|
|
|
|
|
|
|
|
// No version of the provider is compatible.
|
|
|
|
const errProviderVersionIncompatible = `No compatible versions of provider %s were found.`
|