Hello.
I created aws instances with configuration:
...
resource "aws_instance" "mmp_instances" {
ami = "${var.ami_mmp}"
instance_type = "${var.type_mmp}"
key_name = "${var.key_name}"
subnet_id = "${element(aws_subnet.subnets_mmp.*.id, count.index)}"
vpc_security_group_ids = ["${aws_security_group.mmp-sg.id}"]
root_block_device {
volume_type = "gp2"
volume_size = "40"
delete_on_termination = "true"
}
tags {
role = "pool"
env = "dev"
}
provisioner "local-exec" {
command = "aws ec2 create-tags --resources ${self.id} --tags Key=Name,Value=${self.private_ip}"
}
provisioner "local-exec" {
command = "sleep 120; ansible-playbook -i '${self.private_ip},' --timeout=600 --private-key=id_rsa deploy_pool.yml"
}
count = "${var.count_mmp}"
}
i have added ’Name’ tag by provisioner:
provisioner "local-exec" {
command = "aws ec2 create-tags --resources ${self.id} --tags Key=Name,Value=${self.private_ip}"
}
after that i change another part of configuration plan and execute ’terraform plan’ and get output:
…
~ aws_instance.mmp_instances.0
tags.#: "3" => "2"
tags.Name: "10.0.33.65" => ""
~ aws_instance.mmp_instances.1
tags.#: "3" => "2"
tags.Name: "10.0.34.172" => ""
~ aws_instance.mmp_instances.2
tags.#: "3" => "2"
tags.Name: "10.0.35.40" => ""
~ aws_instance.mmp_instances.3
tags.#: "3" => "2"
tags.Name: "10.0.33.9" => «"
….
Tags ’Name’ will be deleted after execution ’terraform apply’ (((
Hi @alexd88
Terraform does not know that you're adding tags via provisioner and uses API to get all attributes of the newly created EC2 instance (including tags) after the provisioner block ran. Since you have not defined that tag in the DSL, it recognises the difference and tries to remove it.
I'm not quite sure why do you need to be setting attribute like private IP as a tag, but the solution could be supporting tags in a separate resource, e.g. aws_instance_tags.
This may however lead to a bunch of other *_tags resources since most AWS resources have tags, which is why I'm not convinced that this is a good approach and I don't think there's enough valid use-cases for this.
Would you mind describing why do you need IP as a tag?
Hi, @radeksimko
Tag 'Name' is used in our monitoring system for ease of use. IP is more representative than instance-id.
Also tags (not only with ip) are used by me for orchestration (via Ansible with dynamic inventory script).
For example (it is my case): we create group of instances. After a while we want to add several instances to the same group. We don`t want to change existing instances. We want to create new instances, we simply change variable containing current number of instances and make 'terraform apply'.. and this action affects on existing configuration, but it should not.
It would be great if terraform would not remove already existing tags.
@alexd88
IP is more representative than instance-id.
Agreed, especially if you have instances with different cloud providers.
Do I understand correctly this is to allow you to target single instances via IP since the tool (Ansible?) you use to provision/orchestrate these instances does not allow you to target via IPs?
The AWS API does allow filtering via IPs so if that tool doesn't allow you to do that, it's worth reporting it to vendor and/or sending PR there, linking here:
http://docs.aws.amazon.com/AWSEC2/latest/CommandLineReference/ApiReference-cmd-DescribeInstances.html
ip-address
The public IP address of the instance.
Type: String
private-ip-address
The private IP address of the instance.
Type: String
I don't feel this is something that people would naturally do. The IP attribute is there, tags are IMO designed for something else. Both attributes are available via API.
There may be a valid reason to support aws_instance_tags, but I don't feel this is one.
@radeksimko, tag with instance IP is particular case. No, i don`t use tag with instance IP for orchestrating and provisioning )) I want to add custom compound tag which may contain information about placement group, availability zone, ip, etc...
I know some workarounds, but they are not good solution for my problem
I guess if terraform supported referring self.ip or self.public_ip in the tags block of the aws_instance type it would solve it.
I dont see any technical reason why the tags could not be set after the run-instance call, in the terraform implementation.
@alexd88 If we were to add support for aws_instance_tags or ${self.private_ip} or anything else, it will be a workaround for your use-case anyway. I believe this is an issue with the other tool you are using. I don't have much experience with Ansible unfortunately, but if that's the problem, I believe it's worth opening discussion in Ansible community about this, so you don't need tags for something that's available from the API already.
@JesperTerkelsen Agreed, self references are currently supported only in provisioner blocks because that's the only place where we're sure we won't hit the chicken/egg problem. Terraform does not know which attribute in the schema can be created separately and then referenced in other attributes. Ain't saying this problem is impossible to solve, just ain't as easy as you may imagine.
This is an issue for me as well. We use chef to create various tags on ec2 instances. These are things like env, apps and version chef installs etc. terraform should not adjust tags it didn't create. These tags can't be known by terraform ahead of time.
It would be nice if the terraform refresh could pull this into the state and then terraform would not freak out about the tags.
I just discovered a workaround use the lifecycle ignore_changes feature like this
resource "aws_instance" "acme-web" {
...
tags {
Catapulta = "Launched By Terraform"
}
#This is very important, as it tells terraform to not mess with tags created by chef
lifecycle {
ignore_changes = ["tags"]
}
}
Hi folks, ignore_changes = ["tags"] is the correct solution to this issue. :+1:
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.
Most helpful comment
I just discovered a workaround use the lifecycle ignore_changes feature like this