scottwinkler / terraform-provider-shell

Terraform provider for executing shell commands and saving output to state file
Mozilla Public License 2.0
279 stars 60 forks source link

Update fail but state get updated #77

Closed rucciva closed 3 years ago

rucciva commented 3 years ago
$ terraform apply

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # shell_script.github_repository will be created
  + resource "shell_script" "github_repository" {
      + dirty             = false
      + environment       = {
          + "DESCRIPTION" = "description"
          + "NAME"        = "hello world"
        }
      + id                = (known after apply)
      + output            = (known after apply)
      + working_directory = "."

      + lifecycle_commands {
          + create = "echo '{\"name\":\"'$NAME'\", \"description\": \"'$DESCRIPTION'\", \"map\":{\"test\":true}}' > tmp"
          + delete = "rm tmp"
          + read   = "cat tmp"
          + update = <<~EOT
                [ -f previous ]  && exit 1
                cat > previous
                echo '{"name":"'$NAME'", "description": "'$DESCRIPTION'", "map":{"test":true}}' > tmp
            EOT
        }
    }

Plan: 1 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

shell_script.github_repository: Creating...
shell_script.github_repository: Creation complete after 0s [id=bub34js82sathf6hqlug]

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
$ terraform apply
shell_script.github_repository: Refreshing state... [id=bub34js82sathf6hqlug]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # shell_script.github_repository will be updated in-place
  ~ resource "shell_script" "github_repository" {
        dirty             = false
      ~ environment       = {
            "DESCRIPTION" = "description"
          ~ "NAME"        = "hello world" -> "hello world 1"
        }
        id                = "bub34js82sathf6hqlug"
        output            = {
            "description" = "description"
            "map"         = jsonencode(
                {
                    test = true
                }
            )
            "name"        = "hello world"
        }
        working_directory = "."

        lifecycle_commands {
            create = "echo '{\"name\":\"'$NAME'\", \"description\": \"'$DESCRIPTION'\", \"map\":{\"test\":true}}' > tmp"
            delete = "rm tmp"
            read   = "cat tmp"
            update = <<~EOT
                [ -f previous ]  && exit 1
                cat > previous
                echo '{"name":"'$NAME'", "description": "'$DESCRIPTION'", "map":{"test":true}}' > tmp
            EOT
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

shell_script.github_repository: Modifying... [id=bub34js82sathf6hqlug]
shell_script.github_repository: Modifications complete after 0s [id=bub34js82sathf6hqlug]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
$ terraform apply
shell_script.github_repository: Refreshing state... [id=bub34js82sathf6hqlug]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  ~ update in-place

Terraform will perform the following actions:

  # shell_script.github_repository will be updated in-place
  ~ resource "shell_script" "github_repository" {
        dirty             = false
      ~ environment       = {
            "DESCRIPTION" = "description"
          ~ "NAME"        = "hello world 1" -> "hello world 2"
        }
        id                = "bub34js82sathf6hqlug"
        output            = {
            "description" = "description"
            "map"         = jsonencode(
                {
                    test = true
                }
            )
            "name"        = "hello world 1"
        }
        working_directory = "."

        lifecycle_commands {
            create = "echo '{\"name\":\"'$NAME'\", \"description\": \"'$DESCRIPTION'\", \"map\":{\"test\":true}}' > tmp"
            delete = "rm tmp"
            read   = "cat tmp"
            update = <<~EOT
                [ -f previous ]  && exit 1
                cat > previous
                echo '{"name":"'$NAME'", "description": "'$DESCRIPTION'", "map":{"test":true}}' > tmp
            EOT
        }
    }

Plan: 0 to add, 1 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

shell_script.github_repository: Modifying... [id=bub34js82sathf6hqlug]

Error: Error occured during shell execution.
Error: 
exit status 1

Command: 
[ -f previous ]  && exit 1
cat > previous
echo '{"name":"'$NAME'", "description": "'$DESCRIPTION'", "map":{"test":true}}' > tmp

StdOut: 

StdErr: 

Env: 
[NAME=hello world 2 DESCRIPTION=description]

StdIn: 
'{"description":"description","map":"{\"test\":true}","name":"hello world 1"}'

  on main.tf line 1, in resource "shell_script" "github_repository":
   1: resource "shell_script" "github_repository" {
$ terraform apply
shell_script.github_repository: Refreshing state... [id=bub34js82sathf6hqlug]

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

P.S: i'm also in the middle of developing custom provider and noticed this behavior. I don't know if this is considered bug in terraform or not. A workaround that i use is to manually reset the *ResourceData using value obtained from GetChange

rucciva commented 3 years ago

i guess this is related to hashicorp/terraform-plugin-sdk#476

scottwinkler commented 3 years ago

so the problem is that i there is an error in the update function, it fails to update (expected) but then it never updates afterwards. That would be a problem. Resetting the resource data could work. Or I could set the Dirty flag to true, which does the same thing. I'll have to think about it. Thanks for bringing this to my attention

rucciva commented 3 years ago

Resetting the resource data could work. Or I could set the Dirty flag to true

I would suggest resetting the resource data, that way the script that depends on old value can work as expected.