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

Trigger new resource when external file changes #11418

Closed
kpersohn opened this issue Jan 25, 2017 · 5 comments · Fixed by #30900
Closed

Trigger new resource when external file changes #11418

kpersohn opened this issue Jan 25, 2017 · 5 comments · Fixed by #30900

Comments

@kpersohn
Copy link
Contributor

For context, see #8099, where I stumbled across @apparentlymart 's call for use cases. This bit in particular inspired me, as this is exactly the functionality I'm looking for:

It might work out conceptually simpler to generalize the triggers idea from null_resource or keepers from the random provider, so that it can be used on any resource

Generically speaking, I'd like to force a new resource when the contents of a file it depends on changes.

More specifically, say I have a compute instance resource with a Chef provisioner using a Policyfile to define its cookbooks, run-list, etc. In a test workflow I'd like to detect changes to policy JSON and force re-create the compute instances to ensure the new policy is effective on a clean slate (without disrupting other resources that aren't affected by the policy change).

resource "compute_instance" "my_policy" {
    ...
    provisioner "chef" {
        ...    
        use_policyfile = true
        policy_group = "staging"
        policy_name = "my_policy"
    }
    
    lifecycle {
        replace_on_change {
            policyfile = "${file("policies/my_policy.rb")}"
        }
    }
}

Consider another workflow, which is probably more common, where a simple shell script is sufficient for provisioning a compute instance and it is desirable to start with a fresh instance anytime the provisioning logic changes:

resource "compute_instance" "foo" {
    ...
    provisioner "file" {
        source = "setup.sh"
        destination = "/tmp/setup.sh"
    }
   provisioner "remote-exec" {
        inline = [
          "chmod +x /tmp/setup.sh",
          "/tmp/setup.sh"
        ]
    }
    
    lifecycle {
        replace_on_change {
            policyfile = "${file("setup.sh")}"
        }
    }
}

Currently, if the contents of setup.sh change, Terraform has no visibility into this and just leaves the instance be. Allowing users to hash the contents would make for easy re-provisioning without the need to care about the idempotence issues of just re-running the provisioner as discussed in #745 and elsewhere (assuming one is willing to take the hit on re-creating the resource from scratch).

@mitchellh
Copy link
Contributor

Retagging as enhancement. A good idea though.

@mitchellh mitchellh added enhancement and removed bug labels Jan 27, 2017
@leighmhart
Copy link

I could really use this too - my use case is similar but related to GCP XPN (cross project networking) policy bindings (JSON). XPN subnet policy bindings are how XPN (host) subnetworks are shared to a project - right now, in the beta at least, you associate a service project with an XPN Host project with a single gcloud command, however, each subnetwork you want users in that service project to be able to use needs to be bound with a gcloud command and a JSON policy document (another gcloud command per network per binding).

Until that gets sorted out, we're binding all networks to each new service project's users' groups' as they come online - however, today that means I have to taint some 42 null_resource objects to get the gcloud command to run again - I'd much rather tag them with a dependency on a policy file like the above. E.g.:

resource "null_resource" "subnetwork-association-one-eleventy-one-one-bang1" {
  provisioner "local-exec" {
    command = "yes | gcloud beta compute networks subnets set-iam-policy one-eleventy-one-one-bang1 subnet-policy.json --region ${var.gcp-us-west} --project my-xpn-host-project"
  }
}

where subnet-policy.json is the file being updated each time a new service project is added:

{
  "bindings": [
    {
      "members": [
        "group:service-project1-admin-group@company.com",
        "group:service-project1-owner-group@company.com",
        "serviceAccount:1234567890001-compute@developer.gserviceaccount.com",
        "serviceAccount:1234567890001@cloudservices.gserviceaccount.com",
        "serviceAccount:automation@service-project1.iam.gserviceaccount.com",

        "group:service-project2-admin-group@company.com",
        "group:service-project2-owner-group@company.com",
        "serviceAccount:1234567890002-compute@developer.gserviceaccount.com",
        "serviceAccount:1234567890002@cloudservices.gserviceaccount.com",
        "serviceAccount:automation@service-project2.iam.gserviceaccount.com"

      ],
      "role": "roles/compute.networkUser"
    }
  ],
}

@apparentlymart
Copy link
Contributor

@allandrick possibly I'm not understanding your use-case properly, but I think you can achieve what you need today using the triggers attribute:

resource "null_resource" "subnetwork-association-one-eleventy-one-one-bang1" {
  triggers = {
    policy_sha1 = "${sha1(file("subnet-policy.json"))}"
  }
  provisioner "local-exec" {
    command = "yes | gcloud beta compute networks subnets set-iam-policy one-eleventy-one-one-bang1 subnet-policy.json --region ${var.gcp-us-west} --project my-xpn-host-project"
  }
}

This issue is asking essentially for this triggers mechanism to be generalized to all resources, but since you happen to be using null_resource you can use the already-existing version of this built in to that resource.

@leighmhart
Copy link

@apparentlymart thank you very much - that does the trick nicely!

I could have also used a data template_file resource with or without vars to pick up any changes that way... but your way is much more elegant!

Regards,

Leigh

@github-actions
Copy link

I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 23, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants