Reputation: 541
I am planning to create puppet infrastructure on AWS with a server node and agent nodes. To be able to install the puppet server and puppet agent packages, it is required to add the IP's to the hosts file on each of the nodes as below
[puppet master ip] puppetmaster puppet
[puppet client ip] puppetclient
I understand that remote-exec runs after the resource is created. But i want it to run after all the resources are created so that i can get the information about the master and client IP's together. So, i used a null resource to execute the remote-exec provisioner after the instances are created. But I am running into an issue
This object does not have an attribute named "public_ip"
I have tried using id instead of public_ip and it complains that this object does not have an attribute named "id"
here is the full code
provision_ec2.tf
resource "aws_key_pair" "puppet" {
key_name = "puppet"
public_key = file("puppet.pub")
}
# Provision Puppet Server
resource "aws_instance" "puppet_instances" {
for_each = toset(local.expanded_names)
ami = var.ami
instance_type = var.instance_type
key_name = aws_key_pair.puppet.key_name
security_groups = ["${aws_security_group.puppet-server.name}"]
tags = {
Name = each.value
}
}
resource "null_resource" "provisioner" {
count = "${var.total_count}"
triggers = {
master_ip = "${element(aws_instance.puppet_instances.*.public_ip, count.index)}"
}
connection {
host = "${element(aws_instance.puppet_instances.*.public_ip, count.index)}"
type = "ssh"
user = "ubuntu"
private_key = file("puppet")
}
# set hostname
provisioner "remote-exec" {
inline = [
"sudo echo ${element(aws_instance.puppet_instances.*.public_ip,0)} puppetmaster puppet>>/etc/hosts",
"sudo echo ${element(aws_instance.puppet_instances.*.public_ip, count.index)} puppetclient>>/etc/hosts"
]
}
}
locals {
expanded_names = flatten([
for name, count in var.host_name : [
for i in range(count) : format("%s-%02d", name, i+1)
]
])
}
variables.tf
# Set the instances type. For puppet, choose instance with minimum 2GB RAM
variable "instance_type" {
default = "t2.small"
}
# Set the region in which the instances will be provisioned. Default region is N.Virgina
variable "aws_region" {
default = "us-east-1"
}
# Sepcify the AMI to be used
variable "ami" {
default = "ami-09e67e426f25ce0d7"
}
# Set the hostnames for the instances as per the count
variable "host_name" {
type = map(number)
default = {
"Puppet-Server" = 1
"Puppet-Agent" = 3
}
}
variable "total_count" {
default = 4
}
security_groups.tf
# Create Security Groups
resource "aws_security_group" "puppet-server" {
name = "puppet-server-SG"
description = "Security Group for puppet master instance"
ingress {
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = "0"
to_port = "0"
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Name = "puppet-server-SG"
}
}
I am out of ideas on how to achieve this.
Upvotes: 1
Views: 262
Reputation: 238209
Since you are using for_each
, you should use values
first. So it should be:
master_ip = element(values(aws_instance.puppet_instances)[*].public_ip, count.index)
Upvotes: 2