#compdef terraform

local -a _terraform_cmds
_terraform_cmds=(
    'apply:Builds or changes infrastructure'
    'destroy:Destroy Terraform-managed infrastructure'
    'get:Download and install modules for the configuration'
    'graph:Create a visual graph of Terraform resources'
    'init:Initializes Terraform configuration from a module'
    'output:Read an output from a state file'
    'plan:Generate and show an execution plan'
    'pull:Refreshes the local state copy from the remote server'
    'push:Uploads the local state to the remote server'
    'refresh:Update local state file against real resources'
    'remote:Configures remote state management'
    'show:Inspect Terraform state or plan'
    'taint:Manually forcing a destroy and recreate on the next plan/apply'
    'version:Prints the Terraform version'
)

__apply() {
    _arguments \
        '-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.]' \
        '-input=[(true) Ask for input for variables if not directly set.]' \
        '-no-color[If specified, output will not contain any color.]' \
        '-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.]' \
        '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]' \
        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
}

__destroy() {
    _arguments \
        '-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.]' \
        '-force[If set, then the destroy confirmation will not be shown.]' \
        '-input=[(true) Ask for input for variables if not directly set.]' \
        '-no-color[If specified, output will not contain any color.]' \
        '-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.]' \
        '-target=[(resource) Instead of affecting "dependencies" will instead also destroy any resources that depend on the target(s) specified.]' \
        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
}

__get() {
    _arguments \
        '-update=[(false) If true, modules already downloaded will be checked for updates and updated if necessary.]'
}

__graph() {
    _arguments \
        '-draw-cycles[Highlight any cycles in the graph with colored edges. This helps when diagnosing cycle errors.]' \
        '-module-depth=[(n) The maximum depth to expand modules. By default this is zero, which will not expand modules at all.]' \
        '-verbose[Generate a verbose, "worst-case" graph, with all nodes for potential operations in place.]'
}

__init() {
    _arguments \
        '-address=[(url) URL of the remote storage server. Required for HTTP backend, optional for Atlas and Consul.]' \
        '-access-token=[(token) Authentication token for state storage server. Required for Atlas backend, optional for Consul.]' \
        '-backend=[(atlas) Specifies the type of remote backend. Must be one of Atlas, Consul, or HTTP. Defaults to atlas.]' \
        '-name=[(name) Name of the state file in the state storage server. Required for Atlas backend.]' \
        '-path=[(path) Path of the remote state in Consul. Required for the Consul backend.]'
}

__output() {
    _arguments \
        '-state=[(path) Path to the state file to read. Defaults to "terraform.tfstate".]' \
        '-module=[(module_name) The module path which has needed output. By default this is the root path. Other modules can be specified by a period-separated list.]'
}

__plan() {
    _arguments \
        '-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.]' \
        '-destroy[If set, a plan will be generated to destroy all resources managed by the given configuration and state.]' \
        '-detailed-exitcode[Return a detailed exit code when the command exits. When provided, this argument changes the exit codes and their meanings to provide more granular information about what the resulting plan contains]' \
        '-input=[(true) Ask for input for variables if not directly set.]' \
        '-module-depth=[(n) Specifies the depth of modules to show in the output. This does not affect the plan itself, only the output shown. By default, this is zero. -1 will expand all.]' \
        '-no-color[If specified, output will not contain any color.]' \
        '-out=[(path) Write a plan file to the given path. This can be used as input to the "apply" command.]' \
        '-refresh=[(true) Update state prior to checking for differences.]' \
        '-state=[(statefile) Path to a Terraform state file to use to look up Terraform-managed resources. By default it will use the state "terraform.tfstate" if it exists.]' \
        '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]' \
        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
}

