I keep getting error "host for provisioner cannot be empty"
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 4.0"
}
}
}
# Configure the AWS Provider
provider "aws" {
region = var.region
profile = "whatsnxt"
}
resource "tls_private_key" "rsa_4096" {
algorithm = "RSA"
rsa_bits = 4096
}
# create key pair for connecting to EC2 via SSH
resource "aws_key_pair" "key_pair" {
key_name = var.key_pair_name
public_key = tls_private_key.rsa_4096.public_key_openssh
}
resource "local_file" "private_key" {
content = tls_private_key.rsa_4096.private_key_openssh
filename = pathexpand("~/.ssh/${var.private_key}")
provisioner "local-exec" {
command = "chmod 400 ${self.filename}"
}
}
# update docker image when var.image_version changes
resource "null_resource" "image_updater" {
depends_on = [ null_resource.node_provisioner, module.ec2_instance ]
triggers = {
image_version = var.image_version
}
connection {
host = module.ec2_instance.public_ip
user = "ec2-user"
type = "ssh"
private_key = local_file.private_key.content
}
provisioner "file" {
source = "run-image.sh"
destination = "run-image.sh"
}
provisioner "file" {
source = "../.env"
destination = ".env"
}
provisioner "remote-exec" {
inline = [
"chmod +x run-image.sh",
"./run-image.sh ${var.image_version}"
]
}
}
module "ec2_instance" {
source = "terraform-aws-modules/ec2-instance/aws"
ami = var.ami
name = var.instance_name
instance_type = var.instance_type
key_name = aws_key_pair.key_pair.key_name
monitoring = true
subnet_id = aws_subnet.blog_public_subnet.id
vpc_security_group_ids = [aws_security_group.blogSG.id]
user_data = <<-EOF
#!/bin/bash -xe
sudo yum update -y
sudo yum install docker -y
sudo systemctl enable docker.service
sudo systemctl start docker.service
sleep 15
EOF
tags = {
Terraform = "true"
Environment = "dev"
Name = var.instance_name
}
}
resource "null_resource" "node_provisioner" {
depends_on = [ module.ec2_instance ]
triggers = {
instance_id = module.ec2_instance.id
}
connection {
host = module.ec2_instance.public_ip
user = "ec2-user"
type = "ssh"
private_key = local_file.private_key.content
}
provisioner "file" {
source = ".credentials"
destination = "credentials"
}
provisioner "remote-exec" {
inline = [
"mkdir -p .aws",
"mv credentials .aws/credentials"
]
}
}
# resource "aws_default_vpc" "default" {
# tags = {
# Name = "Default blog webserver VPC"
# }
# }
resource "aws_vpc" "blog_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "Custom Blog VPC"
}
}
resource "aws_subnet" "blog_public_subnet" {
vpc_id = aws_vpc.blog_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = var.availability_zone
tags = {
Name = "Blog Public Subnet"
}
}
resource "aws_subnet" "blog_private_subnet" {
vpc_id = aws_vpc.blog_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = var.availability_zone
tags = {
Name = "Blog Private Subnet"
}
}
resource "aws_internet_gateway" "blog_ig" {
vpc_id = aws_vpc.blog_vpc.id
tags = {
Name = "Blog Internet Gateway"
}
}
resource "aws_route_table" "public_rt" {
vpc_id = aws_vpc.blog_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.blog_ig.id
}
route {
ipv6_cidr_block = "::/0"
gateway_id = aws_internet_gateway.blog_ig.id
}
tags = {
Name = "Public Route Table"
}
}
resource "aws_route_table_association" "public_1_rt_a" {
subnet_id = aws_subnet.blog_public_subnet.id
route_table_id = aws_route_table.public_rt.id
}
resource "aws_security_group" "blogSG" {
name = "Blog Webserver SG"
description = "Blog Webserver Security Group"
vpc_id = aws_vpc.blog_vpc.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
2
Answers
In
you have set
but in the actual ec2 instance you don’t create a public IP. Either use module.ec2_instance.private_ip instead or in the ec2 instance associate a public IP with the "associate_public_ip_address" parameter
In order to have a public IP attached to an instance, you have to specify it when calling the module:
By adding
associate_public_ip_address = true
, the module will produce the requested output which you can then reference in thehost
argument.