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

Run null_resource always or updates to triggers #8266

Closed
mlushpenko opened this issue Aug 17, 2016 · 9 comments
Closed

Run null_resource always or updates to triggers #8266

mlushpenko opened this issue Aug 17, 2016 · 9 comments

Comments

@mlushpenko
Copy link

mlushpenko commented Aug 17, 2016

Terraform Version

$ terraform -v
Terraform v0.7.0

Affected Resource(s)

  • null_resource

References

Issue #745

The issue for me is to rerun null_resources on changes. For instance, I have a step to add EC2 instance IPs to the group in inventory file:

# Add web hosts to the web group
resource "null_resource" "ansible_inventory_hosts" {
  count = "${var.aws_instances_count}"

  provisioner "local-exec" {
    command = "sed -i '/\\[${element(aws_instance.web.*.tags.group, count.index)}\\]/ a ${element(aws_instance.web.*.private_ip, count.index)}' ansible/inventory"
  }

  depends_on = ["null_resource.ansible_inventory_groups"]
}

So, whenever I change the number of instances, my inventory will be updated. Now I need to copy this new inventory to the ansible "master" host, so I use null_resource again:

resource "null_resource" "ansible_copy" {
  provisioner "file" {
    source = "ansible/"
    destination = "/home/ubuntu"
  }

  connection {
    user        = "ubuntu"
    private_key = "key.pem"
    host                = "${aws_instance.ansible.public_ip}"
  }

  depends_on = ["null_resource.ansible_inventory_hosts"]
}

but it doesn't appear during the plan phase. One solution I found is to monitor number of instances by adding trigger to null_resource:

    triggers = {
        copy_files_on_inventory_change = "${var.aws_instances_count}" 
    }

But I also have ansible files themselves, that are not related to the infrastructure changes, I mean role definitions. Do you have an idea on how to track local files changes, how do I trigger null_resource if I updated my role or how do I make the resource run always?

Considering this case - do you think it would make sense to add something like "tainted: always" option to null_resources? I am new to Terraform, but I feel like the connection between Terraform and configuration management tooling is missing a bit.

Another option is maybe to update trigger functionality to track changes in folder or files, like via hash calculation or so.

@apparentlymart
Copy link
Member

Hi @mlushpenko!

If I'm understanding your question correctly (please excuse my unfamiliarity with Ansible) you're looking for a way to trigger the null-resource provisioner when any file changes in your ansible directory.

I'm afraid I don't have a full answer to your question, since Terraform doesn't yet have a way to hash the contents of a directory, but we can hash the contents of individual files:

    triggers = {
        instance_count = "${var.aws_instances_count}" 
        some_ansible_file = "${sha1(file("${path.module}/ansible/some-ansible-file"))}"
    }

If you are able to list out each of the files in your ansible directory with the above pattern then that should do what you're looking for. Unfortunately I don't have a quick fix for automatically monitoring for new files in there, but if you manually add a new entry to triggers in the config that should have the same effect as changing any of the existing values, and cause the provisioners to re-run.

@mlushpenko
Copy link
Author

Hi @apparentlymart, thanks for the proposal. It definitely helps in my situation, but would be nice to see some better solution in the future, although I understand that tracking changes on local machine (like file or folders in this case) is not an intended functionality in terraform.

@mlushpenko
Copy link
Author

One drawback to this proposal as it seems to me - the provisioner won't work if tracked file is changed during the apply phase. I mean that in my case file is updated dynamically every time, while resources that will be affected are planned "statically" during the plan phase, so before execution starts, the hash of the file will be the same and will change only 1-2 steps before the null_resource provisioner is executed. Do I understand terraform behavior correctly?

@mlushpenko
Copy link
Author

One more use case for having run always fucntionality is self-healing. Let's say I have Ansible to configure my web servers. If some web server crashes, I could rerun Ansible to get web server configuration back to normal, but terraform plan doesn't see such changes, so right now I have to manually taint configuration step and then run apply. If there was run always or tainted:always functionality, I could put 'terraform apply' command into Jenkins and get back my infrastructure and configuration to the desired state even if I didn't notice some error.

@apparentlymart
Copy link
Member

Hi again @mlushpenko.

I apologize that on my first read I didn't notice that you generated that ansible/inventory file in the provisioner on the first resource. What I proposed assumes that the files in the ansible directory are not modified by Terraform itself, but that Terraform is just (indirectly) using them.

Although your original question was about making null_resource run every time, I think the bigger problem here is that Terraform's template language isn't rich enough for you to be able to generate that inventory file without calling out to sed. The feature I proposed over in #8144 could help here by avoiding the need for that temporary file to be created at all, though a resolution of #1845 could eliminate the need to call out to sed at all, depending on what template language we choose.

However, getting back to your specific problem: since your inventory file is produced entirely from data that Terraform knows, you should be able to put similar data inside triggers so that Terraform can "know" the file has changed even though it doesn't really know the file exists:

    triggers = {
        instance_count = "${var.aws_instances_count}" 
        inventory_groups = "${join(" ", aws_instance.web.*.tags.group)}"
        inventory_ip_addresses = "${join(" ", aws_instance.web.*.private_ip)}"
    }

@mlushpenko
Copy link
Author

Hi @apparentlymart!

thanks for sharing this - that's basically what I was looking for: to see that more people share the same pain and the work is going on in that direction. And just in case of misunderstanding - I wasn't blaming you in any way about the "wrong" proposal, just thinking out loud whether it solves the issue in the right way.

Glad to see live community, I will try t share more thoughts on improving terraform.

@matt9mg
Copy link

matt9mg commented Jan 15, 2019

not sure if this will answer any ones q's but recently I had an issue where I wanted secrets.tf to be generated (git ignored of course) i.e database password etc. I came up with

resource "null_resource" "ansible" {
  provisioner "local-exec" {
    command = "cd ../ansible && make terraform CLIENT=${var.customer}"
  }

  triggers = {
    always_run = "${timestamp()}"
  }
}

May help someone else one day

@caarlos0
Copy link
Contributor

Another cool tip, if you want it to apply if a file was changed, for example:

resource "null_resource" "foo" {
  provisioner "local-exec" {
    command = "do something with ${path.module}/files/foo.config"
  }

  triggers = {
    md5 = "${filemd5("${path.module}/files/foo.config")}"
  }
}

@ghost
Copy link

ghost commented Aug 22, 2019

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 Aug 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants