Reputation: 43
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
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
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
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
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