Provision Digitalocean instance using Terraform - terraform

I am trying to provision a digital ocean droplet using Terraform. I appear to be missing the host argument in the connection block, but am not certain what value I need for digitalocean.
This is my configuration file:
resource "digitalocean_droplet" "test" {
image = "ubuntu-18-04-x64"
name = "test"
region = "nyc1"
size = "512mb"
private_networking = true
ssh_keys = [
"${var.ssh_fingerprint}"
]
connection {
user = "root"
type = "ssh"
private_key = "${file("~/.ssh/id_rsa")}"
timeout = "2m"
}
provisioner "remote-exec" {
inline = [
"export PATH=$PATH:/usr/bin",
# install nginx
"sudo apt-get update",
"sudo apt-get -y install nginx"
]
}
}
"terraform validate" gives me the error:
Error: Missing required argument
on frontend.tf line 11, in resource "digitalocean_droplet" "test":
11: connection {
The argument "host" is required, but no definition was found.

I fiddled around with this and found the answer.
In the connection block we should have the host as:
connection {
user = "root"
type = "ssh"
host = "${self.ipv4_address}"
private_key = "${file(var.pvt_key)}"
timeout = "2m"
}

You can explicitly reference the exported var:
connection {
user = "root"
host = "${digitalocean_droplet.test.ipv4_address}"
type = "ssh"
password = "${file(var.pvt_key)}"
}

I think there is a problem with your syntax.
Try to use like below:
private_key = file("/home/user/.ssh/id_rsa")
I'm using terraform version 0.12.25
Best of luck.

Related

Need help in using count in remote-exec provisioner to retrieve multiple VMs IPs

I want to use count to install a package on 2 of my VMs using a single remote-exec provisioner. As of now, I am doing that individually in 2 provisioners blocks as below.
----present code to use remote provisioner for 2 vms-----
resource "null_resource" "install_nginx_host1" {
provisioner "remote-exec" {
inline = [
"sudo apt install nginx -y"
]
}
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = module.virtual-machine[0].linux_vm_public_ips.instance-0
}
}
resource "null_resource" "install_nginx_host2" {
provisioner "remote-exec" {
inline = [
"sudo apt install nginx -y"
]
}
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = module.virtual-machine[1].linux_vm_public_ips.instance-1
}
}
Can someone please help me in getting the value which I should should to set host using count.index? I tried multiple things e.g.
host = "module.virtual-machine[${count.index}].linux_vm_public_ips.instance-${count.index}"
But it returns the host strings as:
module.virtual-machine[0].linux_vm_public_ips.instance-0
module.virtual-machine[1].linux_vm_public_ips.instance-1
while I want the value of above strings.
This should be pretty straightforward to achieve:
resource "null_resource" "install_nginx_host1" {
count = 2
provisioner "remote-exec" {
inline = [
"sudo apt install nginx -y"
]
}
connection {
type = "ssh"
user = "ubuntu"
private_key = file("~/.ssh/id_rsa")
host = module.virtual-machine[count.index].linux_vm_public_ips["instance-${count.index}"]
}
}
Please make sure you understand how to use the count meta-argument [1].
[1] https://www.terraform.io/language/meta-arguments/count

DigitalOcean droplet provisioning: Cycle Error

