Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error #131

Open
leros321 opened this issue Oct 25, 2019 · 19 comments
Open

Comments

@leros321
Copy link

leros321 commented Oct 25, 2019

After destroying our openstack instance with terraform v0.12.10 then terraform-inventory v0.9 crash with following message and our pipeline cannot continue:
Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)
Of course, we understand terraform.tfstate is empty, but it did not happen with terraform v0.11.14 and terraform-inventory v0.8
Below is terraform.tfstate:
{ "version": 4, "terraform_version": "0.12.10", "serial": 12, "lineage": "24894aa7-228d-1dc3-0120-42a4be3cdc57", "outputs": {}, "resources": [] }

@paulmao1
Copy link

+1

1 similar comment
@qasimraz
Copy link

qasimraz commented Nov 5, 2019

+1

@justinas
Copy link

justinas commented Nov 6, 2019

Looks like by default Terraform tries to directly read terraform.tfstate which matches the output of terraform state pull. However, terraform show -json produces a different JSON, where resources are nested under .values.root_module, like the program expects for a 0.12+ file.

I was able to make it work by setting a var:

export TF_STATE=.

By pointing terraform-inventory to a directory instead of a file, it takes a completely different code path that properly utilizes terraform show -json.

I am not sure what the best fix would be here. Maybe terraform-inventory should default to terraform show -json at all times?

@screenman
Copy link

+1

@paulmao1
Copy link

paulmao1 commented Nov 8, 2019 via email

@paulmao1
Copy link

paulmao1 commented Nov 8, 2019 via email

@sprnza
Copy link

sprnza commented Dec 30, 2019

The proposed workaround doesn't work for me for some reason:
Terraform v0.12.18
terraform-ansible a408e89

@justinas
Copy link

justinas commented Dec 30, 2019

Seems to work for me:

$ terraform version
Terraform v0.12.18
+ provider.digitalocean v1.12.0
$ terraform-inventory --list
Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)
$ TF_STATE=. terraform-inventory --list
{"all":{"hosts":["185.14.185.236"],"vars":{}},"test1":["185.14.185.236"],"test1_0":["185.14.185.236"],"type_digitalocean_droplet":["185.14.185.236"]}
$ TF_STATE=. ansible -i $(which terraform-inventory) -u root -m ping all
185.14.185.236 | SUCCESS => {
    "changed": false,
    "ping": "pong"
}

terraform.tf

provider "digitalocean" {}

data "digitalocean_ssh_key" "j" {
  name = "j"
}

resource "digitalocean_droplet" "test1" {
    name = "test1"
    region = "ams2"
    size = "s-1vcpu-1gb"
    image = "ubuntu-18-04-x64"
    ssh_keys = [data.digitalocean_ssh_key.j.id]

    provisioner "remote-exec" {
        inline = [
            "apt update",
            "apt install -y python3",
        ]
    }
}

@sprnza
Copy link

sprnza commented Dec 30, 2019

Yep, sorry it appeared to be this issue #133

@EugenDueck
Copy link

EugenDueck commented Feb 29, 2020

I'm getting the same error. The TF_STATE=. workaround does not work for me. I tried terraform-inventory 0.9 and HEAD -> master as of Feb 29 (c7e468f).

$ terraform-inventory --inventory

Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)

$ TF_STATE=. terraform-inventory --inventory

Error reading Terraform state: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)

$ terraform-inventory --version

terraform-inventory version 0.9

$ terraform --version

Terraform v0.12.21
+ provider.aws v2.51.0
+ provider.random v2.2.1

$ cat terraform.tfstate

{
  "version": 4,
  "terraform_version": "0.12.21",
  "serial": 32,
  "lineage": "72c6e67a-e500-430a-341e-dab290bbf342",
  "outputs": {},
  "resources": []
}

@justinas
Copy link

justinas commented Apr 2, 2020

Hi again everyone.

I have summarized the format differences below.


Terraform 0.11

A: state pull & terraform.tfstate

