diff --git a/command/apply.go b/command/apply.go index eb2740e79c..36b66f677b 100644 --- a/command/apply.go +++ b/command/apply.go @@ -196,23 +196,24 @@ func (c *ApplyCommand) Help() string { func (c *ApplyCommand) Synopsis() string { if c.Destroy { - return "Destroy Terraform-managed infrastructure" + return "Destroy previously-created infrastructure" } - return "Builds or changes infrastructure" + return "Create or update infrastructure" } func (c *ApplyCommand) helpApply() string { helpText := ` -Usage: terraform apply [options] [DIR-OR-PLAN] +Usage: terraform apply [options] [PLAN] - Builds or changes infrastructure according to Terraform configuration - files in DIR. + Creates or updates infrastructure according to Terraform configuration + files in the current directory. - By default, apply scans the current directory for the configuration - and applies the changes appropriately. However, a path to another - configuration or an execution plan can be provided. Execution plans can be - used to only execute a pre-determined set of actions. + 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. Options: diff --git a/command/console.go b/command/console.go index 359d9dca06..c6f872b905 100644 --- a/command/console.go +++ b/command/console.go @@ -203,5 +203,5 @@ Options: } func (c *ConsoleCommand) Synopsis() string { - return "Interactive console for Terraform interpolations" + return "Try Terraform expressions at an interactive command prompt" } diff --git a/command/debug_command.go b/command/debug_command.go deleted file mode 100644 index 7058553b9f..0000000000 --- a/command/debug_command.go +++ /dev/null @@ -1,30 +0,0 @@ -package command - -import ( - "strings" - - "github.com/mitchellh/cli" -) - -// DebugCommand is a Command implementation that just shows help for -// the subcommands nested below it. -type DebugCommand struct { - Meta -} - -func (c *DebugCommand) Run(args []string) int { - return cli.RunResultHelp -} - -func (c *DebugCommand) Help() string { - helpText := ` -Usage: terraform debug [options] [args] - - This command has subcommands for debug output management -` - return strings.TrimSpace(helpText) -} - -func (c *DebugCommand) Synopsis() string { - return "Debug output management (experimental)" -} diff --git a/command/fmt.go b/command/fmt.go index 13e84a2187..ff59d2b9d5 100644 --- a/command/fmt.go +++ b/command/fmt.go @@ -526,7 +526,7 @@ Options: } func (c *FmtCommand) Synopsis() string { - return "Rewrites config files to canonical format" + return "Reformat your configuration in the standard style" } func bytesDiff(b1, b2 []byte, path string) (data []byte, err error) { diff --git a/command/get.go b/command/get.go index 238020a942..49cb207c33 100644 --- a/command/get.go +++ b/command/get.go @@ -54,6 +54,10 @@ Usage: terraform get [options] PATH already downloaded, it will not be redownloaded or checked for updates unless the -update flag is specified. + Module installation also happens automatically by default as part of + the "terraform init" command, so you should rarely need to run this + command separately. + Options: -update Check already-downloaded modules for available updates @@ -66,7 +70,7 @@ Options: } func (c *GetCommand) Synopsis() string { - return "Download and install modules for the configuration" + return "Install or upgrade remote Terraform modules" } func getModules(m *Meta, path string, upgrade bool) tfdiags.Diagnostics { diff --git a/command/graph.go b/command/graph.go index cdfaaa2e78..fba33c6f8a 100644 --- a/command/graph.go +++ b/command/graph.go @@ -190,5 +190,5 @@ Options: } func (c *GraphCommand) Synopsis() string { - return "Create a visual graph of Terraform resources" + return "Generate a Graphviz graph of the steps in an operation" } diff --git a/command/import.go b/command/import.go index f5891ed6dc..cf22946c5c 100644 --- a/command/import.go +++ b/command/import.go @@ -327,7 +327,7 @@ Options: } func (c *ImportCommand) Synopsis() string { - return "Import existing infrastructure into Terraform" + return "Associate existing infrastructure with a Terraform resource" } const importCommandInvalidAddressReference = `For information on valid syntax, see: diff --git a/command/init.go b/command/init.go index 6cd9a27bfc..e90449ca51 100644 --- a/command/init.go +++ b/command/init.go @@ -1052,7 +1052,7 @@ Options: } func (c *InitCommand) Synopsis() string { - return "Initialize a Terraform working directory" + return "Prepare your working directory for other commands" } const errInitConfigError = ` diff --git a/command/output.go b/command/output.go index e389c458c0..3f5cc2bea0 100644 --- a/command/output.go +++ b/command/output.go @@ -223,5 +223,5 @@ Options: } func (c *OutputCommand) Synopsis() string { - return "Read an output from a state file" + return "Show output values from your root module" } diff --git a/command/plan.go b/command/plan.go index 8064cad57d..dc578f42e8 100644 --- a/command/plan.go +++ b/command/plan.go @@ -193,12 +193,12 @@ func (c *PlanCommand) Help() string { helpText := ` Usage: terraform plan [options] [DIR] - Generates an execution plan for Terraform. + Generates a speculative execution plan, showing what actions Terraform + would take to apply the current configuration. This command will not + actually perform the planned actions. - This execution plan can be reviewed prior to running apply to get a - sense for what Terraform will do. Optionally, the plan can be saved to - a Terraform plan file, and apply can take this plan file to execute - this plan exactly. + You can optionally save the plan to a file, which you can then pass to + the "apply" command to perform exactly the actions described in the plan. Options: @@ -249,5 +249,5 @@ Options: } func (c *PlanCommand) Synopsis() string { - return "Generate and show an execution plan" + return "Show changes required by the current configuration" } diff --git a/command/providers.go b/command/providers.go index 918fd841e3..d2042d122b 100644 --- a/command/providers.go +++ b/command/providers.go @@ -21,7 +21,7 @@ func (c *ProvidersCommand) Help() string { } func (c *ProvidersCommand) Synopsis() string { - return "Prints a tree of the providers used in the configuration" + return "Show the providers required for this configuration" } func (c *ProvidersCommand) Run(args []string) int { diff --git a/command/providers_lock.go b/command/providers_lock.go index 38bf2184ae..74f23cef09 100644 --- a/command/providers_lock.go +++ b/command/providers_lock.go @@ -23,7 +23,7 @@ type ProvidersLockCommand struct { } func (c *ProvidersLockCommand) Synopsis() string { - return "Creates or updates dependency locks for providers in the configuration" + return "Write out dependency locks for the configured providers" } func (c *ProvidersLockCommand) Run(args []string) int { diff --git a/command/providers_mirror.go b/command/providers_mirror.go index 029b086304..a2367707a0 100644 --- a/command/providers_mirror.go +++ b/command/providers_mirror.go @@ -24,7 +24,7 @@ type ProvidersMirrorCommand struct { } func (c *ProvidersMirrorCommand) Synopsis() string { - return "Mirrors the provider plugins needed for the current configuration" + return "Save local copies of all required provider plugins" } func (c *ProvidersMirrorCommand) Run(args []string) int { diff --git a/command/providers_schema.go b/command/providers_schema.go index 60e4c4c39f..00634cf2f9 100644 --- a/command/providers_schema.go +++ b/command/providers_schema.go @@ -20,7 +20,7 @@ func (c *ProvidersSchemaCommand) Help() string { } func (c *ProvidersSchemaCommand) Synopsis() string { - return "Prints the schemas of the providers used in the configuration" + return "Show schemas for the providers used in the configuration" } func (c *ProvidersSchemaCommand) Run(args []string) int { diff --git a/command/refresh.go b/command/refresh.go index 4ab3932f4b..36c40633fc 100644 --- a/command/refresh.go +++ b/command/refresh.go @@ -154,5 +154,5 @@ Options: } func (c *RefreshCommand) Synopsis() string { - return "Update local state file against real resources" + return "Update the state to match remote systems" } diff --git a/command/show.go b/command/show.go index 3bf034c9e1..56d0e34b9e 100644 --- a/command/show.go +++ b/command/show.go @@ -209,7 +209,7 @@ Options: } func (c *ShowCommand) Synopsis() string { - return "Inspect Terraform state or plan" + return "Show the current state or a saved plan" } // getPlanFromPath returns a plan and statefile if the user-supplied path points diff --git a/command/taint.go b/command/taint.go index 04a5bf1f10..ad4f10f06d 100644 --- a/command/taint.go +++ b/command/taint.go @@ -201,21 +201,27 @@ func (c *TaintCommand) Help() string { helpText := ` Usage: terraform taint [options]
- Manually mark a resource as tainted, forcing a destroy and recreate - on the next plan/apply. + Terraform uses the term "tainted" to describe a resource instance + which may not be fully functional, either because its creation + partially failed or because you've manually marked it as such using + this command. - This will not modify your infrastructure. This command changes your - state to mark a resource as tainted so that during the next plan or - apply that resource will be destroyed and recreated. This command on - its own will not modify infrastructure. This command can be undone - using the "terraform untaint" command with the same address. + This will not modify your infrastructure directly, but subsequent + Terraform plans will include actions to destroy the remote object + and create a new object to replace it. - The address is in the usual resource address syntax, as shown in - the output from other commands, such as: + You can remove the "taint" state from a resource instance using + the "terraform untaint" command. + + The address is in the usual resource address syntax, such as: aws_instance.foo aws_instance.bar[1] module.foo.module.bar.aws_instance.baz + Use your shell's quoting or escaping syntax to ensure that the + address will reach Terraform correctly, without any special + interpretation. + Options: -allow-missing If specified, the command will succeed (exit code 0) @@ -240,7 +246,7 @@ Options: } func (c *TaintCommand) Synopsis() string { - return "Manually mark a resource for recreation" + return "Mark a resource instance as not fully functional" } func (c *TaintCommand) allowMissingExit(name addrs.AbsResourceInstance) int { diff --git a/command/unlock.go b/command/unlock.go index 94b2f7d8f2..6376fd0f6d 100644 --- a/command/unlock.go +++ b/command/unlock.go @@ -121,7 +121,7 @@ Usage: terraform force-unlock LOCK_ID [DIR] Manually unlock the state for the defined configuration. This will not modify your infrastructure. This command removes the lock on the - state for the current configuration. The behavior of this lock is dependent + state for the current workspace. The behavior of this lock is dependent on the backend being used. Local state files cannot be unlocked by another process. @@ -133,7 +133,7 @@ Options: } func (c *UnlockCommand) Synopsis() string { - return "Manually unlock the terraform state" + return "Release a stuck lock on the current workspace" } const outputUnlockSuccess = ` diff --git a/command/untaint.go b/command/untaint.go index 2f91d44829..96493bcb0c 100644 --- a/command/untaint.go +++ b/command/untaint.go @@ -175,14 +175,17 @@ func (c *UntaintCommand) Help() string { helpText := ` Usage: terraform untaint [options] name - Manually unmark a resource as tainted, restoring it as the primary - instance in the state. This reverses either a manual 'terraform taint' - or the result of provisioners failing on a resource. + Terraform uses the term "tainted" to describe a resource instance + which may not be fully functional, either because its creation + partially failed or because you've manually marked it as such using + the "terraform taint" command. - This will not modify your infrastructure. This command changes your - state to unmark a resource as tainted. This command can be undone by - reverting the state backup file that is created, or by running - 'terraform taint' on the resource. + This command removes that state from a resource instance, causing + Terraform to see it as fully-functional and not in need of + replacement. + + This will not modify your infrastructure directly. It only avoids + Terraform planning to replace a tainted instance in a future operation. Options: @@ -212,7 +215,7 @@ Options: } func (c *UntaintCommand) Synopsis() string { - return "Manually unmark a resource as tainted" + return "Remove the 'tainted' state from a resource instance" } func (c *UntaintCommand) allowMissingExit(name addrs.AbsResourceInstance) int { diff --git a/command/validate.go b/command/validate.go index e9c8914de0..6519a5db9b 100644 --- a/command/validate.go +++ b/command/validate.go @@ -235,7 +235,7 @@ func (c *ValidateCommand) showResults(diags tfdiags.Diagnostics, jsonOutput bool } func (c *ValidateCommand) Synopsis() string { - return "Validates the Terraform files" + return "Check whether the configuration is valid" } func (c *ValidateCommand) Help() string { diff --git a/command/version.go b/command/version.go index b20cc4c6a3..cbece20ac9 100644 --- a/command/version.go +++ b/command/version.go @@ -169,5 +169,5 @@ func (c *VersionCommand) Run(args []string) int { } func (c *VersionCommand) Synopsis() string { - return "Prints the Terraform version" + return "Show the current Terraform version" } diff --git a/commands.go b/commands.go index 1e947d681f..dd6010ce10 100644 --- a/commands.go +++ b/commands.go @@ -25,7 +25,23 @@ const runningInAutomationEnvName = "TF_IN_AUTOMATION" // Commands is the mapping of all the available Terraform commands. var Commands map[string]cli.CommandFactory -var PlumbingCommands map[string]struct{} + +// PrimaryCommands is an ordered sequence of the top-level commands (not +// subcommands) that we emphasize at the top of our help output. This is +// ordered so that we can show them in the typical workflow order, rather +// than in alphabetical order. Anything not in this sequence or in the +// HiddenCommands set appears under "all other commands". +var PrimaryCommands []string + +// HiddenCommands is a set of top-level commands (not subcommands) that are +// not advertised in the top-level help at all. This is typically because +// they are either just stubs that return an error message about something +// no longer being supported or backward-compatibility aliases for other +// commands. +// +// No commands in the PrimaryCommands sequence should also appear in the +// HiddenCommands set, because that would be rather silly. +var HiddenCommands map[string]struct{} // Ui is the cli.Ui used for communicating to the outside world. var Ui cli.Ui @@ -89,19 +105,10 @@ func initCommands( // The command list is included in the terraform -help // output, which is in turn included in the docs at - // website/source/docs/commands/index.html.markdown; if you + // website/docs/commands/index.html.markdown; if you // add, remove or reclassify commands then consider updating // that to match. - PlumbingCommands = map[string]struct{}{ - "state": struct{}{}, // includes all subcommands - "debug": struct{}{}, // includes all subcommands - "force-unlock": struct{}{}, - "push": struct{}{}, - "0.12upgrade": struct{}{}, - "0.13upgrade": struct{}{}, - } - Commands = map[string]cli.CommandFactory{ "apply": func() (cli.Command, error) { return &command.ApplyCommand{ @@ -339,12 +346,6 @@ func initCommands( }, nil }, - "debug": func() (cli.Command, error) { - return &command.DebugCommand{ - Meta: meta, - }, nil - }, - "force-unlock": func() (cli.Command, error) { return &command.UnlockCommand{ Meta: meta, @@ -403,6 +404,23 @@ func initCommands( }, nil }, } + + PrimaryCommands = []string{ + "init", + "validate", + "plan", + "apply", + "destroy", + } + + HiddenCommands = map[string]struct{}{ + "0.12upgrade": struct{}{}, + "0.13upgrade": struct{}{}, + "env": struct{}{}, + "internal-plugin": struct{}{}, + "push": struct{}{}, + } + } // makeShutdownCh creates an interrupt listener and returns a channel. diff --git a/help.go b/help.go index e020edea9c..64eb032732 100644 --- a/help.go +++ b/help.go @@ -13,20 +13,32 @@ import ( // helpFunc is a cli.HelpFunc that can is used to output the help for Terraform. func helpFunc(commands map[string]cli.CommandFactory) string { // Determine the maximum key length, and classify based on type - porcelain := make(map[string]cli.CommandFactory) - plumbing := make(map[string]cli.CommandFactory) + var otherCommands []string maxKeyLen := 0 - for key, f := range commands { + + for key := range commands { + if _, ok := HiddenCommands[key]; ok { + // We don't consider hidden commands when deciding the + // maximum command length. + continue + } + if len(key) > maxKeyLen { maxKeyLen = len(key) } - if _, ok := PlumbingCommands[key]; ok { - plumbing[key] = f - } else { - porcelain[key] = f + isOther := true + for _, candidate := range PrimaryCommands { + if candidate == key { + isOther = false + break + } + } + if isOther { + otherCommands = append(otherCommands, key) } } + sort.Strings(otherCommands) // The output produced by this is included in the docs at // website/source/docs/commands/index.html.markdown; if you @@ -35,62 +47,47 @@ func helpFunc(commands map[string]cli.CommandFactory) string { Usage: terraform [global options] [args] The available commands for execution are listed below. -The most common, useful commands are shown first, followed by -less common or more advanced commands. If you're just getting -started with Terraform, stick with the common commands. For the -other commands, please read the help and docs before usage. +The primary workflow commands are given first, followed by +less common or more advanced commands. -Common commands: +Main commands: %s All other commands: %s - Global options (use these before the subcommand, if any): - -chdir=DIR Switch to a different working directory before executing - the given subcommand. - -help Show this help output, or the help for a specified - subcommand. - -version An alias for the "version" subcommand. -`, listCommands(porcelain, maxKeyLen), listCommands(plumbing, maxKeyLen)) + -chdir=DIR Switch to a different working directory before executing the + given subcommand. + -help Show this help output, or the help for a specified subcommand. + -version An alias for the "version" subcommand. +`, listCommands(commands, PrimaryCommands, maxKeyLen), listCommands(commands, otherCommands, maxKeyLen)) return strings.TrimSpace(helpText) } // listCommands just lists the commands in the map with the // given maximum key length. -func listCommands(commands map[string]cli.CommandFactory, maxKeyLen int) string { +func listCommands(allCommands map[string]cli.CommandFactory, order []string, maxKeyLen int) string { var buf bytes.Buffer - // Get the list of keys so we can sort them, and also get the maximum - // key length so they can be aligned properly. - keys := make([]string, 0, len(commands)) - for key, _ := range commands { - // This is an internal command that users should never call directly so - // we will hide it from the command listing. - if key == "internal-plugin" { - continue - } - keys = append(keys, key) - } - sort.Strings(keys) - - for _, key := range keys { - commandFunc, ok := commands[key] + for _, key := range order { + commandFunc, ok := allCommands[key] if !ok { - // This should never happen since we JUST built the list of - // keys. + // This suggests an inconsistency in the command table definitions + // in commands.go . panic("command not found: " + key) } command, err := commandFunc() if err != nil { + // This would be really weird since there's no good reason for + // any of our command factories to fail. log.Printf("[ERR] cli: Command '%s' failed to load: %s", key, err) continue } key = fmt.Sprintf("%s%s", key, strings.Repeat(" ", maxKeyLen-len(key))) - buf.WriteString(fmt.Sprintf(" %s %s\n", key, command.Synopsis())) + buf.WriteString(fmt.Sprintf(" %s %s\n", key, command.Synopsis())) } return buf.String() diff --git a/website/docs/commands/index.html.markdown b/website/docs/commands/index.html.markdown index 4617ebb617..2f8ee2a4e2 100644 --- a/website/docs/commands/index.html.markdown +++ b/website/docs/commands/index.html.markdown @@ -3,86 +3,79 @@ layout: "docs" page_title: "Commands" sidebar_current: "docs-commands" description: |- - Terraform is controlled via a very easy to use command-line interface (CLI). Terraform is only a single command-line application: terraform. This application then takes a subcommand such as "apply" or "plan". The complete list of subcommands is in the navigation to the left. + Main usage information for the Terraform CLI tool. --- # Terraform Commands (CLI) > **Hands-on:** Try the [Terraform: Get Started](https://learn.hashicorp.com/collections/terraform/aws-get-started?utm_source=WEBSITE&utm_medium=WEB_IO&utm_offer=ARTICLE_PAGE&utm_content=DOCS) collection on HashiCorp Learn. -Terraform is controlled via a very easy to use command-line interface (CLI). -Terraform is only a single command-line application: terraform. This application -then takes a subcommand such as "apply" or "plan". The complete list of subcommands -is in the navigation to the left. +The command line interface to Terraform is via the `terraform` command, which +accepts a variety of subcommands such as `terraform init` or `terraform plan`. +A full list of all of the supported subcommands is in the navigation section +of this page. -The terraform CLI is a well-behaved command line application. In erroneous cases, -a non-zero exit status will be returned. It also responds to -h and --help as you'd -most likely expect. +We refer to the `terraform` command line tool as "Terraform CLI" elsewhere +in the documentation. This terminology is often used to distinguish it from +other components you might use in the Terraform product family, such as +[Terraform Cloud](/docs/cloud/) or +the various [Terraform providers](/docs/providers/), which are developed and +released separately from Terraform CLI. -To view a list of the available commands at any time, just run terraform with no arguments: +To view a list of the commands available in your current Terraform version, +run `terraform` with no additional arguments: ```text Usage: terraform [global options] [args] The available commands for execution are listed below. -The most common, useful commands are shown first, followed by -less common or more advanced commands. If you're just getting -started with Terraform, stick with the common commands. For the -other commands, please read the help and docs before usage. - -Common commands: - apply Builds or changes infrastructure - console Interactive console for Terraform interpolations - destroy Destroy Terraform-managed infrastructure - env Workspace management - fmt Rewrites config files to canonical format - get Download and install modules for the configuration - graph Create a visual graph of Terraform resources - import Import existing infrastructure into Terraform - init Initialize a Terraform working directory - login Obtain and save credentials for a remote host - logout Remove locally-stored credentials for a remote host - output Read an output from a state file - plan Generate and show an execution plan - providers Prints a tree of the providers used in the configuration - refresh Update local state file against real resources - show Inspect Terraform state or plan - taint Manually mark a resource for recreation - untaint Manually unmark a resource as tainted - validate Validates the Terraform files - version Prints the Terraform version - workspace Workspace management +The primary workflow commands are given first, followed by +less common or more advanced commands. -All other commands: - debug Debug output management (experimental) - force-unlock Manually unlock the terraform state - state Advanced state management +Main commands: + init Prepare your working directory for other commands + validate Check whether the configuration is valid + plan Show changes required by the current configuration + apply Create or update infrastructure + destroy Destroy previously-created infrastructure +All other commands: + console Try Terraform expressions at an interactive command prompt + fmt Reformat your configuration in the standard style + force-unlock Release a stuck lock on the current workspace + get Install or upgrade remote Terraform modules + graph Generate a Graphviz graph of the steps in an operation + import Associate existing infrastructure with a Terraform resource + login Obtain and save credentials for a remote host + logout Remove locally-stored credentials for a remote host + output Show output values from your root module + providers Show the providers required for this configuration + refresh Update the state to match remote systems + show Show the current state or a saved plan + state Advanced state management + taint Mark a resource instance as not fully functional + untaint Remove the 'tainted' state from a resource instance + version Show the current Terraform version + workspace Workspace management Global options (use these before the subcommand, if any): - -chdir=DIR Switch to a different working directory before executing - the given subcommand. - -help Show this help output, or the help for a specified - subcommand. - -version An alias for the "version" subcommand. + -chdir=DIR Switch to a different working directory before executing the + given subcommand. + -help Show this help output, or the help for a specified subcommand. + -version An alias for the "version" subcommand. ``` -To get help for any specific command, use the -help option to the relevant -subcommand. For example, to see help about the graph subcommand: +(The output from your current Terraform version may be different than the +above example.) -```text -$ terraform graph -help -Usage: terraform graph [options] PATH +To get specific help for any specific command, use the `-help` option with the +relevant subcommand. For example, to see help about the "validate" subcommand +you can run `terraform validate -help`. - Outputs the visual graph of Terraform resources. If the path given is - the path to a configuration, the dependency graph of the resources are - shown. If the path is a plan file, then the dependency graph of the - plan itself is shown. - - The graph is outputted in DOT format. The typical program that can - read this format is GraphViz, but many web services are also available - to read this format. -``` +The inline help built in to Terraform CLI describes the most important +characteristics of each command. For more detailed information, refer to each +command's section of this documentation, available in the navigation +section of this page. ## Switching working directory with `-chdir`