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

Suggestion: Use CustomizeDiff and ForceNew if Update is empty #78

Closed
rucciva opened this issue Oct 28, 2020 · 0 comments
Closed

Suggestion: Use CustomizeDiff and ForceNew if Update is empty #78

rucciva opened this issue Oct 28, 2020 · 0 comments

Comments

@rucciva
Copy link
Contributor

rucciva commented Oct 28, 2020

Calling Delete -> Create when Update is empty will result in Delete operation done using new state, instead of old state. For example in the following script, Delete will run rm /tmp/shell/folder/test1 instead of rm /tmp/shell/folder/test (which surprisingly does not produce error even though the script return error due to file not exist) when updating environment.File.

locals {
  path = "/tmp/shell/folder"  # change this
}

resource "null_resource" "directory"{
  triggers = {
    path = local.path
  }
  provisioner "local-exec" {
    command = "mkdir -p ${self.triggers.path}"
  }
  provisioner "local-exec" {
    when = destroy
    command = "rm -rf ${self.triggers.path}"
  }
}

resource "shell_script" "github_repository" {
  lifecycle_commands {
    create = "touch $FILE"
    read   = "echo '{\"name\":\"'\"$FILE\"'\"}'"
    delete = "rm $FILE"
  }
  
  environment = {
    FILE = "${null_resource.directory.triggers["path"]}/test1"
  }

}
$ ls /tmp/shell
ls: /tmp/shell: No such file or directory
$ 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:

  # null_resource.directory will be created
  + resource "null_resource" "directory" {
      + id       = (known after apply)
      + triggers = {
          + "path" = "/tmp/shell/folder"
        }
    }

  # shell_script.github_repository will be created
  + resource "shell_script" "github_repository" {
      + dirty             = false
      + environment       = {
          + "FILE" = "/tmp/shell/folder/test"
        }
      + id                = (known after apply)
      + output            = (known after apply)
      + working_directory = "."

      + lifecycle_commands {
          + create = "touch $FILE"
          + delete = "rm $FILE"
          + read   = "echo '{\"name\":\"'\"$FILE\"'\"}'"
        }
    }

Plan: 2 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

null_resource.directory: Creating...
null_resource.directory: Provisioning with 'local-exec'...
null_resource.directory (local-exec): Executing: ["/bin/sh" "-c" "mkdir -p /tmp/shell/folder"]
null_resource.directory: Creation complete after 0s [id=8706134334622958825]
shell_script.github_repository: Creating...
shell_script.github_repository: Creation complete after 0s [id=buchmouvvhfkg3qaorj0]

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
$ ls  /tmp/shell/folder/
test
$ terraform apply
null_resource.directory: Refreshing state... [id=8706134334622958825]
shell_script.github_repository: Refreshing state... [id=buchmouvvhfkg3qaorj0]

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       = {
          ~ "FILE" = "/tmp/shell/folder/test" -> "/tmp/shell/folder/test1"
        }
        id                = "buchmouvvhfkg3qaorj0"
        output            = {
            "name" = "/tmp/shell/folder/test"
        }
        working_directory = "."

        lifecycle_commands {
            create = "touch $FILE"
            delete = "rm $FILE"
            read   = "echo '{\"name\":\"'\"$FILE\"'\"}'"
        }
    }

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=buchmouvvhfkg3qaorj0]
shell_script.github_repository: Modifications complete after 0s [id=buchmv6vvhfkgjj4kq20]

Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
$ ls  /tmp/shell/folder/
test    test1

i suggest using CustomizeDiffFunc as such

                CustomizeDiff: func(c context.Context, rd *schema.ResourceDiff, i interface{}) (err error) {
			if rd.Id() == "" {
				return
			}
			if _, ok := rd.GetOk("lifecycle_commands.0.update"); ok {
				return
			}
			for _, key := range rd.GetChangedKeysPrefix("") {
                                 if strings.HasPrefix(key, "triggers") {
					continue // already force new
				}

				// need to remove index from map and list
				switch {
				case strings.HasPrefix(key, "environment"):
					key = strings.Split(key, ".")[0]
				case strings.HasPrefix(key, "sensitive_environment"):
					key = strings.Split(key, ".")[0]
				case strings.HasPrefix(key, "interpreter"):
					key = strings.Split(key, ".")[0]
				}

				err = rd.ForceNew(key)
				if err != nil {
					return
				}
			}
			return
		},
rucciva added a commit to TelkomIndonesia/terraform-provider-shell that referenced this issue Nov 12, 2020
scottwinkler added a commit that referenced this issue Nov 12, 2020
@rucciva rucciva closed this as completed Nov 13, 2020
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

1 participant