__push() {
    _arguments \
        '-atlas-address=[(url) An alternate address to an Atlas instance. Defaults to https://atlas.hashicorp.com.]' \
        '-upload-modules=[(true) If true (default), then the modules being used are all locked at their current checkout and uploaded completely to Atlas. This prevents Atlas from running terraform get for you.]' \
        '-name=[(name) Name of the infrastructure configuration in Atlas. The format of this is: "username/name" so that you can upload configurations not just to your account but to other accounts and organizations. This setting can also be set in the configuration in the Atlas section.]' \
        '-no-color[Disables output with coloring]' \
        '-overwrite=[(foo) Marks a specific variable to be updated on Atlas. Normally, if a variable is already set in Atlas, Terraform will not send the local value (even if it is different). This forces it to send the local value to Atlas. This flag can be repeated multiple times.]' \
        '-token=[(token) Atlas API token to use to authorize the upload. If blank or unspecified, the ATLAS_TOKEN environmental variable will be used.]' \
        '-var=[("foo=bar") Set the value of a variable for the Terraform configuration.]' \
        '-var-file=[(foo) Set the value of variables using a variable file.]' \
        '-vcs=[(true) If true (default), then Terraform will detect if a VCS is in use, such as Git, and will only upload files that are committed to version control. If no version control system is detected, Terraform will upload all files in path (parameter to the command).]'
}

__refresh() {
    _arguments \
        '-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.]' \
        '-no-color[If specified, output will not contain any color.]' \
        '-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.]' \
        '-target=[(resource) A Resource Address to target. Operation will be limited to this resource and its dependencies. This flag can be used multiple times.]' \
        '-var[("foo=bar") Set a variable in the Terraform configuration. This flag can be set multiple times.]' \
        '-var-file=[(path) Set variables in the Terraform configuration from a file. If "terraform.tfvars" is present, it will be automatically loaded if this flag is not specified.]'
}

__remote() {
    _arguments \
        '-address=[(url) URL of the remote storage server. Required for HTTP backend, optional for Atlas and Consul.]' \
        '-access-token=[(token) Authentication token for state storage server. Required for Atlas backend, optional for Consul.]' \
        '-backend=[(atlas) Specifies the type of remote backend. Must be one of Atlas, Consul, or HTTP. Defaults to atlas.]' \
        '-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.]' \
        '-disable[Disables remote state management and migrates the state to the -state path.]' \
        '-name=[(name) Name of the state file in the state storage server. Required for Atlas backend.]' \
        '-path=[(path) Path of the remote state in Consul. Required for the Consul backend.]' \
        '-pull=[(true) Controls if the remote state is pulled before disabling. This defaults to true to ensure the latest state is cached before disabling.]' \
        '-state=[(path) Path to read and save state (unless state-out is specified). Defaults to "terraform.tfstate".]'
}

__show() {
    _arguments \
        '-module-depth=[(n) The maximum depth to expand modules. By default this is zero, which will not expand modules at all.]' \
        '-no-color[If specified, output will not contain any color.]'
}

__taint() {
    _arguments \
        '-allow-missing[If specified, the command will succeed (exit code 0) even if the resource is missing.]' \
        '-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.]' \
        '-module=[(path)  The module path where the resource lives. By default this will be root. Child modules can be specified by names. Ex. "consul" or "consul.vpc" (nested modules).]' \
        '-no-color[If specified, output will not contain any color.]' \
        '-state=[(path) Path to read and save state (unless state-out is  specified). Defaults to "terraform.tfstate".]' \
        '-state-out=[(path) Path to write updated state file. By default, the "-state" path will be used.]'
}

_arguments '*:: :->command'

if (( CURRENT == 1 )); then
  _describe -t commands "terraform command" _terraform_cmds
  return
fi

local -a _command_args
case "$words[1]" in
  apply)
    __apply ;;
  destroy)
    __destroy ;;
  get)
    __get ;;
  graph)
    __graph ;;
  init)
    __init ;;
  output)
    __output ;;
  plan)
    __plan ;;
  push)
    __push ;;
  refresh)
    __refresh ;;
  remote)
    __remote ;;
  show)
    __show ;;
  taint)
    __taint ;;
esac
