2014-05-24 21:27:58 +02:00
package command
import (
2014-06-19 01:42:13 +02:00
"fmt"
2014-05-24 21:27:58 +02:00
"strings"
2017-01-19 05:50:45 +01:00
"github.com/hashicorp/terraform/backend"
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
"github.com/hashicorp/terraform/command/arguments"
"github.com/hashicorp/terraform/command/views"
2021-02-02 16:35:45 +01:00
"github.com/hashicorp/terraform/plans/planfile"
2021-02-12 02:52:10 +01:00
"github.com/hashicorp/terraform/terraform"
terraform: ugly huge change to weave in new HCL2-oriented types
Due to how deeply the configuration types go into Terraform Core, there
isn't a great way to switch out to HCL2 gradually. As a consequence, this
huge commit gets us from the old state to a _compilable_ new state, but
does not yet attempt to fix any tests and has a number of known missing
parts and bugs. We will continue to iterate on this in forthcoming
commits, heading back towards passing tests and making Terraform
fully-functional again.
The three main goals here are:
- Use the configuration models from the "configs" package instead of the
older models in the "config" package, which is now deprecated and
preserved only to help us write our migration tool.
- Do expression inspection and evaluation using the functionality of the
new "lang" package, instead of the Interpolator type and related
functionality in the main "terraform" package.
- Represent addresses of various objects using types in the addrs package,
rather than hand-constructed strings. This is not critical to support
the above, but was a big help during the implementation of these other
points since it made it much more explicit what kind of address is
expected in each context.
Since our new packages are built to accommodate some future planned
features that are not yet implemented (e.g. the "for_each" argument on
resources, "count"/"for_each" on modules), and since there's still a fair
amount of functionality still using old-style APIs, there is a moderate
amount of shimming here to connect new assumptions with old, hopefully in
a way that makes it easier to find and eliminate these shims later.
I apologize in advance to the person who inevitably just found this huge
commit while spelunking through the commit history.
2018-04-30 19:33:53 +02:00
"github.com/hashicorp/terraform/tfdiags"
2014-05-24 21:27:58 +02:00
)
// ApplyCommand is a Command implementation that applies a Terraform
// configuration and actually builds or changes infrastructure.
type ApplyCommand struct {
2014-07-13 05:21:46 +02:00
Meta
2014-10-01 06:49:24 +02:00
// If true, then this apply command will become the "destroy"
// command. It is just like apply but only processes a destroy.
Destroy bool
2014-05-24 21:27:58 +02:00
}
2014-06-19 01:42:13 +02:00
func ( c * ApplyCommand ) Run ( args [ ] string ) int {
2021-02-03 21:05:05 +01:00
var refresh , autoApprove bool
2020-04-01 21:01:08 +02:00
args = c . Meta . process ( args )
2014-10-01 06:49:24 +02:00
cmdName := "apply"
if c . Destroy {
cmdName = "destroy"
}
2018-11-21 15:35:27 +01:00
cmdFlags := c . Meta . extendedFlagSet ( cmdName )
2018-02-01 01:14:42 +01:00
cmdFlags . BoolVar ( & autoApprove , "auto-approve" , false , "skip interactive approval of plan before applying" )
2014-07-27 02:50:13 +02:00
cmdFlags . BoolVar ( & refresh , "refresh" , true , "refresh" )
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
cmdFlags . IntVar ( & c . Meta . parallelism , "parallelism" , DefaultParallelism , "parallelism" )
2017-01-19 05:50:45 +01:00
cmdFlags . StringVar ( & c . Meta . statePath , "state" , "" , "path" )
2014-10-12 03:05:23 +02:00
cmdFlags . StringVar ( & c . Meta . stateOutPath , "state-out" , "" , "path" )
cmdFlags . StringVar ( & c . Meta . backupPath , "backup" , "" , "path" )
2017-02-06 16:07:32 +01:00
cmdFlags . BoolVar ( & c . Meta . stateLock , "lock" , true , "lock state" )
2017-04-01 22:19:59 +02:00
cmdFlags . DurationVar ( & c . Meta . stateLockTimeout , "lock-timeout" , 0 , "lock timeout" )
2014-06-19 01:42:13 +02:00
cmdFlags . Usage = func ( ) { c . Ui . Error ( c . Help ( ) ) }
if err := cmdFlags . Parse ( args ) ; err != nil {
2021-02-08 19:29:42 +01:00
c . Ui . Error ( fmt . Sprintf ( "Error parsing command-line flags: %s\n" , err . Error ( ) ) )
2014-06-19 01:42:13 +02:00
return 1
}
2021-02-08 19:29:42 +01:00
diags := c . parseTargetFlags ( )
if diags . HasErrors ( ) {
c . showDiagnostics ( diags )
return 1
}
2018-10-16 16:47:32 +02:00
2014-06-19 01:42:13 +02:00
args = cmdFlags . Args ( )
2021-02-02 16:35:45 +01:00
var planPath string
if len ( args ) > 0 {
planPath = args [ 0 ]
args = args [ 1 : ]
}
2017-01-19 05:50:45 +01:00
configPath , err := ModulePath ( args )
if err != nil {
c . Ui . Error ( err . Error ( ) )
2014-06-19 01:42:13 +02:00
return 1
}
2017-06-15 20:26:12 +02:00
// Check for user-supplied plugin path
if c . pluginPath , err = c . loadPluginPath ( ) ; err != nil {
c . Ui . Error ( fmt . Sprintf ( "Error loading plugin path: %s" , err ) )
return 1
}
2014-09-30 00:55:28 +02:00
2021-02-02 16:35:45 +01:00
// Try to load plan if path is specified
var planFile * planfile . Reader
if planPath != "" {
planFile , err = c . PlanFile ( planPath )
if err != nil {
c . Ui . Error ( err . Error ( ) )
return 1
}
2021-02-03 20:10:14 +01:00
// If the path doesn't look like a plan, both planFile and err will be
// nil. In that case, the user is probably trying to use the positional
// argument to specify a configuration path. Point them at -chdir.
if planFile == nil {
c . Ui . Error ( fmt . Sprintf ( "Failed to load %q as a plan file. Did you mean to use -chdir?" , planPath ) )
return 1
}
// If we successfully loaded a plan but this is a destroy operation,
// explain that this is not supported.
if c . Destroy {
c . Ui . Error ( "Destroy can't be called with a plan file." )
return 1
}
2014-10-01 06:49:24 +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
if planFile != nil {
2017-01-19 05:50:45 +01:00
// Reset the config path for backend loading
configPath = ""
2018-10-16 16:47:32 +02:00
if ! c . variableArgs . Empty ( ) {
diags = diags . Append ( tfdiags . Sourceless (
tfdiags . Error ,
"Can't set variables when applying a saved plan" ,
"The -var and -var-file options cannot be used when applying a saved plan file, because a saved plan includes the variable values that were set when it was created." ,
) )
c . showDiagnostics ( diags )
return 1
}
}
command: validate config as part of loading it
Previously we required callers to separately call .Validate on the root
module to determine if there were any value errors, but we did that
inconsistently and would thus see crashes in some cases where later code
would try to use invalid configuration as if it were valid.
Now we run .Validate automatically after config loading, returning the
resulting diagnostics. Since we return a diagnostics here, it's possible
to return both warnings and errors.
We return the loaded module even if it's invalid, so callers are free to
ignore returned errors and try to work with the config anyway, though they
will need to be defensive against invalid configuration themselves in
that case.
As a result of this, all of the commands that load configuration now need
to use diagnostic printing to signal errors. For the moment this just
allows us to return potentially-multiple config errors/warnings in full
fidelity, but also sets us up for later when more subsystems are able
to produce rich diagnostics so we can show them all together.
Finally, this commit also removes some stale, commented-out code for the
"legacy" (pre-0.8) graph implementation, which has not been available
for some time.
2017-12-07 01:41:48 +01:00
2021-01-29 20:39:06 +01:00
// Set up our count hook that keeps track of resource changes
countHook := new ( CountHook )
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
// Load the backend
var be backend . Enhanced
var beDiags tfdiags . Diagnostics
if planFile == nil {
backendConfig , configDiags := c . loadBackendConfig ( configPath )
2018-03-28 00:31:05 +02:00
diags = diags . Append ( configDiags )
if configDiags . HasErrors ( ) {
command: validate config as part of loading it
Previously we required callers to separately call .Validate on the root
module to determine if there were any value errors, but we did that
inconsistently and would thus see crashes in some cases where later code
would try to use invalid configuration as if it were valid.
Now we run .Validate automatically after config loading, returning the
resulting diagnostics. Since we return a diagnostics here, it's possible
to return both warnings and errors.
We return the loaded module even if it's invalid, so callers are free to
ignore returned errors and try to work with the config anyway, though they
will need to be defensive against invalid configuration themselves in
that case.
As a result of this, all of the commands that load configuration now need
to use diagnostic printing to signal errors. For the moment this just
allows us to return potentially-multiple config errors/warnings in full
fidelity, but also sets us up for later when more subsystems are able
to produce rich diagnostics so we can show them all together.
Finally, this commit also removes some stale, commented-out code for the
"legacy" (pre-0.8) graph implementation, which has not been available
for some time.
2017-12-07 01:41:48 +01:00
c . showDiagnostics ( diags )
2017-01-19 05:50:45 +01:00
return 1
}
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
be , beDiags = c . Backend ( & BackendOpts {
Config : backendConfig ,
} )
} else {
plan , err := planFile . ReadPlan ( )
if err != nil {
diags = diags . Append ( tfdiags . Sourceless (
tfdiags . Error ,
"Failed to read plan from plan file" ,
fmt . Sprintf ( "Cannot read the plan from the given plan file: %s." , err ) ,
) )
2018-09-30 18:29:51 +02:00
c . showDiagnostics ( diags )
return 1
}
if plan . Backend . Config == nil {
// Should never happen; always indicates a bug in the creation of the plan file
diags = diags . Append ( tfdiags . Sourceless (
tfdiags . Error ,
"Failed to read plan from plan file" ,
2020-12-01 16:42:07 +01:00
"The given plan file does not have a valid backend configuration. This is a bug in the Terraform command that generated this plan file." ,
2018-09-30 18:29:51 +02:00
) )
c . showDiagnostics ( diags )
return 1
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
}
be , beDiags = c . BackendForPlan ( plan . Backend )
}
2018-03-28 00:31:05 +02:00
diags = diags . Append ( beDiags )
if beDiags . HasErrors ( ) {
c . showDiagnostics ( diags )
2017-01-19 05:50:45 +01:00
return 1
}
2020-10-15 03:00:23 +02:00
// Applying changes with dev overrides in effect could make it impossible
// to switch back to a release version if the schema isn't compatible,
// so we'll warn about it.
2021-02-01 16:50:08 +01:00
diags = diags . Append ( c . providerDevOverrideRuntimeWarnings ( ) )
2020-10-15 03:00:23 +02:00
2018-03-28 00:31:05 +02:00
// Before we delegate to the backend, we'll print any warning diagnostics
// we've accumulated here, since the backend will start fresh with its own
// diagnostics.
c . showDiagnostics ( diags )
diags = nil
2017-01-19 05:50:45 +01:00
// Build the operation
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
opReq := c . Operation ( be )
2018-10-05 15:25:17 +02:00
opReq . AutoApprove = autoApprove
2018-03-28 00:31:05 +02:00
opReq . ConfigDir = configPath
2018-10-31 16:45:03 +01:00
opReq . Destroy = c . Destroy
2021-02-12 02:52:10 +01:00
opReq . Hooks = [ ] terraform . Hook { countHook , c . uiHook ( ) }
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
opReq . PlanFile = planFile
2017-01-19 05:50:45 +01:00
opReq . PlanRefresh = refresh
2021-02-12 19:59:14 +01:00
opReq . ShowDiagnostics = c . showDiagnostics
2017-01-19 05:50:45 +01:00
opReq . Type = backend . OperationTypeApply
backend/local: Replace CLI with view instance
This commit extracts the remaining UI logic from the local backend,
and removes access to the direct CLI output. This is replaced with an
instance of a `views.Operation` interface, which codifies the current
requirements for the local backend to interact with the user.
The exception to this at present is interactivity: approving a plan
still depends on the `UIIn` field for the backend. This is out of scope
for this commit and can be revisited separately, at which time the
`UIOut` field can also be removed.
Changes in support of this:
- Some instances of direct error output have been replaced with
diagnostics, most notably in the emergency state backup handler. This
requires reformatting the error messages to allow the diagnostic
renderer to line-wrap them;
- The "in-automation" logic has moved out of the backend and into the
view implementation;
- The plan, apply, refresh, and import commands instantiate a view and
set it on the `backend.Operation` struct, as these are the only code
paths which call the `local.Operation()` method that requires it;
- The show command requires the plan rendering code which is now in the
views package, so there is a stub implementation of a `views.Show`
interface there.
Other refactoring work in support of migrating these commands to the
common views code structure will come in follow-up PRs, at which point
we will be able to remove the UI instances from the unit tests for those
commands.
2021-02-17 19:01:30 +01:00
opReq . View = views . NewOperation ( arguments . ViewHuman , c . RunningInAutomation , c . View )
2018-10-31 16:45:03 +01:00
2018-03-28 00:31:05 +02:00
opReq . ConfigLoader , err = c . initConfigLoader ( )
2017-01-19 05:50:45 +01:00
if err != nil {
2018-03-28 00:31:05 +02:00
c . showDiagnostics ( err )
return 1
2014-06-19 01:42:13 +02:00
}
2018-10-31 16:45:03 +01:00
2018-10-12 22:19:58 +02:00
{
var moreDiags tfdiags . Diagnostics
opReq . Variables , moreDiags = c . collectVariableValues ( )
diags = diags . Append ( moreDiags )
if moreDiags . HasErrors ( ) {
c . showDiagnostics ( diags )
return 1
}
}
2014-06-19 01:42:13 +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
op , err := c . RunOperation ( be , opReq )
2018-03-28 00:31:05 +02:00
if err != nil {
c . showDiagnostics ( err )
command: validate config as part of loading it
Previously we required callers to separately call .Validate on the root
module to determine if there were any value errors, but we did that
inconsistently and would thus see crashes in some cases where later code
would try to use invalid configuration as if it were valid.
Now we run .Validate automatically after config loading, returning the
resulting diagnostics. Since we return a diagnostics here, it's possible
to return both warnings and errors.
We return the loaded module even if it's invalid, so callers are free to
ignore returned errors and try to work with the config anyway, though they
will need to be defensive against invalid configuration themselves in
that case.
As a result of this, all of the commands that load configuration now need
to use diagnostic printing to signal errors. For the moment this just
allows us to return potentially-multiple config errors/warnings in full
fidelity, but also sets us up for later when more subsystems are able
to produce rich diagnostics so we can show them all together.
Finally, this commit also removes some stale, commented-out code for the
"legacy" (pre-0.8) graph implementation, which has not been available
for some time.
2017-12-07 01:41:48 +01:00
return 1
}
2021-01-29 20:39:06 +01:00
2018-03-28 00:31:05 +02:00
if op . Result != backend . OperationSuccess {
return op . Result . ExitStatus ( )
}
command: validate config as part of loading it
Previously we required callers to separately call .Validate on the root
module to determine if there were any value errors, but we did that
inconsistently and would thus see crashes in some cases where later code
would try to use invalid configuration as if it were valid.
Now we run .Validate automatically after config loading, returning the
resulting diagnostics. Since we return a diagnostics here, it's possible
to return both warnings and errors.
We return the loaded module even if it's invalid, so callers are free to
ignore returned errors and try to work with the config anyway, though they
will need to be defensive against invalid configuration themselves in
that case.
As a result of this, all of the commands that load configuration now need
to use diagnostic printing to signal errors. For the moment this just
allows us to return potentially-multiple config errors/warnings in full
fidelity, but also sets us up for later when more subsystems are able
to produce rich diagnostics so we can show them all together.
Finally, this commit also removes some stale, commented-out code for the
"legacy" (pre-0.8) graph implementation, which has not been available
for some time.
2017-12-07 01:41:48 +01:00
2021-01-29 20:39:06 +01:00
// Show the count results from the operation
if c . Destroy {
c . Ui . Output ( c . Colorize ( ) . Color ( fmt . Sprintf (
"[reset][bold][green]\n" +
"Destroy complete! Resources: %d destroyed." ,
countHook . Removed ) ) )
} else {
c . Ui . Output ( c . Colorize ( ) . Color ( fmt . Sprintf (
"[reset][bold][green]\n" +
"Apply complete! Resources: %d added, %d changed, %d destroyed." ,
countHook . Added ,
countHook . Changed ,
countHook . Removed ) ) )
}
// only show the state file help message if the state is local.
if ( countHook . Added > 0 || countHook . Changed > 0 ) && c . Meta . stateOutPath != "" {
c . Ui . Output ( c . Colorize ( ) . Color ( fmt . Sprintf (
"[reset]\n" +
"The state of your infrastructure has been saved to the path\n" +
"below. This state is required to modify and destroy your\n" +
"infrastructure, so keep it safe. To inspect the complete state\n" +
"use the `terraform show` command.\n\n" +
"State path: %s" ,
c . Meta . stateOutPath ) ) )
}
cli: Add initial command views abstraction
Terraform supports multiple output formats for several sub-commands.
The default format is user-readable text, but many sub-commands support
a `-json` flag to output a machine-readable format for the result. The
output command also supports a `-raw` flag for a simpler, scripting-
focused machine readable format.
This commit adds a "views" abstraction, intended to help ensure
consistency between the various output formats. This extracts the render
specific code from the command package, and moves it into a views
package. Each command is expected to create an interface for its view,
and one or more implementations of that interface.
By doing so, we separate the concerns of generating the sub-command
result from rendering the result in the specified output format. This
should make it easier to ensure that all output formats will be updated
together when changes occur in the result-generating phase.
There are some other consequences of this restructuring:
- Views now directly access the terminal streams, rather than the
now-redundant cli.Ui instance;
- With the reorganization of commands, parsing CLI arguments is now the
responsibility of a separate "arguments" package.
For now, views are added only for the output sub-command, as an example.
Because this command uses code which is shared with the apply and
refresh commands, those are also partially updated.
2021-01-27 21:51:40 +01:00
if ! c . Destroy && op . State != nil {
outputValues := op . State . RootModule ( ) . OutputValues
if len ( outputValues ) > 0 {
c . Ui . Output ( c . Colorize ( ) . Color ( "[reset][bold][green]\nOutputs:\n\n" ) )
view := views . NewOutput ( arguments . ViewHuman , c . View )
view . Output ( "" , outputValues )
2018-10-15 00:33:30 +02:00
}
2014-07-13 18:34:35 +02:00
}
2018-03-28 00:31:05 +02:00
return op . Result . ExitStatus ( )
2014-05-24 21:27:58 +02:00
}
func ( c * ApplyCommand ) Help ( ) string {
2014-10-01 07:01:11 +02:00
if c . Destroy {
return c . helpDestroy ( )
}
return c . helpApply ( )
}
func ( c * ApplyCommand ) Synopsis ( ) string {
if c . Destroy {
2020-10-24 01:55:32 +02:00
return "Destroy previously-created infrastructure"
2014-10-01 07:01:11 +02:00
}
2020-10-24 01:55:32 +02:00
return "Create or update infrastructure"
2014-10-01 07:01:11 +02:00
}
func ( c * ApplyCommand ) helpApply ( ) string {
2014-05-24 21:27:58 +02:00
helpText := `
2020-10-24 01:55:32 +02:00
Usage : terraform apply [ options ] [ PLAN ]
2014-05-24 21:27:58 +02:00
2020-10-24 01:55:32 +02:00
Creates or updates infrastructure according to Terraform configuration
files in the current directory .
2014-09-30 00:57:35 +02:00
2020-10-24 01:55:32 +02:00
By default , Terraform will generate a new plan and present it for your
approval before taking any action . You can optionally provide a plan
file created by a previous call to "terraform plan" , in which case
Terraform will take the actions described in that plan without any
confirmation prompt .
2016-04-11 19:24:08 +02:00
2014-05-24 21:27:58 +02:00
Options :
2019-12-10 20:06:06 +01:00
- auto - approve Skip interactive approval of plan before applying .
2014-07-28 00:09:04 +02:00
- backup = path Path to backup the existing state file before
modifying . Defaults to the "-state-out" path with
2014-08-07 09:19:56 +02:00
".backup" extension . Set to "-" to disable backup .
2014-07-28 00:09:04 +02:00
2019-12-10 20:06:06 +01:00
- compact - warnings If Terraform produces any warnings that are not
accompanied by errors , show them in a more compact
form that includes only the summary messages .
2018-03-26 19:21:47 +02:00
2017-02-06 16:07:32 +01:00
- lock = true Lock the state file when locking is supported .
2017-02-03 20:15:08 +01:00
2017-04-01 22:19:59 +02:00
- lock - timeout = 0 s Duration to retry a state lock .
2014-09-29 21:46:58 +02:00
- input = true Ask for input for variables if not directly set .
2014-07-13 05:21:46 +02:00
- no - color If specified , output won ' t contain any color .
2017-02-08 20:49:08 +01:00
- parallelism = n Limit the number of parallel resource operations .
2015-10-05 22:06:08 +02:00
Defaults to 10.
2015-05-06 17:58:42 +02:00
2014-07-27 02:50:13 +02:00
- refresh = true Update state prior to checking for differences . This
has no effect if a plan file is given to apply .
2014-07-12 06:30:40 +02:00
- state = path Path to read and save state ( unless state - out
is specified ) . Defaults to "terraform.tfstate" .
2014-06-19 06:36:44 +02:00
2014-07-12 06:30:40 +02:00
- state - out = path Path to write state to that is different than
"-state" . This can be used to preserve the old
state .
2014-05-24 21:27:58 +02:00
2015-03-24 17:18:15 +01:00
- target = resource Resource to target . Operation will be limited to this
resource and its dependencies . This flag can be used
multiple times .
2014-07-18 20:37:27 +02:00
- var ' foo = bar ' Set a variable in the Terraform configuration . This
flag can be set multiple times .
- var - file = foo Set variables in the Terraform configuration from
2017-06-22 03:22:07 +02:00
a file . If "terraform.tfvars" or any ".auto.tfvars"
files are present , they will be automatically loaded .
2014-07-18 20:37:27 +02:00
2014-05-24 21:27:58 +02:00
`
return strings . TrimSpace ( helpText )
}
2014-10-01 07:01:11 +02:00
func ( c * ApplyCommand ) helpDestroy ( ) string {
helpText := `
2021-02-02 16:35:45 +01:00
Usage : terraform destroy [ options ]
2014-10-01 07:01:11 +02:00
Destroy Terraform - managed infrastructure .
Options :
- backup = path Path to backup the existing state file before
modifying . Defaults to the "-state-out" path with
".backup" extension . Set to "-" to disable backup .
2018-02-01 01:14:42 +01:00
- auto - approve Skip interactive approval before destroying .
2017-02-06 16:07:32 +01:00
- lock = true Lock the state file when locking is supported .
2017-02-03 20:15:08 +01:00
2017-04-01 22:19:59 +02:00
- lock - timeout = 0 s Duration to retry a state lock .
2014-10-01 07:01:11 +02:00
- no - color If specified , output won ' t contain any color .
2015-10-06 00:18:03 +02:00
- parallelism = n Limit the number of concurrent operations .
Defaults to 10.
2014-10-01 07:01:11 +02:00
- refresh = true Update state prior to checking for differences . This
has no effect if a plan file is given to apply .
- state = path Path to read and save state ( unless state - out
is specified ) . Defaults to "terraform.tfstate" .
- state - out = path Path to write state to that is different than
"-state" . This can be used to preserve the old
state .
2015-03-24 17:18:15 +01:00
- target = resource Resource to target . Operation will be limited to this
resource and its dependencies . This flag can be used
multiple times .
2014-10-01 07:01:11 +02:00
- var ' foo = bar ' Set a variable in the Terraform configuration . This
flag can be set multiple times .
- var - file = foo Set variables in the Terraform configuration from
2017-06-22 03:22:07 +02:00
a file . If "terraform.tfvars" or any ".auto.tfvars"
files are present , they will be automatically loaded .
2014-10-01 07:01:11 +02:00
`
return strings . TrimSpace ( helpText )
2014-06-27 23:43:23 +02:00
}
2015-06-15 17:40:56 +02:00
2017-04-25 17:43:59 +02:00
const outputInterrupt = ` Interrupt received .
Please wait for Terraform to exit or data loss may occur .
Gracefully shutting down ... `