Terraform: Support for running Terraform with a configuration directory other than PWD is inconsistent between commands

Created on 8 Aug 2017  ยท  11Comments  ยท  Source: hashicorp/terraform

Terraform Version

Terraform v0.10.0

Terraform Configuration Files

See https://github.com/hashicorp/terraform/issues/15759#issuecomment-321031623 for an example of my remote config

Expected Behavior

Given terraform output in project root with remote state configuration, I would expect terraform to transparently give me output as it is in the remote state.

Actual Behavior

I receive a message starting with

Backend reinitialization required. Please run "terraform init".
...

Steps to Reproduce

Please list the steps required to reproduce the issue, for example:

  1. After a terraform init with remote state configuration of: https://github.com/hashicorp/terraform/issues/15759#issuecomment-321031623
  2. then terraform apply
  3. outpus are displayed on the screen as usual
  4. subsequent calls with terraform output give reinitialization message.

Important Factoids

The local .terraform folder contains state without the outputs terraform apply gives.

My use-case here is a build tool pipes the outputs for further configuring with tools outside of terraform (arns, ids, etc.)

cli enhancement

Most helpful comment

Excellent, I can live with this. Verified your suggestion.

I created a root.tf file in project root containing only:

terraform {
  backend "s3" {}
}

executed terraform output and the rest was inferred. I got my value.

To be clear, wasn't attempting to give it a directory path. I expected it to know of the .terraform in the same directory it was being executed. But I get what you are saying.

All 11 comments

Hi @cantide5ga,

Thanks for filing this!

While I've found a minor code issue related to this (it's actually caught and fixed in the code, and surfaces as a warning), I can't seem to reproduce this behavior.

$ terraform init  -backend-config=backend.hcl

Initializing the backend...

Successfully configured the backend "s3"!
<snip>
$ terraform apply

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

Outputs:

out = something
$ terraform output
out = something

Are you running the exact commands shown, with no arguments, consecutively in the same directory?

Can you show a complete configuration that does this?

hi again @jbardin

Can you show a complete configuration that does this?

I'll try to reduce my project to isolate. I heavily rely on reusable modules both local and remote. In the mean time:

Are you running the exact commands shown, with no arguments, consecutively in the same directory?

Yes in that order, but slight differ in commands. I'm running from root and with both init and apply I'm specifying a directory. The .terraform folder is still generated in the root fyi.

I'm specifying a directory

Ah, that explains it. The output command can't take a directory argument:

Usage: terraform output [options] [NAME]

Unfortunately that means that the output command might not work when the initialized directory is not the same as the root config module.

As a workaround, you could duplicate the "terraform" block from your configuration in the initialized directory. That should allow the output command to load the config in order to read the state.

Excellent, I can live with this. Verified your suggestion.

I created a root.tf file in project root containing only:

terraform {
  backend "s3" {}
}

executed terraform output and the rest was inferred. I got my value.

To be clear, wasn't attempting to give it a directory path. I expected it to know of the .terraform in the same directory it was being executed. But I get what you are saying.

I can confirm this is a bug/regression from previous versions of TF. In my case, the pattern I follow is

$> git clone <some TF code repo> deploy
$> terraform init deploy
$> terraform plan deploy
$> terraform apply deploy
$> terraform show
Backend reinitialization required. Please run "terraform init".
Reason: Unsetting the previously set backend "s3"

The "backend" is the interface that Terraform uses to store state,
perform operations, etc. If this message is showing up, it means that the
Terraform configuration you're using is using a custom configuration for
the Terraform backend.

Changes to backend configurations require reinitialization. This allows
Terraform to setup the new configuration, copy existing state, etc. This is
only done during "terraform init". Please run that command now then try again.

If the change reason above is incorrect, please verify your configuration
hasn't changed and try again. At this point, no changes to your existing
configuration or state have been made.

Failed to load backend: Initialization required. Please see the error message above.

Workaround above works, but feels like a bug to me

Creating a root.tf in my project root also worked for me (using gcs backend) however it feels like a workaround for a bug.

Why does terraform output not take a directory argument like init, apply, plan, etc. do?

@matalo33,

The directory argument for many commands is somewhat of a legacy mode of operation, especially since Terraform stores and locates local data relative to the current working directory. Commands like output, taint, untaint and import also take specific positional arguments, which may preclude them from taking a directory argument in some cases.

We're planning on refactoring the cli directory handling in a future release to make the commands more consistent.

Yes, I can reproduce it. It's a bug for both terraform show and terraform output. Thanks @jbardin @cantide5ga for your input. I can at least make it work for now.

The workaround works also for the terraform taint command.

I am trying to apply this workaround but I am probably missing something, here is my directory structure:

โ”œโ”€โ”€ dev
โ”‚ย ย  โ”œโ”€โ”€ backend.tfvars
โ”‚ย ย  โ”œโ”€โ”€ environment.tfvars
โ”‚ย ย  โ”œโ”€โ”€ plan.tfplan
โ”‚ย ย  โ””โ”€โ”€ .terraform
โ”‚ย ย      โ”œโ”€โ”€ modules
โ”‚ย ย      โ”‚ย ย  โ”œโ”€โ”€ 646d7caaf2abe555e4b77f561f0642af -> ......
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ modules.json
โ”‚ย ย      โ”œโ”€โ”€ plugin_path
โ”‚ย ย      โ”œโ”€โ”€ plugins
โ”‚ย ย      โ”‚ย ย  โ””โ”€โ”€ linux_amd64
โ”‚ย ย      โ”‚ย ย      โ””โ”€โ”€ lock.json
โ”‚ย ย      โ””โ”€โ”€ terraform.tfstate
โ”œโ”€โ”€ .gitignore
โ”œโ”€โ”€ main.tf
โ”œโ”€โ”€ outputs.tf
โ””โ”€โ”€ vars.tf

I am keeping entire TF specs in the root and have specific dev/prod etc directories with tfvars files for backend and environment. I always run terraform from within the dev or prod directories (this allows me to reuse same main.tf etc from root but keep state .terraform directories in dev/prod). So all my init apply etc calls are done with a directory parameter ...

How do I apply the workaround mentioned here in my case? I tried putting above mentioned root.tf inside dev to no avail

Just getting started with terraform, following the pattern layed out here:
https://medium.com/hdeblog/terraform-sane-practices-project-structure-c4347c1bc0f1

...This means each environment gets it's own tfstate file on the remote backend (in my case different keys in S3)... which to me means it's essential that output and show (others?) take a directory argument. Otherwise you'd have to copy the environment you want every time you run the command.

RE: @jbardin "The directory argument for many commands is somewhat of a legacy mode of operation, especially since Terraform stores and locates local data relative to the current working directory."

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nevir picture nevir  ยท  82Comments

gwagner picture gwagner  ยท  81Comments

mirogta picture mirogta  ยท  74Comments

atkinchris picture atkinchris  ยท  68Comments

ncraike picture ncraike  ยท  77Comments