I want to create multiple droplets while installing some software onto each of them using a remote provisioner. I have the following code:
resource "digitalocean_droplet" "server" {
for_each = var.servers
name = each.key
image = each.value.image
size = each.value.size
region = each.value.region
ssh_keys = [
data.digitalocean_ssh_key.terraform.id
]
tags = each.value.tags
provisioner "remote-exec" {
inline = [
"mkdir -p /tmp/scripts/",
]
connection {
type = "ssh"
user = "root"
private_key = file("${var.ssh_key}")
host = digitalocean_droplet.server[each.key].ipv4_address
}
}
This always results in the following error:
Error: Cycle: digitalocean_droplet.server["server2"], digitalocean_droplet.server["server1"]
I understand this refers to a circular dependency but how to install the software on each server.
As mentioned in my comment, the issue here is that you are creating a cyclic dependency because you are referring a resource by its name within its own block. To quote [1]:
References create dependencies, and referring to a resource by name within its own block would create a dependency cycle.
To fix this, you can use a special keyword self to reference the same instance that is getting created:
resource "digitalocean_droplet" "server" {
for_each = var.servers
provisioner "remote-exec" {
inline = [
"mkdir -p /tmp/scripts/",
]
connection {
type = "ssh"
user = "root"
private_key = file("${var.ssh_key}")
host = self.ipv4_address # <---- here is where you would use the self keyword
}
}
[1] https://www.terraform.io/language/resources/provisioners/connection#the-self-object

SSH isnt working in Windows with Terraform provisioner connection type

I tried Creating Instance in AWS using Terraform and try to copy a set of files into the newly created AWS Instance. I used "provisioner" for the same but for the connection, it always says connection timed out.
In the example below I showed like its AWS Pem file but I tried with both ppk and pem files. nothing works.
provider "aws" {
region = "ap-southeast-1"
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
}
resource "aws_instance" "firsttest" {
ami = "ami-061eb2b23f9f8839c"
instance_type = "t2.micro"
key_name = "deepak"
provisioner "file" {
source = "index.html"
destination = "/home/ubuntu/index.html"
connection {
type = "ssh"
user = "ubuntu"
private_key = file("D:/awskeyterraform/deepak.pem")
host = "${aws_instance.firsttest.public_ip}"
}
}
user_data = <<-EOF
#!/bin/bash
apt-get update -y
apt-get install -y nginx
systemctl enable nginx
service nginx restart
touch index.html
EOF
tags = {
name = "terraform-firsttest"
}
}
Expected should copy the index.html but actual the connection timed out to connect to the newly created instance
In Windows, SSH module Connection doesn't accept "*.pem". Instead, it accepts the PEM file after renaming it to "id_rsa".
provider "aws" {
region = "ap-southeast-1"
access_key = "${var.access_key}"
secret_key = "${var.secret_key}"
}
resource "aws_instance" "firsttest" {
ami = "ami-061eb2b23f9f8839c"
instance_type = "t2.micro"
key_name = "deepak"
provisioner "file" {
source = "index.html"
destination = "/home/ubuntu/index.html"
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file("D:/awskeyterraform/id_rsa")}"
host = "${aws_instance.firsttest.public_ip}"
}
}
user_data = <<-EOF
#!/bin/bash
apt-get update -y
apt-get install -y nginx
systemctl enable nginx
service nginx restart
touch index.html
EOF
tags = {
name = "terraform-firsttest"
}
}
Hope this should solve the issue.

Remote-exec not working in Terraform with aws_instance resourse

I have this below code when I run apply it gets a timeout. An instance is created but remote-exec commands don't work.
I am running this in the windows 10 machine.
Terraform version is v0.12.12 provider.aws v2.33.0
resource "aws_instance" "web" {
ami = "ami-54d2a63b"
instance_type = "t2.nano"
key_name = "terra"
tags = {
Name = "HelloWorld"
}
connection {
type = "ssh"
user = "ubuntu"
private_key = "${file("C:/Users/Vinayak/Downloads/terra.pem")}"
host = self.public_ip
}
provisioner "remote-exec" {
inline = [
"echo cat > test.txt"
]
}
}
Please try to change you host line to
host = "${self.public_ip}"
Letting people know the actual error message you are getting might help too. :)

Terraform openstack instance doesn't return floating ip

Im setting up and openstack instance using terraform. Im writing to a file the ip returned but for some reason its alwayse empty (i have looked at the instance in openstack consol and everythign is correct with ip, securitygroups etc etc)
resource "openstack_compute_instance_v2" "my-deployment-web" {
count = "1"
name = "my-name-WEB"
flavor_name = "m1.medium"
image_name = "RHEL7Secretname"
security_groups = [
"our_security_group"]
key_pair = "our-keypair"
network {
name = "public"
}
metadata {
expire = "2",
owner = ""
}
connection {
type = "ssh"
user = "vagrant"
private_key = "config/vagrant_private.key"
agent = "false"
timeout = "15m"
}
##Create Ansible host in staging inventory
provisioner "local-exec" {
command = "echo -e '\n[web]\n${openstack_compute_instance_v2.my-deployment-web.network.0.floating_ip}' > ../ansible/inventories/staging/hosts"
interpreter = ["sh", "-c"]
}
}
The host file generated only gets [web] but no ip. Anyone know why?
[web]
Modifying the variable from
${openstack_compute_instance_v2.my-deployment-web.network.0.floating_ip}
to
${openstack_compute_instance_v2.my-deployment-web.network.0.access_ip_v4}
solved the problem. Thank you #Matt Schuchard

Resources