{
  "version": 3,
  "terraform_version": "0.11.14",
  "serial": 1,
  "lineage": "3c9951c1-3229-ca05-2cf3-25d8472a9d51",
  "modules": [
	{
	  "path": [
		"root"
	  ],
	  "outputs": {},
	  "resources": {
		"digitalocean_droplet.hanginx.0": {...}
	  }
	}
  ]
}

Terraform 0.12

B: show -json

{
  "format_version": "0.1",
  "terraform_version": "0.12.24",
  "values": {
	"root_module": {
	  "resources": [
		{...}
      ]
    }
  }
}

C: state pull & terraform.tfstate

{
  "version": 4,
  "terraform_version": "0.12.24",
  "serial": 6,
  "lineage": "1239f061-72f1-7e7b-161a-cb4bf72005f1",
  "outputs": {},
  "resources": [
	{...}
  ]
}

The problem right now is that TI tries to use terraform show -json but it can not actually parse that output (!!!)

Edit: the above statement is false. For 0.11 we support state pull or terraform.tfstate (the same format). For 0.12 we only support show -json, but not terraform.tfstate. Yet, we still try to read that file directly, because even if TF_STATE is not set, we default to terraform.tfstate.

I did not dig too deep here so I do not know if we actually have a hard requirement for something that is not present in state pull, but present in show -json or if it was just used as a new feature that could help us identify the version.

Anyway, I suggest to either drop support for 0.11 (0.12 has been out since May 2019 and people on 0.11 can keep using older versions of TI) OR detect version by parsing terraform version, terraform.tfstate, etc.

Having done that, stop calling show -json at all and use state pull that will match the format of terraform.tfstate.

I suggest this in order to avoid having to maintain 3 parsers: one for 0.11, one for 0.12 show -json, one for 0.12 state files.

@adammck we really need your thoughts here.

@justinas
Copy link

justinas commented Apr 2, 2020

@AndiDog your input would also be appreciated.

It is not clear to me whether we should use show -json or state pull. The output of show -json is well documented, but it does not match the format of state files. The easiest thing here would be to simply drop supporting raw state files and only allow using show -json.

terraform state pull on the other hand matches the state file, but is not documented well. However, the website indicates:

This is useful for reading values out of state (potentially pairing this command with something like jq).

So it seems that this is a valid use-case.

@AndiDog
Copy link
Contributor

AndiDog commented Apr 21, 2020

The error is clear enough: the state is empty. And it doesn't make sense to use terraform-inventory on empty state, right? If people have a different opinion, we could change the error to a warning in case state is empty (and assume Terraform 0.12).

@justinas
Copy link

But the state file is not empty, it just contains a format we do not expect (B vs C in this comment). This is an obvious regression where previously pointing to either a directory or an individual state file worked, but now only a directory is processed correctly (and it is not even a default).

As I see it, out of the box (read: without pointing it to a directory via the env var) terraform-inventory 100% does not work with 0.12.

@AndiDog
Copy link
Contributor

AndiDog commented Apr 22, 2020

Understood now. Let me put this in a reproducible example:

$ rm -rf /tmp/example && mkdir /tmp/example && cd /tmp/example

$ cat >main.tf <<EOF
provider "null" {}

resource "null_resource" "example" {
  provisioner "local-exec" {
    command = "true"
  }
}
EOF

$ terraform init
[...]

$ terraform apply -auto-approve
[...]

$ jq -c . terraform.tfstate
{"version":4,"terraform_version":"0.12.24","serial":1,"lineage":"3e8f9aa4-9daf-322e-e68f-dcaebf391f0b","outputs":{},"resources":[{"mode":"managed","type":"null_resource","name":"example","provider":"provider.null","instances":[{"schema_version":0,"attributes":{"id":"3973960162525722052","triggers":null},"private":"bnVsbA=="}]}]}

$ terraform show -json
{"format_version":"0.1","terraform_version":"0.12.24","values":{"root_module":{"resources":[{"address":"null_resource.example","mode":"managed","type":"null_resource","name":"example","provider_name":"null","schema_version":0,"values":{"id":"3973960162525722052","triggers":null}}]}}}

