scottwinkler/terraform-provider-shell

Update fail but state get updated

Closed this issue · 3 comments

$ 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

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

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

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.