Guru
Guru

Reputation: 43

How to introduce reboot option in remote exec -Terraform

I am running terraform script to create a vm and install the packages(some packages not as showed in below script).After the installation of some packages I want to reboot the vm and again continue with the next step to install the other packages.I am just mentioning the example script which will helps to understand the problem.Can some one suggest how can be done?

    inline = [
      "chmod +x /tmp/script.sh",
      "sudo /tmp/script.sh",
    ]
  }```

Example script.sh as below.

```#!/bin/bash

# install nginx
apt-get update

reboot

apt-get -y install nginx

# make sure nginx is started
service nginx start

error executing "/tmp/terraform_1234501241.sh": wait: remote command exited without exit status or exit signal

Can someone help.

Upvotes: 2

Views: 10617

Answers (4)

rimkashox
rimkashox

Reputation: 1008

You can do it in remote-exec, with shutdown -r 1, it will exit correctly and then reboot. But then you have to wait a full minute before accessing the node again, which is not ideal.

Instead, you can do with a local-exec of this sort:

provisioner "local-exec" {
    command = <<-EOT
      ssh ${local.ssh_args} root@${self.ipv4_address} '(sleep 2; reboot)&'; sleep 3
      until ssh ${local.ssh_args} -o ConnectTimeout=2 root@${self.ipv4_address} true 2> /dev/null
      do
        echo "Waiting for node to reboot and become available..."
        sleep 3
      done
    EOT
}

Upvotes: 0

Andy Shinn
Andy Shinn

Reputation: 28523

I'm offering a different approach to bootstrapping before and after a reboot.

Since you are using a EC2 instance in the cloud you should have access to cloud-init. In fact, it is usually baked into the Debian and Ubuntu EC2 images already.

EC2 has a concept of User Data that you can pass to the instance at boot time. This data can drive cloud-init and in the case of EC2 can even be a regular shell script that gets run at startup. We can also set cloud-init to run on every boot per https://aws.amazon.com/premiumsupport/knowledge-center/execute-user-data-ec2/.

Using this combined with the remote-exec provisioner you could split your script into initial boot script and a startup script that only runs when the initial script has finished.

Assuming something like:

resource "aws_instance" "my_host" {
  instance_type = "t1.micro"
  ami = "ami-00a208c7cdba991ea"
  count = 1
  key_name = var.aws_key_name
  security_groups = "my-tsgsting"
  user_data = file("script2.sh")

  provisioner "remote-exec" {
    inline = [
      "chmod +x /tmp/script1.sh",
      "sudo /tmp/script1.sh",
    ]
  }
}

Your script1.sh would write out a file before restart:

#!/bin/bash
sudo apt-get update

sudo apt-get install nginx -y

# make sure nginx is started
sudo systemctl enable nginx.service
sudo systemctl start nginx.service

sudo touch /etc/.script1-complete

sudo shutdown -r now

Your script2.sh would be a multipart message that sets cloud-init to run every boot and the script to check for the tombstone file existence at the top:

Content-Type: multipart/mixed; boundary="//"
MIME-Version: 1.0

--//
Content-Type: text/cloud-config; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="cloud-config.txt"

#cloud-config
cloud_final_modules:
- [scripts-user, always]

--//
Content-Type: text/x-shellscript; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="userdata.txt"

#!/bin/bash
if [ ! -f /etc/.script1-complete ]; then
    echo "Initial script not run yet, exiting"
    exit 0
fi

echo "Bootstrapping script2..."
--//

This removes any logic needed in Terraform or SSH and instead relies on some existing tooling and a tombstone file.

Upvotes: 2

Satyashil Deshpande
Satyashil Deshpande

Reputation: 196

I think you need to create a wait statement so that the code will know once the VM is up. you can follow this link to write a code https://serverfault.com/questions/152795/linux-command-to-wait-for-a-ssh-server-to-be-up

make an explicit dependency with other resource which shall take output of your reboot task

Upvotes: 0

Ubunter
Ubunter

Reputation: 23

I would change the script for this

Example script.sh as below.


# install nginx
sudo apt-get update

sudo apt-get install nginx -y

# make sure nginx is started
sudo systemctl enable nginx.service
sudo systemctl start nginx.service

sudo shutdown -r now

Upvotes: 0

Related Questions