$ terraform show -json .
[...]
Plan read error: read .: is a directory

$ terraform show -json terraform.tfstate
{"format_version":"0.1","terraform_version":"0.12.24","values":{"root_module":{"resources":[{"address":"null_resource.example","mode":"managed","type":"null_resource","name":"example","provider_name":"null","schema_version":0,"values":{"id":"3973960162525722052","triggers":null}}]}}}

$ terraform-inventory --list
Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)

$ terraform-inventory --list . ; echo
{"all":{"hosts":[],"vars":{}}}

$ TF_STATE=. terraform-inventory --list ; echo
{"all":{"hosts":[],"vars":{}}}

I suggest we drop 0.11 support and always call terraform show -json - no implementation effort needed apart from removing lots of old code. With the current implementation, 0.12 format parsing has been working without issues since I implemented it. terraform show -json gives the current state by default, and we should use that default as well. If TF_STATE/TI_STATE is defined explicitly, we can still pass it on to terraform show -json <argument> (changing TF_STATE=. to TF_STATE=terraform.tfstate with a warning, because only terraform show -json terraform.tfstate works fine).

@ssarkarnetip
Copy link

I am having same issue in AWS. Everything worked great in terraform 11.

@alor
Copy link

alor commented Aug 18, 2020

anyone already tested with terraform 0.13? asking before upgrading...

[UPDATE] I've upgraded to 0.13 and the issue is still the same and the workaround works even with 0.13. at least it's safe to upgrade.

@patsevanton
Copy link

patsevanton commented Oct 30, 2020

I build terraform-inventory from source code

Same error:
terraform-inventory --list Error reading tfstate file: 0.12 format error: <nil>; pre-0.12 format error: <nil> (nil error means no content/modules found in the respective format)

@patsevanton
Copy link

terraform-inventory build from source.

Try on repo https://github.com/yandex-cloud/examples/tree/master/active-directory

$ terraform -version
Terraform v0.11.14
+ provider.yandex v0.46.0

$ terraform show -json .
Usage: terraform show [options] [path]

  Reads and outputs a Terraform state or plan file in a human-readable
  form. If no path is specified, the current state will be shown.

Options:

  -module-depth=n     Specifies the depth of modules to show in the output.
                      By default this is -1, which will expand all.

  -no-color           If specified, output won't contain any color.

$ terraform show -json terraform.tfstate
Usage: terraform show [options] [path]

  Reads and outputs a Terraform state or plan file in a human-readable
  form. If no path is specified, the current state will be shown.

Options:

  -module-depth=n     Specifies the depth of modules to show in the output.
                      By default this is -1, which will expand all.

  -no-color           If specified, output won't contain any color.

$ terraform-inventory --list
Error running `terraform show -json` in directory /home/user/examples/active-directory, exit status 1, falling back to trying Terraform pre-0.12 command
{"ad":["10.0.0.26"],"ad_0":["10.0.0.26"],"all":{"hosts":["10.0.0.26"],"vars":{}},"type_yandex_compute_instance":["10.0.0.26"]}

$ terraform-inventory --list . ; echo
Error running `terraform show -json` in directory /home/user/examples/active-directory, exit status 1, falling back to trying Terraform pre-0.12 command
{"ad":["10.0.0.26"],"ad_0":["10.0.0.26"],"all":{"hosts":["10.0.0.26"],"vars":{}},"type_yandex_compute_instance":["10.0.0.26"]}

$ TF_STATE=. terraform-inventory --list ; echo
Error running `terraform show -json` in directory /home/user/examples/active-directory, exit status 1, falling back to trying Terraform pre-0.12 command
{"ad":["10.0.0.26"],"ad_0":["10.0.0.26"],"all":{"hosts":["10.0.0.26"],"vars":{}},"type_yandex_compute_instance":["10.0.0.26"]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests