janul
November 25, 2019, 1:02pm
1
Hi,
I’m having trouble with “remote-exec” provisioner . I followed documenation but for some reason “host” in “connection block” is not resolved. After the very first apply I’m getting:
null_resource.testinstance (remote-exec): Connecting to remote host via SSH...
null_resource.testinstance (remote-exec): Host:
null_resource.testinstance (remote-exec): User: ubuntu
null_resource.testinstance (remote-exec): Password: false
null_resource.testinstance (remote-exec): Private key: true
null_resource.testinstance (remote-exec): Certificate: false
null_resource.testinstance (remote-exec): SSH Agent: true
null_resource.testinstance (remote-exec): Checking Host Key: false
The part of my terraform config loooks like:
resource "aws_eip" "ip-test-env" {
instance = aws_instance.testinstance.id
vpc = true
tags = {
Name = "test eip"
Creator = var.deployer
Environment = var.environment
}
}
resource "aws_instance" "testinstance" {
ami = data.aws_ami.instance_store_ami.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.SSH.id, aws_security_group.PING.id]
tags = {
Name = "testinstance"
Creator = var.deployer
Environment = var.environment
}
subnet_id = aws_subnet.SUBNET1.id
key_name = aws_key_pair.ssh-access-key.id
}
resource "null_resource" "testinstance" {
depends_on = [aws_eip.ip-test-env, aws_instance.testinstance]
connection {
type = "ssh"
host = aws_instance.testinstance.public_ip
private_key = file(var.private_key)
user = var.ansible_user
}
provisioner "remote-exec" {
inline = ["sudo apt-get -qq install python -y"]
on_failure = continue
}
}
Any ideas?
Thanks, Janusz
I might be jumping ahead, but I assume the machine is being launched in a public subnet, right? (and not in a private subnet)
other than that there could be a timing possibility?! could it be taking time to assign a public IP. (I am guessing this one)
grimm26
November 25, 2019, 4:46pm
3
It might help to show us the actual remote-exec resource.
janul
November 25, 2019, 9:04pm
4
Thanks @shantanugadgil @grimm26
remote-exec I shown in my first mail.
I tested two ways:
I did put provisioner block inside instance resource:
resource "aws_instance" "testinstance" {
ami = data.aws_ami.instance_store_ami.id
instance_type = "t2.micro"
vpc_security_group_ids = [aws_security_group.SSH.id, aws_security_group.PING.id]
subnet_id = aws_subnet.SUBNET1.id
key_name = aws_key_pair.ssh-access-key.id
provisioner "remote-exec" {
connection {
type = "ssh"
host = self.public_ip
private_key = file(var.private_key)
user = var.ansible_user
timeout = "30"
}
inline = ["sudo apt-get -qq install python -y"]
on_failure = continue
}
}
That provisioner obviously failed because terraform initiated creating that resource before elastic IP instance which references to above one:
resource "aws_eip" "ip-test-env" {
instance = aws_instance.testinstance.id
vpc = true
}
So I tried to use resource “null_resource” “testinstance” and set to depend on those instances.
resource "null_resource" "testinstance" {
depends_on = [aws_eip.ip-test-env, aws_instance.testinstance]
provisioner "remote-exec" {
connection {
type = "ssh"
host = aws_instance.testinstance.public_ip
private_key = file(var.private_key)
user = var.ansible_user
}
inline = ["sudo apt-get -qq install python -y"]
on_failure = continue
}
}
But it also failing with empty Host for 5 mins even if after couple of seconds public ip was assigned.
To me is strange that “host” is required in “connection” block and in the same time is trying SSH connection with Host: null
Shouldn’t it try to check again for referenced values if null ?
And obviously when I run again: terraform apply
works well because both aws_instance and eip_instance are already provisioned
Is any work around for it?
Thanks, Janusz
Have you verified the .public_ip value is being populated. I would try to apply your configuration without the provisioner. Then launch the terraform shell locally and type “aws_instance.testinstance.public_ip”. This should output the value of the ip address if it has one.
janul
November 26, 2019, 1:12am
6
Thanks @castironclay ,
Actually I hadn’t check that with terraform console.
After apply (without provisioner):
> aws_instance.testinstance.id
i-0af1625021e141dcb
> aws_instance.testinstance.public_ip
/*empty result*/
>aws_eip.ip-test-env.public_ip
XX.XX.XXX.XX
>aws_eip.ip-test-env.instance
i-0af1625021e141dcb
So yes public_ip is missing in that instance from the tfstate
When I typed “terraform refresh” and run console again I got expected result:
>aws_instance.testinstance.public_ip
XX.XX.XXX.XX
I wonder if that expected or a bug in core/aws plugin ?
Thank you,
Janusz
No I think it’s an error in your implementation. Trying to find it though. I do basically the same thing but don’t run in to that problem. I’ll post what I use below. Hope it helps. I am using multiple modules but I think you can follow the interpolation
**main.tf**
resource "aws_instance" "host" {
vpc_security_group_ids = [var.aws_sg]
associate_public_ip_address = true
subnet_id = var.subnet
ami = var.ami
instance_type = var.size
key_name = aws_key_pair.host_key.key_name
availability_zone = var.a_zone
depends_on = [aws_key_pair.host_key]
root_block_device {
delete_on_termination = var.delete_root_volume
}
tags = {
Status = var.dev_or_prod
Name = var.instance_name
}
provisioner "remote-exec" {
inline = ["echo 'Im alive!'"]
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = aws_instance.host.public_ip
}
}
}
1 Like
ah. You are missing one line in your aws_instance resource I think.
associate_public_ip_address = true
If you want to ssh to the instance using the eip IP address you need to change your line in your provisioner to host = aws_eip.ip-test-env.public_ip
janul
November 26, 2019, 1:51am
10
@castironclay , thanks very much.
yes, referrencing to aws_eip.ip-test-env.public_ip
fixed the issue !!!
btw. interesting side effect when used associate_public_ip_address = true
and left eip
untouched:
> aws_instance.testinstance.public_ip
XX.XX.XX.XX
> aws_eip.ip-test-env.public_ip
YY.YY.YY.YY
Again, thanks for you help in fixing it !
Janusz
The default behavior is to not assign a public IP to your instance so setting it to true fixing that’s. So you could actually target the instance via either the dynamically assigned public ip or the eip.
Happy to help! Glad it worked.