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

Feature Request: "blank" resource #1181

Closed
ctro opened this issue Mar 11, 2015 · 9 comments
Closed

Feature Request: "blank" resource #1181

ctro opened this issue Mar 11, 2015 · 9 comments

Comments

@ctro
Copy link

ctro commented Mar 11, 2015

Imagine: aws_eip has a dependency on aws_instance.
The final public ip (i.e. aws_eip.public_ip) has to be written to a file on aws_instance.

That means that a provisioner has to live on aws_eip. This is a known workaround, and makes sense.

Now you invalidate aws_instance, maybe bumping a version number or something.
Because EIPs are not always re-provisioned the next apply will run provisioners for aws_instance but NOT aws_eip.

That means aws_eip.public_ip will not be written to our file on aws_instance.

A dirty workaround is to add some un-needed resource, maybe an s3_bucket, that has a provisioner that points to our aws_instance. The bucket is not needed, but it gives me a place to add a provision step that references aws_eip.public_ip w/o creating a circular dependency.

Then I thought: maybe an easy solution to this problem is to add a "blank" or "resource-less" resource. One could add a custom connection block in this blank resource, and provisioner steps could reference aws_eip.public_ip This blank resource would always be Created, never Updated -- ensuring that we always write the necessary file on the aws_instance.

@ctro
Copy link
Author

ctro commented Mar 11, 2015

Another related thought: being able to depend on a variable could help solve this also.
Use a changed variable value to invalidate some resource and make sure it gets re-provisioned.

variable "foo_version" {
  default = "0.0.1"
}
resource "aws_instance" "foo" {
  depends_on = "${var.foo_version}"
...

@phinze
Copy link
Contributor

phinze commented Mar 11, 2015

These are some really interesting ideas! I definitely think we should provide some sort of model for accomplishing the goals you are talking about here. I sort of like the idea of a "noop" resource that would let you inject local-exec providers in at certain places in the dependency graph.

Going to mark this thinking while we discuss and consider the options here.

@lalloni
Copy link
Contributor

lalloni commented Mar 12, 2015

I've come to the very same need: running some local orchestration script having the output from other various resource/s as input, specially when the others are multi-instance. We implemented the idea of a using an unneeded resource just as @ctro mentioned, using joined splat interpolations as input, and it worked fine, except TF can not kill the resource when it's not longer needed.

I think having a "null" (yet another possible name) resource capable of executing "local-exec" provisioners would be enough for solving the issue, but possibly it should not allow using "remote-exec" or "file" provisioners (those make no sense here without some mental twist) so it would be pretty much a "special case" resource (which always smells).

So, what if TF could have provisioners outside resources and participating in the dependency graph on its own, so being capable of dependending on other resources?

For instance:

resource "do_droplet" "node" {
  count = 10
  ...
}
provisioner "local-exec" "cluster-start" {
  command = "start-cluster.sh ${join(" ", do_droplet.node.*.ipv4_address)}"
}

I believe this could easily be seen as a generalization of provisioners given you could do with it all the things you can do now with "resource" provisioners, we only lose the implicit provisioner to resource connection of a given "remote-exec" or "file" provisioner which of course could be easily reinstated explicitly:

resource "do_droplet" "node" {
  ...
}
provisioner "remote-exec" "start-service" {
  resource = "do_droplet.node"
  script = "start-service.sh"
}

@knuckolls
Copy link
Contributor

Just wanted to mention that I've previously written up a lot of thoughts on this matter in #580. I currently believe it wouldn't be that hard to write a provisioner shim resource that does everything you'd expect it to do versus just using the null_resource as a hack.

@ctro
Copy link
Author

ctro commented Mar 13, 2015

shoot, @knuckolls I can't believe I didn't see #580. Thank you for ref-ing it here.

@lalloni
Copy link
Contributor

lalloni commented Mar 14, 2015

@ctro: same here.
@knuckolls: thanks again.

@bitglue
Copy link

bitglue commented Apr 1, 2015

This is also a problem that can be solved by not using provisioners. Instead, "the IP written on the instance" is a resource: it's a thing that can exist or not, which you can update or delete. It maps very nicely to CRUD operations.

@phinze
Copy link
Contributor

phinze commented Sep 10, 2015

Hey folks, going to merge this thread with #580. See you there!

@ghost
Copy link

ghost commented May 1, 2020

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.

@ghost ghost locked and limited conversation to collaborators May 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants