### Introduction Welcome to lab 2. You are going to find the code here very similar to lab 1, and thats by design, we'll build upon our experience and learn how to add variables and use environment files, so that you can reuse the code in say a deployment for dev, stage and prod. This is the power of IaC and prevents you having to rebuild everything from scratch. Now I'll assume you have your AWS account and CloudShell setup already. If not please reffer to the lab 1 [README.md](../1-getting-started/README.md). Remeber i use the command tofu but if you've installed terraform instead you can swap the commands easily enough. In this example we are going to do the same and deploy a VPC with subnets and an instance with a security group attached. What's different is that this time we'll use the ```user_data``` feature of EC2 to run apache and show you a running web server. In the ```main.tf``` file it differs in the ```aws_resource``` block of code to include the command to start apache. ```terraform resource "aws_instance" "test_ami" { ami = "ami-029b91ed285a24a90" instance_type = "t4g.nano" associate_public_ip_address = true subnet_id = module.vpc.public_subnets[0] vpc_security_group_ids = [aws_security_group.web_server_sg_tf.id] user_data = <<-EOF #!/bin/bash sudo dnf install -y nginx sudo systemctl enable nginx sudo systemctl start nginx EOF } ``` I've also updated ```outputs.tf``` to show the public IP address of the instance we've deployed by adding this code block: ```terraform # Public IP of instance output "instance_public_ip" { description = "Show the public IP of the instance deployed" value = aws_instance.test_ami.public_ip } ``` #### Create a Stack Once again lets deploy the stack before editing it: ```bash cd 2-simple-example/code tofu init tofu plan tofu apply ``` Answer yes at the apply prompt and you should end up with a screen like this: ![Tofu apply output](./img/lab-2-tofu-apply.png) Embedded in there you'll see something liek this ```instance_public_ip``` thats out new output, copy the value and head to ```http:///``` and you should get a very similar looking default nginx page. ![Default nginx page](./img/webpage.png) (I'm of course in dark mode, don't worry if yours is white with black text!) Right we now have our basic stack to work with. Everything else we do will be to update this stack, so **don't destroy** it just yet #### Introducing variables Right this is great and all but what if we want to make it easy to change things, such as the ami_id we are deploying or the size of the instance we are running so we have more CPU and RAM. This is where variables make it easy, and as an added advantage we can create variable files for different environments with different values in them to override the defaults. > [!Note] > For this next bit you can use your favourite command line editor to alter the files in CloudShell, vim and nano are installed by deafult, I use vim so if you copy the examples you'll need to press ```i``` after opening the files to go into insert mode and when you want to save and exit the file press ```ESC``` and type ```:wq``` to exit. Right lets add new variables for both the **ami_id** and **instance_size**, start by opening variables.tf in the code directory from CloudShell: ```bash vi variables.tf ``` Scroll to the bottom of the file and press ```i``` for insert then add the following: ```terraform variable "instance_size" { description = "Size of the instance to run" type = string default = "t4g.nano" } variable "ami_id" { description = "Instance Amazon Machine Image to run" type = string default = "ami-029b91ed285a24a90" } ``` Save that file and exit press ```ESC``` and type ```:wq``` to exit (last tiem I'll remind you). Now you've set up terraform/tofu to understand the ```intsance_size``` and ```ami_id``` are variables and we've also given them default values. If you didn't use a dfault in this file when you run apply you'd get prompted to enter the details. Right now terraform/tofu knows about the variables lets use them. Open up ```main.tf``` ready for editing: ```bash vi main.tf ``` Scroll down to the code block called **resource "aws_instance" "test_ami"** and edit the following lines: ```terraform ami = "ami-029b91ed285a24a90" instance_type = "t4g.nano" ``` you want them to look like this: ```terraform ami = var.ami_id instance_type = var.instance_size ``` Now you're ready, it really was that easy. However, if you went and ran ```tofu plan``` right now you'd see that nothing has changed in the stack because our defaults we set on ```variables.tf``` have the same values as before. ![No changes dialog](./img/no-changes.png) #### Using tfvars So lets look how to override those settings. In this example we are going to alter both the ```ami_id``` and the ```instance_size``` to something more production ready. Let's use a Redhat AMI rather than Amazon Linux and a larger instance maybe a t4g.small rather than the t4g.nano. Create a new folder called ```env``` and a new file inside it called ```prod.tfvars``` ```bash mkdir env vi env/prod.tfvars ``` Lets populate it with some new values: ```terraform ami_id = "ami-01d28a73af0a85125" instance_size = "t4g.small" ``` Save and quit the file and we are ready to use it! Let's start by running ```tofu plan``` but we are going to add the argument ```--var-file=``` and point it to our file we just created ```env/prod.tfvars``` ```bash tofu plan --var-file=env/prod.tfvars ``` You'll see theres things to be changed now. ![changes to the stack](./img/changes.png) So let's go ahead and apply that, once again adding our new argument: ```bash tofu apply --var-file=env/prod.tfvars ``` Remeber to type **yes** at the prompt, you'll see terraform/tofu destroy the old instance and bring up a new one: ![Destroying and instance](./img/destroying.png) You'll finally land back at the command prompt. At this point I encourage you to go tot he AWS console and open **EC2 > Instances** you should see something liek this happening, which shows a terminated old instance and a new one either fully booted or initializing. ![Instances swapped over in the console](./img/new-instance.png) There we have it a brand new instance this time running RedHat Linux, it'll also have a new public IP address to view in your web browser. You could go on and update again, adding in aditional arguments to any of the resources we've created. We could use a ```envirnment``` variable for instance to call the VPC a different name and label the instance according to what environment it's running in. You could go ahead and have a plan at this point and create another tfvars file such as ```env/stage.tfvars``` and have different values in there. #### Clean up Don't forget to terminate the resources running in this lab. Run the following: ```bash tofu destroy ``` ### Recap What we've done in this lab is learn how to: - create variables - use variables in out HCL code - create a tfvars file - specify the tvfars file onthe command line - update a running stack