Learn how to use TerraForm with AWS.
In this course from Derrick Morgan, you will realize within a few minutes of
watching how amazing Derek is as an instructor. Hello, and welcome to the build a development
environment with AWS and TerraForm resume foundations project. So a resume foundations
project is a short project that is tailored to cover the important aspects of a technology in
order to help you build the foundations necessary to build your own projects and apply them to your
resumes. So let's take a look at what you're going to find in the course. In this two hour project
centered around TerraForm. You're going to use VS code and deploy an AWS EC two instance, along
with the VPC, Internet Gateway security groups, et cetera, that will serve as a remote development
environment that you can log into directly from VS code will utilize several TerraForm tools
and functions such as TerraForm, state format, replace console variables, conditionals, file,
template file, and more. We'll also use AWS user data and a local exec provisioner to bootstrap the
EC two instance and add its connection information to your VS code SSH configuration file,
allowing you to modify it for your own projects. Since we'll make heavy use of documentation
and highlight the process behind developing a brand new TerraForm deployment,
you'll have the skills you need to dive deeper into TerraForm and add this
extremely in demand skill to your resume. So what are you waiting for, sign up today.
And don't forget to terraform apply yourself. So let's start out right here in the AWS
console. And let's go to I am. Now as you can see I've recently visited but just in case
you haven't, you can just search right up here in the search bar. Let's click on
that. And now let's click on Users. Now within users, you may see a lot more
information here I've actually hidden most of mine, let's go ahead and create
a new user. So we'll click on Add Users. And for the user name, feel free to use whatever
you'd like. I'm just going to call it VS code. And now I'm going to choose
access key programmatic access, we're not bothering with a password, this is not
going to be a user that logs into the console. So go ahead and click that in next permissions.
Now as you can see, I've got a group of admins, you can of course, create a new group, or you
can just attach the policies directly. And I'm going to do that just click on Attach existing
policies directly click on administrator access, and then click next tax. Now feel free to tag
it if you'd like to, I'm not going to bother. The next review, we've got right here our user
name programmatic access, and administrator access. Go ahead and click on Create user.
And right here, you'll see that you've got your access key ID and your secret access key.
Go ahead and download that CSV. As you can see, I've already installed Visual Studio code it was a
pretty straightforward process, I am on a Windows machine. But this of course will also work on a
Mac or Linux. So go ahead and first things first, let's get the AWS extension installed. So
click on the extensions icon here on the left, and then search for AWS. And once you've done
that, we've got this AWS toolkit here, go ahead and click Install. Looks like everything installed
fine. So I'm going to go ahead and close this pane and close this tab. And then I'm going
to click on this little AWS icon. As you can see, we've got connect to AWS
right here. But before we can do that, we need to get some credentials installed.
So head up to View and command palette. Then as you can see, I've searched for this
before, but if you need to get to it, you can type AWS and then start typing create credentials
profile, just like so. And then open that. And as you can see here, I've got a credentials
profile called VS code. If yours looks different, make sure that you get this looking the same if
you want to follow along in the course exactly. But of course if you don't or you're comfortable
making simple modifications, you can name this whatever you'd like. But what we need to do
is populate this AWS access key ID In secret access key. So go ahead and open your credentials
file and paste this information in. Just like so. Alright, and once you've done that, go ahead
and Ctrl S to Save this file, you should not have this white dot that was up here before, then
close this tab, and then click on Connect to AWS. And you should see your profile right here.
If not, you can obviously type profile VS code if you need to, and just click on that, and
default region of US East one, I actually don't want that region, I'm going to use a different
one. But whichever region you choose, you can choose that here, I'm just going to say no. And
I'm going to add US west to that's the region I typically use in my courses, because there's so
much default stuff that goes on in US East one, I just prefer to stick with us West too, but it
is totally up to you. So once you've done that, you can go ahead and minimize that. And then
open the extensions panel again, let's go ahead and add something that will give us a little
TerraForm syntax highlighting, let's go ahead and type in TerraForm. And as you can see, there is an
official TerraForm extension here, it's rated 2.5. It is pretty buggy, it might be better now that
you're watching this video, feel free to choose this one if you'd like. But I'm actually going to
use this one here, it's just got a higher rating. And it's been pretty consistent for me. So I'm
going to install this one, just like so. Alright, and I'm going to close that tab and close my
extensions. So now that we've got our extensions installed, let's go ahead and create our working
directory. So I'm going to go ahead and click on Open folder. And I'm just going to set mine up in
the Documents directory, feel free to set this up wherever you'd like of course, just like so.
And then I'm going to create a new directory. And I'm just going to call it TerraForm. Just like
so. All right, and I'm going to open that and hit select folder, just like so. Alright, so now we
have a working directory, we've got our extensions installed, everything is ready to start the
course. Now it's a fairly straightforward build, we're going to cut it down to the bare necessities
because you don't need much for your development environment, the more resources we add, the
more can go wrong. So let's just make sure that we keep it as small as possible. And then
of course, as you develop new requirements, you can build out your environment to meet your
needs from there. So what we're going to do is we're going to use VS code on our terminal.
And then we're going to use the TerraForm configuration files, providers variables, main
terraform.tf VARs, which of course, we will be explaining all of these throughout the course.
And then we've got a configuration file here that's going to configure VS code based on the IP
and other information of our developer node. And we've got our user data that's going to bootstrap
that node. Now in AWS, we will build out a VPC, we're going to build out an Internet Gateway,
public route table, a security group, a public subnet, and an EC two instance. So all of this
together will form our developer environment. And once we're done, after all of these files have
been processed, and everything is good to go, your VS code terminal will have access directly to
this EC two node to deploy a remote SSH session, which will allow you to have file and SSH access
to your EC two node to run whatever you need. So that's a very high level overview. Let's go ahead
and get building. So here I am in the AWS provider documentation within TerraForm. And a provider is
basically used by TerraForm to interface with the API of whatever infrastructure you're trying to
build. So in this case, you're trying to build AWS infrastructure. So you use the AWS provider, if
you're using GCP, or Azure, or VMware or whatever else you will use their respective providers. So
as you can see, it's pretty straightforward. Since we've already provided credentials, we don't need
to provide those within the provider block here. If you scroll down, you can see there's actually
lots of ways to add these credentials. But again, we already have a profile. So all we need to
do is access the shared credentials file, just like this. So let's go ahead and we'll keep it
fairly simple. I'm just going to copy this here. And then within our TerraForm directory here,
which we created Earlier are going to create a new file. And let's call this providers.tf. Just
like so. And we'll paste that in. Now I'm actually going to remove this version block here, because
you may be in the distant future, and not on version three anymore. So again, I'm going to just
remove that and let you download whatever version is current. Now after that, we need to add our
provider block, that is the required providers block. And that provides configuration that
TerraForm needs to know about. But the provider block itself provides the information needed to
access AWS specifically. So if you scroll down here, you can actually see that we have some usage
examples. And we have one right here with shared credentials file already here for us. So let's
go ahead and just copy this one. And I'm going to paste that right here. Now again, typically,
I type all of this out. But since this is a very quick course, I want to make sure it is as
streamlined as possible for you. So here, I'm just going to remove this. And I'm just going to add
that little squiggly right there to indicate the home directory, dot AWS slash credentials. Because
that's where our credentials file is stored. Now, if you've moved it, of course, you'll want to
change this. But this is actually the default for Windows and Mac. So you should be good to go. Now
for the profile, remember, that was named VS code. And the region is US West two. So this is
what you should have here for the provider. Again, if the documentation did not provide
this exactly, of course, just copy it from here. All right. So now that that's done, let's
go ahead and run a TerraForm init to initialize this and connect to AWS to ensure everything
works out. So I'm going to click on terminal and new terminal just like so.
Let's go ahead and I'm going to pull this up a little bit, clear this screen.
And let's go ahead and run TerraForm init. All right, TerraForm has been successfully
initialized. As you can see, we've got hashey Corp, AWS version 3.7 1.0. At least
that's my version, your version is different, that is perfectly fine. Also, you
can see that TerraForm has created a lock file TerraForm lock dot HCl. And what that's
going to do is ensure that the version is frozen. Again, you can change this if you'd like. And
this should be the current version you're using. But this is something you might want to keep
in your GitHub or git lab or wherever you're storing your code repository so that you can
ensure that every time you run this code, it always uses the same version of the provider, and
you have a much lower risk of having some sort of issue with an upgrade. So it looks like everything
is all nice. And initialized. As you can see here, I can do this drop down. And you can actually
see the provider which for Windows is an exe. And for Linux and Mac, you'll actually see another
binary there. But this is compiled and you're not going to go digging through it. As you can see
here the VPC is actually pretty straightforward. You basically specify the resource, this
being the actual resource, as you can see, AWS VPC, this is a static value that cannot be
changed. If you change this, you're not going to deploy a VPC. Now after that, we've got the
name for this VPC, which in this case is main, we can name it, whatever it is, we want. This is
a logical name that only TerraForm knows about. So this isn't going to show up in AWS anywhere.
So again, make sure you understand that, but this is how we will reference this VPC in future
lessons. And then we just provide a cider block. Now there are also lots of other options that
you can specify here. As you can see, it gets pretty complicated. If you go down to the argument
reference, you can see that we have a lot of stuff here we can use, such as enabled DNS support,
which defaults to true in enabled DNS host names, which defaults to false. So let's go ahead and
let's utilize this to create a VPC, we're going to bring my VS code back over here. And I'm going
to create a new file and we're going to call that main.tf. So I'll create a new file main.tf
Just like so make sure that it is in the proper directory here and you didn't accidentally
add it within the TerraForm directory here. And we've got that up. Now, the way these TF
files are processed is they're processed as if they're all the same file. So if you have 20,
TF files in here, all with different resources, they're all going to be processed Test as if
they're the same file. So keep that in mind. You can split up your code, however makes sense
to you, you can have a compute.tf networking.tf, whatever you'd like. It's all processed the
same as long as it's in the same directory. So let's go ahead and create this VPC
resource. So I'm going to type resource, AWS VPC, just like so. So this, of course,
is specifying that I want a resource, or here I wanted a provider. Here, I want a resource. Now
once again, let's name this VPC. I'm going to name it MTC for more than certified VPC just like so.
And then I'm going to use some curly braces here. This will wrap our entire resource that
I want to specify that cider block. And in my case, I'm going to do 10.123 dot 0.0
slash 16. If you've taken my other courses, you've probably seen this cider block before.
Now under that, let's say I want to enable DNS host names. As you remember, DNS host names
defaults to false. So if I want to enable this, I need to make sure that I add
it. So I'll go ahead and enable DNS host names equals true just like so. And if
I wanted to, I can also say enable DNS support equals true. Now we don't have to because this is
assumed, however, depending on your development team, you might want to ensure that this is
explicitly mentioned, your team may not understand what's default for your VPC. And it might be
very helpful to be very explicit and specify some things that default is true as true just to ensure
that when it's easy to modify, and to your team knows that this is enabled, again, not required,
but it's something you might want to do. Now under that, we're going to specify some tags. And I just
want a name for it. And I'm just going to name it Dev, just like so. So I know that this is my
dev VPC whenever I go searching alright, and as you can see, I've got my two curly braces
here. One is to enclose these tags, and one is to enclose this resource. So that's all I need
there. Let's go ahead and run a TerraForm plan, just like so. And what this is going to do
is let us know what we're trying to build. Just like so as you can see we've got all of
these new pieces that are going to be created. Within our VPC resource, we're going to have our
cider block and Arn will be created which we won't know until we actually apply it in the same with
a lot of this other information such as the ID we will not know until we apply it. Now as you can
see we've got these green plus marks that means that these are all being added. So that all looks
good. We've got one actual resource AWS, VPC dot, MTC VPC to add. So what we want to do next is
apply we'll run a TerraForm apply, just like so. And as you can see, it basically runs another
plan, and then asks us to confirm and to confirm, I'm going to type yes, scroll this up a
little bit, and our VPC is being created. All right, perfect. Our apply is now complete.
So if we go over here to our AWS pane, I'm going to click no here I do not need us
East one right now because I am in US West. I'm then going to click on Resources. And as you
can see, I've actually got some resources already shown here that's from a previous installation.
If you click on this little sprocket type AWS colon colon EC two colon colon VPC, you can also
search for VPC, you can see that that's been added, go ahead and checkmark that and click OK.
To ensure that resources added, then if you click on it, you'll see our brand new VPC is here. So
there's our cider block, our default network ACL default security group, it looks like
everything is here enable DNS host names is true enabled DNS support is true, we're going to take
a slight detour from building to dive into the TerraForm state a bit. So we better understand
how information about our deployment is stored for TerraForm. To use. This is probably one of the
most important concepts with TerraForm. So make sure you read over the documentation a good bit
if you really want to understand how things work. But essentially, we're just going to take a
look here and see exactly what is stored in our state as we deploy resources. As you
can see, there's a lot here in the docs. And we're going to explore several pieces
of this as we build our infrastructure. So here we are right here after we have now
deployed our fresh new VPC. As you remember, in our AWS resources pane here, you can see all
of this wonderful information about our VPC. Now, another way we can see what we've deployed, is
to head into our Explorer. And right here, our terraform.tf state file. As you can see, we have
a lot of the same information default network ACL default route, table ID, security group ID, the
VPC ID there. As you can see, all of that is here, VPC ID, default network, ACLs, security group,
etc. Now, it's formatted a little bit differently. But it's, for the most part, the same information.
And this was all pulled right from the AWS API. So now typically, you're not going to
want to traverse this tf state manually as it will normally be stored somewhere off site,
whether it's in TerraForm, cloud or in AWS, or somewhere else. So we have several
different tools, we can use command line tools to access the state. So let's take a look at
TerraForm state list just like so. As you can see, we only have one piece and our state one resource
that MTC VPC that we deployed. So if I want to see that information within that VPC, I can run
a TerraForm state show, AWS VPC dot MTC VPC, as you can see shown right here, I hit ENTER
on that. We have all of the same information. So we've got information here from our API,
we've got information here within our state, the state file specifically. But this
is all the same information. It's just formatted a little bit differently.
Now you can output as JSON and really manipulate that output. But we're not
going to dive into that right now. All right. And of course, if you want to see the entire state,
all you have to do is just type TerraForm show. So keep that in mind. TerraForm state
show requires you to insert a resource. Now TerraForm show is just going to show
you everything that you've got, which of course can be massive if you have a very large
environment. So those are the basics of our state, and the information that's being stored within it.
There are a lot of commands that you can use to manipulate that state to refresh it to migrate it.
But we're not going to dive into that right now. But just know, it'll be very beneficial to you.
If you dive into the documentation a little bit, and just read all about state as it is the
most important feature within TerraForm. We're going to check out a command almost as fun
to use this TerraForm apply, but much more fun to say. And that command is TerraForm destroy.
So TerraForm destroy is pretty straightforward. Basically, it's going to destroy anything that
we have created. And as you can see here, you can actually run a TerraForm apply dash destroy.
But we typically just use TerraForm destroy, there's not a lot else going on here that
you need to really worry about, you can run a TerraForm plan in destroy mode, which will tell
you what happens when you destroy. So that can be fairly useful if you need to test something out.
But for the most part, we're just going to run this TerraForm destroy. So let's do that. Let's
knock out this VPC that we created completely delete everything we have applied. So just run
TerraForm destroy. And then we can just use a dash auto approve if we don't want that confirmation
dialog, again, useful in automation. Probably wouldn't use this in production. If you're typing
it yourself though. Let's go ahead and run that. Alright, right, the destruction is complete,
everything is gone. So that's really all you need to know there. So go ahead and reapply
it as we're going to need this VPC for pretty much the remainder of the course. So TerraForm
apply, auto approve, just like so. All right, all set. We're back to where we left off. You saw
how easy that was. This is one of the great things about TerraForm infrastructure just comes and goes
as you need it. We're going to deploy a subnet to which we can deploy our future EC two instance.
As you can see here in the docs, it's pretty straightforward. Although there are a few more
options, we're going to want to add one of them and if you scroll down here is To map public IP
on launch, default is false. We want to make sure that our instance receives a public IP address
whenever we launch into the subnet, so we want to ensure we add that so let's go ahead and get
started. All right, so right here under my VPC, we're going to add another resource. And that
resource is AWS underscore subnet. Just like so. And then let's go ahead and name it. I'll just use
MTC underscore public underscore subnet, just like so. And you don't always have to add a prefix like
this. Although I've been doing it for so long. If I did not add this prefix, this course would be
way too long due to all the errors I've made. So for consistency sake, I'm just going to keep this
MTC prefix on all of my resources. All right, so let's go ahead and open and close those resource
braces. And what we need to do is provide a VPC ID now as you remember, when we ran our TerraForm
state list, we've got a list of our resources. And this is how we want to access this VPC
resource. So what we're going to do is AWS VPC dot, MTC underscore VPC, which again, matches
this as well. And since this is another resource, it's like a variable, it's not a string, so you're
not going to quote this. This is a reference to a resource, so you don't need to add quotes. And
then what we need to do is just specify an ID. So if I do the TerraForm, state show, AWS, VPC
dot, MTC, VPC, just like so we can see that it has an ID attribute. And that's the ID that we need
for our subnets. So we just specify that.id Right there. And that's how you're going to reference
most of the resources that you have to reference from other resources. So next, we
need to provide our cider block. And that's going to equal 10.123. And I'm just
going to say, dot 1.0, slash 24, which, of course, is one of the subnets within this slash 16. And
then after that, we're going to add our map, public IP on launch, that's a long one there,
equals true and since this is a Boolean, it's also not quoted. And then we need to provide an
availability zone, just like so. And that'll be US West. And we're just going to use to a or at least
I am, because I know a is probably good to go. There are ways to use what are called data
sources to ensure that this is always correct, especially if you're using multiple availability
zones. But we're not going to dive into that now. But feel free, of course, to research that if you
are curious. So next up, we're going to add tags. And that name equals Dev. Public, we'll just
go with that. So the VPC, we just named Dev. And we'll just name this here as dev public
so that we know that it's a public subnet. Again, map public IP on launch equals true
is a good reason for us to want to make sure we label it correctly. So we don't accidentally
put sensitive resources in this subnet, which of course, could cause a security nightmare. Alright,
so that's all we have to do for this subnet. Let's go ahead and run our TerraForm plan. All right,
we've got one resource to add. So that's good and AWS subnet is going to get added. As you can
see, everything we have specified is listed here. And of course, certain things like the ID are
known after apply. So let's go ahead and run a TerraForm apply. And then I'm just going to add
auto approve, you're not always going to do this. But if you're running a plan first, it's usually
pretty safe to go ahead and just auto approve it, and not have to type that yes, every single
time. This especially is useful in automation. So I'll go ahead and run this. All right,
one added, everything looks successful. So I'll go ahead and click on this sprocket
next to resources, which again is in the AWS pane. And I'll go ahead and type subnet. As
you can see, we actually do not have subnets available. This is a limitation of this AWS
plugin, so we're not going to worry about it. But it looks like that subnet creation was
successful. And of course, you can always go into the AWS console to verify we are going to give
our resources a way to the internet by creating an Internet Gateway. We will then introduce TerraForm
format to clean up our code a little bit. So let's get started. As you can see here, the
Internet Gateway is pretty straightforward. It's actually a really simple resource to deploy.
We've got a few attributes here. These are the things that will be exported. within our
state, and these are the arguments VPC ID tags and default tags. So let's just go ahead and
knock this out. Alright, so here we are. Let's go ahead and scroll down a little bit under
our subnet, and we will add a new resource. AWS Internet Gateway just like so. And we'll
call that the MTC Internet Gateway. All right, and then I will open and close my braces. Let's
add that VPC ID. And remember how we access this VPC AWS, VPC dot, MTC vpc.id. Just like so in
fact, I can even copy this to save a little bit of time, and just paste it in. And then just for the
heck of it, I'm gonna go ahead and add some tags. And we'll give it a name of DEV Igw, just like
so. So we've got our dev VPC, our dev public, and our dev Igw. So once we've done that, that's
literally all we've got to do. But let's go ahead and introduce that fun new command. If you go
ahead and run a TerraForm, FMT, just like so what that just did was that corrected any type
of inconsistencies we've got in formatting, as you can see, main.tf and providers.tf,
or both corrected. Now, unfortunately, I was not scrolled up. But as you can see, now
all of our equal signs are lined up perfectly. So it made some very minor formatting
changes, but it looks a whole lot better. So that's great. And if you want to
see it in action, just go ahead and move that a little bit. Run the command again.
And as you can see, it automatically corrects. Alright, so let's go ahead and deploy this brand
new Internet Gateway. Go ahead and run TerraForm plan, just like so. All right one to add. As you
can see, we've got our Internet Gateway that's going to get added. So let's go ahead and run
a TerraForm apply. Auto approve, just like so. Okay, apply complete, everything looks
good. Let's click on our AWS pane. And let's see if we can access this resource.
Just go ahead and type internet. Haha, AWS Internet Gateway, we've got it. So
let's go ahead and check that and select OK. And if I expand my resources here, and
take a look under EC two Internet Gateway, we'll see we've got two. So if I
click on the one with the longer ID we can see right here that
we've got our Internet Gateway. With the proper tag, we're going to create a
route table to route traffic from our subnet to our Internet Gateway. All right, here I am
in the docks. And as you can see, there's a note here. And basically, you can use a standalone
route resource. Or you can define routes in line. Now in this case, they have the routes defined
in line just like so we're going to do it a little bit differently, we're actually going to
use a route resource, which as you can see here is also fairly straightforward. And we'll
walk through this here shortly. So let's head back over to our route table. As you
can see, all we basically need is the VPC ID, and then we'll provide some tax. So let's go ahead
and do that. So I'll open my main.tf. Once again, scroll down some, let's go ahead and create
that resource AWS route table, just like so. MTC public R T, just keep
it from getting too long, and open and close our resource braces. And within
here we need to provide that VPC ID again. And as always, I'll just copy this and paste it
right there. And then we'll add some tags. Name equals Dev, public AR T, just
like so. So now that we've done that, once again, remember, we then need to add the AWS
route, which is right here. And basically we need to specify a route table ID, destination cider
block. And in our case in Internet Gateway, so let's go ahead and do that. So we'll create that
resource AWS route just like so. default route is what we'll call it. This is a default route, of
course for all traffic to get to the internet. Open and close those resource braces, route table
ID equals and we're going to need to Use the AWS route table in TC public RT AWS route, table
dot MTC public RT. And once again, all we need to specify is the ID, it's asking for an ID.
And pretty much universally, all AWS resources are going to have this ID attribute. So then we
need a destination cider block, just like so. And that's going to be 0.0 dot 0.0 slash
zero, which means all IP addresses will head for this internet gateway. And then again,
that Gateway ID is now going to be AWS Internet Gateway just like so. Dot MTC and as you can
see, VS code is providing me some nice little hints. So I'm just going to hit Tab, Internet
gateway.id. Just like so if we scroll up, we can see TC Internet Gateway right here.
All right, perfect. That's all we need to add. So let's go ahead and I'm going to scroll this
up. Let's go ahead and run that TerraForm plan. And we should have two resources to add this time.
Perfect to to add, we've got our route table. And we've got our route. So that's great. Let's go
ahead and run our TerraForm apply, auto approve. And everything was applied successfully. Let's
go ahead and click on the little sprocket next to resources and see what we have to
offer. So what we've deployed is a route table. AWS EC to route table great. And then I actually
do not see a route that we want to use. So we're just going to take a look at the route table. All
right, here it is. It's going to be one of these dev public route table. Perfect. We're going to
bridge the gap between our route table and our subnet by providing a route table association.
So let's go ahead and get started. As you can see here in the docs, the AWS route table
association is actually pretty straightforward. Basically, we just need to access
our subnet and our route table ID. And just specify both of those in an association.
So let's go ahead and knock that out. All right, so I'm gonna go ahead and scroll
down under this route here, resource and AWS route, table Association,
probably one of the longer resource names, MTC public, and I'll just call it an a sock
there and open and close my resource braces, we need to provide our subnet id. In
that we just scroll up and take a look. AWS subnet, MTC public subnet and then once
again, we just need to provide the ID of that. So AWS subnet auto complete that dot MTC
scroll down here public subnet remove some typing and potential for errors.id. Just
like so. So that's all we've got to do there. Then we need to provide a route table ID in that
once again, we can just copy right from here. And paste in. All right. So that is
literally it. Let's go ahead and save. And then I'm also going to run another
TerraForm FMT just to clean things up, look at that much more beautiful. All right. And
then let's go ahead and run our TerraForm plan. Perfect One to add our route table Association.
And we'll run a TerraForm apply, auto approve. All right, that is all set and all done. And
if we want to see that association and some of the other things we've created, we can't
access those from the resources. So of course, we can always go to the console
here. We can access the VPC area and the route tables. We've got our dev public
RT right here. Take a look at our subnet associations. And there it is. Our dev public
subnet is associated with this route table, we're going to add a very important resource
to our deployment, the security group. So here we are on the documentation, as you can
see here is an illustration of the usage of a security group. Now in this case, they've actually
defined the ingress and egress in law Live, which is perfectly fine. Now you can specify
them separately, as you can see by this note, as a security group rule resource just like we did
with a route resource. But this is perfectly fine. Now in your organization, you may find a benefit
to adding separate resources. But in our case, this will work perfectly. So as you can see here,
the egress actually allows egress to everything on any protocol, that's zero to zero. And then
the protocol is negative one, which means UDP, TCP, ICMP, etc. Any protocol, you need to use
negative one, we'll cover it now the ingress only allows port 443. But we actually want to allow
everything, we're just going to ensure that we hard code this IP to our own IP, so that we don't
allow someone to compromise that our instance. So let's go ahead and get started. Now, sometimes, I
might actually choose to just copy this and paste it into my IDE, and then modify from there to
simplify things. But since this documentation may have changed by the time you watch this, we're
going to type it out manually. So let's go ahead and start that. We're going to add our resource
like always, AWS security group, just like so. And let's just name that MTC SG for right now,
we'll open and close those resource braces, we'll create a name. That's dev S G.
Sounds good to me. Now, keep in mind, we don't need a tag here, because the security
groups actually have a name attribute. So there's no point in having to tag it, you of course, could
tag it for other organizational reasons. But as far as the name goes, this is perfectly fine.
After that, we need to provide a description dev security group sounds great to
me, we then need to provide a VPC ID, which we've used many, many times, I'm
actually going to just scroll up, copy this and paste it down here just like
so. And then we need to provide our ingress and egress. So let's go ahead
and add our ingress here. From Port, make sure you have that underscore there
from Port equals zero to port equals zero protocol equals, in quotes here negative one,
this is presented like a string TerraForm is not going to honor this negative right here, this
dash. So make sure you specify this as a string. And then cider blocks equals now I'm just going
to put in 0.0 dot 0.0 slash zero. Because I don't want to show everyone my IP address. Make sure
you only add your own IP address here. So you can go to what's my IP or somewhere else to find
your IP address. And then that will be something something something something slash 32. That slash
32 indicates you want to use only this address. But again, I'm just going to put anything
for right now. And I'll be sure to destroy my infrastructure that has this open port and
replace it with my own later. Now as you notice, this is cider blocks with an S which
indicates that it expects a list. Now these brackets allow you to enter lists. So if
you had multiple IPs, you could put a comma here and specify another one after that. But we only
need one. All right, so our ingress is taken care of. Now let's set up our egress. gonna slide this
down a little bit, there we go. egress from Port equals zero to four equals zero. Protocol, once
again equals negative one, insider blocks. In this case, I'm going to allow whatever goes into
this subnet to access anything so you won't put your IP address here. You will make sure you
allow it to access the open Internet. All right, perfect. So that's all we need to do there.
Let's run a TerraForm FMT to clean that up. There we go. Beautiful. Then let's go ahead and run a
TerraForm plan and make sure everything works out. Slide that up. Okay, one to add like we expected.
Looks like everything looks good here from Port zero protocol, negative one to port zero. Perfect.
Let's go ahead and run that. TerraForm apply, auto approve. All right, all complete.
Let's scroll over to our AWS console. I will click on Security Groups Go ahead and refresh that page
here is our dev s g. by open that, click on Edit inbound rules, we can see all
traffic is allowed on all protocols, all ports, custom source, and again in my case is 0.0
dot 0.0 slash zero. All right, perfect. We're almost to the deployment of our EC two
instance. But first, we need to provide the AMI from which we want to deploy. To do this,
we can utilize what's called a data source. A data source is basically just a query of
the AWS API to receive information needed to deploy a resource. In this case, we need an AMI ID
based on some filters we're going to provide. So let's get started. So if I head over here to my
data source documents here for the AWS AMI, you can see an example, data AWS Ami. And of course
data basically is like the resource keyword we've been using, we're just using data. Now AWS AMI
is the name of this data source. And of course, this needs to stay the same no matter what. And
then this here can be whatever you want to name it. Now we'll be using most recent, and we'll be
using some filters as well. Now one thing we have to make sure is that we have the correct owner.
Now one way to do that is to use AWS Marketplace. But in our case, we're going to be a little more
specific, let's take a look at how to get the owner ID we need. So if I head into the management
console here, going to type EC two up at the top. Going to open that, if I go to instances and
Launch Instance, let's take a look. I'm just going to type Ubuntu here. And I'm going to deploy
Ubuntu server 1804. That's what I've used in my other courses. And I'm just going to stick to
that for now. 2004 should work perfectly fine. And whatever it is you want, you can choose. But
in our case, we're just going to use this 1804. So what I'm going to do is copy this AMI ID
because an owner ID is not provided here, which is a little annoying. And then I'm going to head back
to my EC to console. And I'm going to click on AMI under images. And right there, make sure you
have public images chosen and enter that AMI ID. And here is our owner. So go ahead and copy that
you're going to need it here shortly. Alright, so once we have that, let's head back over and start
coding this thing out. Let me drop this a little give us some room. So now what I'm going to do
is actually create a new file for this. And we're going to call it data sources.tf. So I'll
just create a new file, and data sources.tf, just like so. And this will just keep things
a little cleaner. So we'll use data, AWS AMI, and we'll just call it our server
AMI or whatever you want to call it, we want to specify most recent equals true.
And then we provide the owners. Now the owners, as you can see is plural. So we're actually going
to use brackets, which makes it a list. Go ahead and paste that owner ID that we got into here. And
of course, if there are other owners, you could but in this case, we just need that owner ID. All
right, now that we have provided our owners here, let's go ahead and provide a filter to get the
correct Ami. So if I type filter, just like so, name equals, and we're going to filter on
name, I know this looks a little confusing, but the filter name is actually name and then
values equals and once again, this is plural, so make sure it's in brackets. Ubuntu slash
images, slash HV M dash S S D slash Ubuntu bionic dash 18 dot o four dash AMD 64. Make
sure you have the right architecture there. Dash server Dash. And then what we're going
to do since there's usually a date here, and we're just going to pull the most recent no
matter what, we're just going to add an asterisk. So instead of the date that we would use here,
we use an asterisk so that any date will qualify. So if I just head right back over here and take
a look, you can see. Basically all we're doing is just putting an asterisk instead of this date, but
everything else is exactly the same. All right, so perfect. So that's actually all we
need to do. Go ahead and save this file. And then let's go ahead and run a TerraForm
apply TerraForm apply auto approved just like so. All right, great. So now that is applied. So
if I open my terraform.tf state right here, again, you would usually use a TerraForm show.
But this is a little bit easier for this. We can scroll down under resources. And
you can actually see we have instances, even though we don't have any EC two instances
actually deployed, there's still an instances section that contains this AMI data source.
And if you look down, you can actually see, we've got an image ID right here, which actually
does not match here. And there's a reason for that. And that is, if you look at the date, 2021
1129, the date of this one is actually 2022 0104. So this is actually a newer instance than
what is in the console, which is why that AMI doesn't match. And for our purposes, that's
perfectly fine, we're going to create a key pair, and then create a TerraForm resource that
utilizes this key pair. This will be used by the EC two instance resource we create
so that we can SSH into it later. So let's get started. All right, I'm gonna first highlight
my main.tf here, and then I'm gonna go ahead and create that key pair. So to do that, and yes,
I am on Windows, Windows actually does have an SSH utility. So I'm going to run the same commands
that I would run on OSX or Linux, SSH dash key Gen dash t. And we will use a more secure key than
the typical RSA we use, let's use Ed 25519, and hit Enter. Now we're going
to rename this key pair here, I'm just going to copy this instead of retyping.
It basically everything before the ID EDI 25519. And I'm going to paste that in. And then we're
just going to name this MTC key, or at least I am, name it, whatever you want here, just make sure
you reference it properly throughout the rest of the course. And I'll hit enter, we're not
going to bother with a passphrase. All right, perfect. It looks like everything is good to
go. Just going to run an LS tilde slash dot SSH here. And that shows me that directory. And
MTC key is there an empty C key dot pub, which is what we'll use for our key resource. So now
let's take a look at the Docs as we usually do. Resource AWS key pair, as you see, we basically
need to specify a resource, AWS key pair and the name that wherever we need to, we'll give it a
name. And then we will provide the public key. Now we could just copy and paste the public key
from our file. But that looks very, very messy. So what we're going to do is use a TerraForm
function, we're going to use the file function. So all we have to do is utilize file and then
enter the path to our key. And what that will allow us to do is specify the key just like
this only much shorter by just passing in a path instead of the full public key. So let's go
ahead and do that. So we'll start with a resource. AWS key pair just like so after that, I'm just
going to call it MTC off, open and close those resource braces. Key name, I'm going to go ahead
and call that MTC key just to keep things simple. And then we need to pass in that public key.
And to do that, we're going to utilize the file function. And we'll quote this and I'll use
that tilde slash dot SSH slash MTC key dot pub. And again, I'm on Windows, but these commands
should all pretty much line up and be the same. So I'm going to go ahead and save that. Gonna run
a TerraForm plan. Make sure everything looks good. I'll scroll up here a little bit. All right,
perfect. So the key pair will be created looks like everything past those initial checks. So I'll
run a TerraForm apply, auto approve, just like so. All right, apply complete. So if I take
a look over here and my AWS resources, we can see if this is one that is available for
us, so I'll just type in key. Unfortunately, key pair does not appear to be one that we can see
right here from this screen. So we'll just head back into the EC two console. I'll click on key
pairs. And there it is. MTC key type EDI, 25519. Everything looks great. We're going to
finally deploy our E See to instance, it won't have anything installed on it yet. But
we'll at least get it scaffolded and deployed. So let's get started. All right, we take a look
at our docks here, the resource is actually called AWS instance, as you can see, in the basic
example, it's using an AMI lookup, which looks very similar to what we have used before. As you
can see, it's got the owner, it's got everything else here. Of course, we already saw how to get
the owner ID ourself, so that's great. And then basically, we just need to provide that AMI and
you reference that by using the data keyword, dot AWS underscore AMI dot Ubuntu ID. So do keep
that in mind where typically with a resource, we would just use AWS vpc.my vpc.id, for instance,
but with a data source, you need to pin that with the word data. And then we'll just
provide a few more arguments. As you can see, there are a lot of arguments for the EC two
instance. So let's go ahead and start coding this thing out. All right, so what I'm going
to do, let's scroll this down a little bit. And let's add our resource. AWS instance, just like
so I'll just call this dev node, just like so open and close those resource braces, we need to
provide an instance type first. And to keep this in the free tier, we will use a T two dot
micro Of course, you can scale that up, but that might cost you some money. And then
we need to provide our Ami. So as you remember, the AMI in our data source here is data dot AWS
AMI dot server AMI data dot AWS underscore AMI dot server AMI, just like so. And then
we just need to add ID to the end. And then let's add some tags. We'll just give it
a name equals, and we'll call it dev dash node, just like so. Now after that, we need to provide
our key name, which of course we created recently. And what we're going to use is AWS key pair,
which of course we just created right here, dot MTC underscore off.id. Once
again, now I see that this says key name and not necessarily ID, but the ID
is perfectly fine. Here the ID will work. Now if you take a look by just running TerraForm
state show AWS key pair dot MTC underscore off we can see there actually is a key name.
So if you want to be more explicit, you can absolutely use key name ID is just a force
of habit. It's something that I do frequently. As you can see, it is the same for both. So
both works perfectly fine. But just know you can use key underscore name if you want to be more
explicit. Alright, so now that we've done that, let's go ahead and give this EC
two instance a security group VPC Security Group IDs. You see this s here,
which means you guessed it, we need to use brackets. And I'm just going to do AWS underscore
security and tab there to autofill. That dot MTC underscore s g. Right there.id. And
of course, if you have multiple you can use comma separation to provide multiple security
groups. And then we just need a subnet id. So that's going to be AWS subnet dot MTC
underscore public subnet just like so.id. Then if we want to resize the default size of the
drive on this instance, we can provide root block device just like so. And you can actually up this
we can say volume, size equals you could say we'll just say 10. We'll keep it in the free tier, which
gives you 16. So we'll just say volume size equals 10, which is larger than the eight that they give
you by default. All right, so that actually is all we need to add for our instance for now.
Let's go ahead and run our TerraForm plan. All right. As you can see, we've got a lot of
attributes there. But everything looks good to go. But actually don't bother applying yet. We're
going to go ahead and come on back to the next lesson and add some user data before we apply this
instance. So we don't have to wait for it and then just re destroy it. We're going to utilize user
data to bootstrap our instance and install the doc per engine. This will allow us to have an
easy to instance deployed with Docker ready to go for all of our development needs. So let's
get started. Now the first thing I'm going to do is just clean up this AWS instance a
little bit, I'm going to cut this out. And I'm just going to take everything that's not
in a block, and place it together. So this will make things look a little more streamlined. So as
you can see, we've got all of our arguments here, followed by the tags block, and the root device
block. And just to be consistent, I'm actually going to cut out this root device block and put it
above the tags block since almost everywhere, we finish the resource with tags. All right, perfect.
So that looks a lot better. So now let's add this user data. First thing I want to do is create
the user data file. So I'll create a new file. And let's just call it user data dot
tpl. Now, this TPL actually stands for template. We're not using this as a template
right now. But just in case in the future, you decide to use it as a template you can
and we'll take a look at templating here in the coming lessons. Alright, so go ahead and
take that script I have provided in this lesson, and paste that in. Now this script, as you can see
is going to update apt, it's going to install some dependencies, it's going to download the Docker
GPG key, it's going to add the Docker repository update once again, install Docker, and then
it's going to add Ubuntu to the Docker group, allowing you to run Docker commands as the
Ubuntu user. I know that was a little quick, feel free to reach out if you have any
questions. So now that we've got this in, it's in our user data dot tpl script, and I
have saved it and this is in our root directory. Let's head back to our main.tf. And let's go
ahead and add this user data to our resource. So what I'll do is just add user underscore data
equals, and we're just going to use the file function here. And in quotes, once again,
user data dot tpl. So what this is going to do is extract the contents from our user
data dot tpl file and use that to bootstrap our instance. So Perfect, let's go ahead and see
if everything works. Let's run a TerraForm plan. All right one to add. As you can see,
we've got our EC two instance here, everything's looking pretty good. As you can
see, our user data is hashed here. So if this user data were to change, it actually would change
that hash and indicate that we need to redeploy our instance. So that's really, really
useful. So now let's go ahead and apply TerraForm apply, auto approve, just like
so. Now, this is going to take a little bit, so feel free to pause, and then come on
back whenever your instance is deployed. All right, as you can see, the apply is complete,
I'm going to head into my PC to console, just like so. And as you can see, it's running.
And I've actually had a few dead ones here. But this new one is running, but it's still
initializing. So go ahead and pause the video once again, hit refresh a few times, and come on back
whenever the status check is green. All right, so now everything is green, we've got to have
two checks past perfect. So now let's SSH into the instance. First of all, I need that IP
address, so we can definitely just copy it from right here. But another way, of course, is to
use our TerraForm state. So if we do a TerraForm state list, just like so we then see our
instance right here, I'm just going to copy that. Then I'm going to do a TerraForm state
show and hit that instance right there. And here's all of the information we can get it
if I scroll up a little bit, I've got the public IP address right here. Perfect. So now what I'm
going to do is just do it SSH dash i. Then if you're on Linux or Windows, you can use the tilde
slash dot SSH slash MTC key or whatever you name that key. Now, if I hit tab that will actually
correct it for Windows users, but it doesn't matter. It works either way. And then I'm just
going to use my Ubuntu username at that public IP address. And hit Enter. Type yes, and bam we are
in the instance now. So if I run a Docker version. As you can see, we now have Docker installed and
the instance is running, we're going to take a look at the configuration we're going to have
to create to allow VS code to connect to our EC two instance. So first of all, if you haven't
already, head over to the extensions, and go ahead and search for SSH. And you should see this remote
SSH app here. Go ahead and install that extension. Just like so. Alright, perfect. So now that
we've done that, we can go ahead and head back to the Explorer. And first thing I want
to do is take a look at some example config files. So you should have a file now at
your home slash dot SSH slash config. So if I do cat, SSH config, just like so. I
can see here that I already have two entries. Of course, this is something I've done before.
And what we need is we need to provide a host, a host name, which happened to be the same here
and the user that we're going to use to log in. So what we need to do is provide the IP address
of our instance, on both of these host areas host and host name. And then we'll utilize Ubuntu for
the user. So how are we going to do that? What we're going to do is we're going to use template
files. And we'll take a look into that very soon. But first, let's create the files. So go ahead
and create a file based on your operating system. Whether you're on Windows, or Linux or Mac,
Linux and Mac can both use the same script, Windows is going to be different. So I'm
going to create both in this lesson. First, I'm just going to create windows dash SSH config
dot tpl, just like so. And if you're on Windows, go ahead and grab that script, copy it, and paste
it in. So basically what this is doing, and you will need to replace your username here. Mine,
of course is Derek yours probably isn't Derek, but you might be go ahead and replace that. And
then this is going to add the host host name user and an identity file, which we didn't see before.
But we do require to our config. Now what we do is we actually specify the host name, the
user and identity file from our main.tf. And we're going to take a look at how to do
that in the coming lessons. So go ahead and save this file if your windows. And if you're
Linux, let's go ahead and create that one. So again, you can call this Mac if
you want, I'm just going to call Linux SSH config for our file name. And this
will serve for either Mac or Linux. And for that, go ahead and copy the script and paste it in. And
what we've got here is we're actually catting into home dot SSH slash config. And then we've got the
host host name, host name, user and identity file, just as we did before. So go ahead and save that
file. If you're Linux, you can also provide both if you utilize both platforms like I do,
we're going to utilize a provisioner to configure the VS code on our local terminal
to be able to SSH into our EC two instance. Now a provisioner is not something you want to
use for every deployment. Unlike other resources, a provisioner success or failure will not
be recorded or managed by TerraForm state. So if something goes wrong, that's just too bad.
There's no rollback or any other way to manage it other than just running it again. While this
is not good for configuring remote instances, it's perfectly fine. For something like this, all
we're going to be doing is adding information to a config file on our local terminal. This is a
lightweight operation that doesn't affect the overall success of the deployment if something
were to go wrong. So with that being said, let's get started. First, we'll take a look over
here at the provisioner documents. As you can see, provisioners are a last resort. Generally
speaking, you're going to want to use user data which of course we do Ansible or
packer, or chef or something else some other configuration management tool. If there's some
sort of configuration we need to do on a remote instance. But once again, on our situation,
it's perfectly fine. And we can use the local exec provisioner to allow us to configure local
machines and run local commands. As you can see, basically we're running a provisioner
and in this case a Local exec provisioner within an AWS instance, resource provisioners are
always run within another resource. This could be something called a null resource also. But we're
not going to look into that right now. Now another thing we're going to use is this self object here,
which basically allows us to access this instance, and access information. So if we need a
private IP, or public IP, or whatever, we're able to access that right here, using
this self attribute. Now, something else you might notice, we've got this dollar sign, and
braces here, that is interpolation syntax. And basically what that means is this is going to be
replaced by whatever it is we're trying to use. So we've got a string here. But this here will be
replaced by the private IP of this AWS instance. And you may have remembered that in our previous
scripts, so let's go ahead and just get to work. So right over here, once again, we can take a
look at our configuration files. And once again, remember these here, the same syntax, these are
going to be replaced by the host name, the user identity file, whatever we need to pass in. So
let's go ahead and start typing our provisioner. Gonna go to the bottom of our instance resource
here, we're going to type provisioner. Just like so. And then local dash exec, we've been using
underscores a lot throughout this script, as you remember, but this provisioner uses a dash make
sure you remember that this is a dash or a hyphen, and not an underscore. This is a mistake I've made
many, many times open and close that provisioner block. Next up, we provide our command. Now
this command is actually going to be run from these files here. And to run these
files and pass in the variables necessary, we won't use the file function, we'll use what's
called the template file function. So we take a look at the template file function here, you can
see that basically, you pass in VARs, after you pass in the path. So for instance, you can take a
look at here template file. And then this here is the path which is using this interpolation syntax
and path dot module, which is a built in variable and then you use a comma. And then within an
object here with these curly braces, you pass in the variables that you need to pass in. So
let's go ahead and do that. So for the path, in my case, since I'm on a Windows machine, I'm
just going to use quotes windows, dash SSH dash config dot tpl, just like so if you're on Linux
or Mac, you'll use the Linux version. And then after that, we need to pass in our variables.
So I'll add a comma here, then open and close some curly braces, and we will pass in these
variables, I'm actually going to indent this. First up, we need our host name. Remember, we had
to pass in a host name there. And that host name is going to be self dot public underscore IP.
Remember, we have a public IP attribute for our instance that we used before, whenever we SSH into
it. So we can just use self dot public IP here to access that after that, we need to provide the
user and that's going to be Ubuntu because that is the EC two instance username that we have.
After that we need to provide an identity file. So that identity file is
going to be our private key. And the private key is located we'll just
use a tilde here slash dot SSH slash and TC key just like so. Alright, so that is all of the
variables we need to pass in. And then after that, we need to pass in an interpreter. Now the
interpreter basically just tells our provisioner what it needs to use to run this script. Now it
defaults to bash so you don't necessarily need to add this for that, but we will just to be sure,
so I'm going to add interpreter, just like so. Equals, and since I'm on Windows, we're going
to use PowerShell and then we need to pass in the next command which is dash command. Now if you
are on Linux, and do not put both of these here, I'm just using this as an example.
For interpreter. You're going to use bash, and we'll have a comma here. And then
dash c is the interpreter you'll use for Linux. But again, I'm on Windows so I'm going to
delete that and keep this here. Alright, so once you've done that, that is everything
We need to do and this will hopefully create our instance. And it will replace the
hostname with self dot public IP the user with Ubuntu and the identity file with this key
here. So let's go ahead and give it a shot. Now the first thing we need to do is we need
to run a TerraForm plan. Pull this up some. Now as you can see, we've got no changes here. That's
because the provisioner does not affect our state, it doesn't read that there's a provisioner there,
and it's not going to change anything just because we added one, we're going to redeploy our EC two
instance. And finally see if everything works. So hopefully, when we redeploy this instance, this
provisioner is going to run add the information required to our configuration file and allow us to
SSH into the instance without any issues. So let's go ahead and give it a shot. So first up, once
again, I'm just going to run that TerraForm plan. And as you can see no changes, which means that
this provisioner is not going to run because TerraForm hasn't detected anything different.
Once again, it does not detect provisioners as differences in the state. So it's not going
to trigger a run. So let's go ahead and take a look at a way that we can trigger that run. First
up, I'm just going to run a TerraForm state list again. And of course, we've got our AWS instance
dot dev node, go ahead and highlight that and copy it. And then what we want to do is use a new
command we haven't used or at least a new flag, we've used TerraForm apply a lot. But now what
we're going to use is a dash replace. Now this used to be known as TerraForm tanked, which
would actually cause a resource to be replaced on the next run. But now instead, we just use dash
replace, I'll go ahead and paste in this instance, dot dev node here. And let's hit enter. All right,
as you can see, we are refreshing the state. Okay, now we've got one to destroy, and
one to add. So it is removing and replacing our instance. And once that happens, it should run
our local exec replacing the content in our config file with what we need. And allowing us to SSH
into our instance from VS code. So let's go ahead and type yes, and pause this video. Come
on back whenever it's done. Of course, you might want to hop into the EC to console. And
once the instance shows up, is running and has to have to complete and green. Go ahead and come
on back. And we'll see if everything worked. All right, all of my checks are passed here.
Let's go ahead and bring our editor back over. And this is now the moment of truth. First
things first, I'm just going to Cat my SSH config file. And this is a really good sign. Look at
that it looks like our provisioner did exactly what we asked it to it added the IP address the
host name, our user and the identity file to our config file. So now that that's happened,
let's head up to View command palette. And let's just type in SSH right here. And as you can
see remote SSH connect to host click on that. And hey, check that out. So we've already got
our IP address ready to go. Let's click on it opens a new window. This is a Linux host.
Again, we're on Windows terminal or I am but it's a Linux host. So Choose Linux here.
Yes, we are sure we'd like to continue. Looks like everything is setting up
downloading installing VS code server. All right, let's open a terminal terminal new
terminal. Bam check that out. And if we run Docker Docker is nice and installed. Once again we can
do a Docker dash dash version. So now we have a perfectly good development environment ready to go
you can open up folders on the remote. Once again home Ubuntu is a remote folder. So if I run that
I am now in a fully remote terminal. Go ahead, I can hit trustees authors. Bam, perfect.
So this is really, really cool. We're going to start optimizing our script and making it more
dynamic by adding variables. So let's get started. Now, so far, we've hard coded pretty much
everything. So now it's time to modify that to give us some flexibility. So that we can adjust
things easily without having to fish through every single attribute here. And instead being able
to go to one file and modify what we need there, for instance, probably one of the things we're
going to modify the most is the type of OS we're using. So since for instance, I use Mac, Windows
and Linux quite frequently, there's a good chance, I'm going to want to be able to modify
which type of instance I'm using on the fly. So let's go ahead and take a look at that. Now
first of all, what I want to do is I want to use interpolation syntax to specify a variable here.
Now, basically, that variable will be calculated whenever we apply our script. So I'm going to use
interpolation syntax, which I've mentioned before, and basically that's going to be $1 sign
in two curly braces, just like that. So whatever happens here is going to be
calculated dynamically whenever we run our script. So let's go ahead and name this variable,
we'll call it var dot host underscore OS. So anywhere we need a variable, you
specify it with var dot variable name, just like so. So now if I choose windows,
then it will be Windows dash, SSH dash config, Linux, Linux, dash SSH dash config, just like so.
So now what we need to do is we need to initialize this variable and specify that, hey, we've got
a variable that we're going to need to define. And to do that, we can either do it here in
line in the main.tf, or what I prefer to do, and most everyone is to create a new file for
it. So I'm going to create a variables.tf file. Once again, it's analyzed just like any other
TF file, it's all run at the same time. But this will just make sure that it's easier to find our
variables when we need them. Now, you can take a look here at the input variables, documentation,
declaring an input variable is actually fairly straightforward, you use the variable, variable
name, and then within braces, you give it a type. And you can also give it a default. Now the type
is not necessarily required, but it is strongly recommended. So that your other DevOps coworkers
don't lose their minds trying to figure out what type of variable is expected. So let's head back
over here, and let's go ahead and build this. So it's going to be a variable, once again, post
underscore OLS, then we'll use our curly braces. And we'll just provide a type and that
type equals string. We're not going to bother with a default yet, but we'll
get to it. So now that we've done that, let's actually go ahead and perform a TerraForm
destroy, auto approve. And as you can see here, it's actually asking for this variable
to be defined now. So keep that in mind. Anytime you add a new variable, any destroy,
apply, or plan operation is going to require that you define those variables. And we'll look
at other ways to define them so that we don't have it popping up every time here from the
command line. But for right now, we can just define it dynamically. So let's just go ahead and
I'm gonna say windows if you're on Mac, or Linux, specify Linux, but again, nothing really matters
now, because nothing is running. So go ahead and destroy this infrastructure. Pause the video and
come on back whenever it's destroyed. All right, so everything is destroyed here. In just to
illustrate, once again, if I run a TerraForm plan, it is going to ask me for that variable. So if I
type that in, then the plan will run. So keep that in mind. Again, if you have variables that are not
set, a plan, apply or destroy is going to ask for those variables. So if you're in automation that
can break your automation, we've now seen how to initialize a variable and how to define it at the
command line. But as we saw, that is not a great way to define variables when an automation as it
requires Dynamic Input, which is the opposite of automated. So in this lesson, we're going to
look at a few other ways to define variables, and which of those ways take precedence over the
others. So let's get started. So first of all, let's take a look at the docs again, and if
you scroll a good bit down, you can kind of see like we've got default values, custom validation
rules. We've got a lot here that's actually really good information. But what we really want
to see is if you scroll all All the way down, you can see variable definition precedents.
So basically environment variables are processed last. So as we go down this list,
these are processed in front of the other. So environment variables are processed last. So if
you have an environment variables set, but then you define a variable in terraform.tf VARs, which
we're going to look at, then terraform.tf. VARs, is the variable we're going to use. And then
you've got terraform.tf, fires dot JSON, which not too many people use, but you can use
it in automation, it does help sometimes, you've then got auto.tf, vars, and auto that
TFR is dot JSON, which are used in TerraForm. Cloud quite frequently. And then you can specify
a VAR and var file option on the command line. But this isn't like a dynamic definition.
It's not like it asks you for the definition and you type it, you just add this dash var
switch, and then you provide the definition. And we will look at that. So let's
go ahead and just take a look, what we're going to do is run the TerraForm
console. And this is a really good tool that will help you work with certain functions and play with
different values and things like that, that you might need to experiment with before you deploy.
So if you run TerraForm console, let's just take a look. As you can see, it did not ask us for a
variable. So if I run var dot host underscore OS can see it's known after apply. So until we
actually apply and specify that variable, then our TerraForm console has no idea what that
host OS variable is. So I'm going to go ahead and type exit to get out of the console. And what
I'm going to do first is just add a default here, so go ahead and add default equals, and then
specify your host, which again, mine is Windows, yours might be Linux. So now let's go ahead and
run a TerraForm console. It was run var dot host underscore OS. There you go. So now it is
processed it basically TerraForm console has looked at all of our configuration files and
saw that we have a default of Windows. So that's awesome. All right, so I'm gonna get out of the
console once again. Now what I'm going to do is I'm going to create a new file, and we're going
to call that TerraForm dot t f bars, just like so. Now, this is the default name for our variable
definition file. So here, all we need to do is define the variable. So host OS equals windows.
Or you know what, I'm just going to type Linux, since we're not running this right now. So now
let's run a TerraForm console, just like so. And let's run var dot host OS. Now it's
Linux, as you can see TerraForm, that TF VARs takes precedence over a default variable set
within the variables.tf. Alright, so that's great. So now I'm going to get out of the console again.
Now let's say we have I don't know a Unix System, or we want a different script that only
works with OSX. And we want to specify that now if we still have these two files, how are we
going to override this value? Now that we have it defined in TerraForm dot TFRs? Well, there are
a few ways to do that. And one way is to specify the variable in line with our command. So if
I run TerraForm, console, dash var equals, and we'll just say host, os equals in Unix,
just like so. Now, var dot host, underscore OS is Unix. So if you need to override everything
that you have specified in any file anywhere, you specify it right here in line,
and again, this could be a TerraForm. Apply or TerraForm plan that you specify this
VAR for in this will override any other files that you've got. So now let's take a look at
one more scenario. I'm going to exit once again. Let's say that we have a dev dot TFRs. Now what
matters is the TFR is not necessarily the word in front. However, TerraForm is going to process
anything in TerraForm, that TFRs by default, so if you have a dev dot, TFR, and let's say
that was host OS equals OSX, just like so, we run a TerraForm console. And then we run Varta
host OS. As you can see, it's still Linux, not OSX. So if we want to pass in this file, we just
need to run TerraForm console. Dash var dash file equals dev.tf VARS. Just like so. And now let's
take a look Farda host underscore OLS is now OSX. Perfect. So now we've seen most of the ways
that TerraForm will process variables and the precedents it uses to decide which variable to
use. So now that we've managed to choose our SSH config file dynamically based on the definition
of our host OS variable, we now need to make our interpreter dynamic. Unfortunately, this isn't
as simple as interpolation syntax replacements. So we need to look at a better way, we're going
to utilize conditional expressions to choose the interpreter we need dynamically based on the
definition of the host OS variable. So let's get started. So what I mean by interpreter, of course,
is this interpreter here, the one that determines what interpreter is going to be used to interpret
our SSH config script. And if it's Windows, it's PowerShell. And if it's Linux, it's bash,
and as you can see, we can't just replace it like we did up here. That was very simple. And
of course, there are ways we could define this. But you know what, since we know that it's
only one or the other based on the host OS, I don't want to create a new variable just to
do this, I'd much rather just continue using the same host OS variable. So if you take a look
at conditionals, here, conditional expressions, you can see basically, you provide a condition
question mark, and then you see the true value, or the false value. So if host OS is Windows,
the true value would be PowerShell. And the false value could be bash, for instance. So let's
go ahead and just hop in and take a look at what this looks like. So I'm going to run the TerraForm
console. And we're going to pass in a variable definition. Of course, we haven't defined all over
the place up here in our files, but we're just going to define it right here in line, instead of
messing with those files right now. So var equals host underscore OS equals windows. For me
anyway, and enter. Let's verify var dot host OS, Windows perfect. So what we want to do is say
if var dot host OS equals and we're using two equal signs here, because we're not setting
this we are checking for equality windows, then first we'll just say PowerShell. And
of course, this isn't the interpreter, we'll use exactly, but just for the sake of
using this now, this will be easier. Or bash, just like so. As you can see, we got
PowerShell. Now if var dot host OS is Linux, and we run this same exact command
again, PowerShell. Bash, then we get bash. So that's pretty straightforward. So what we want
is we actually want this command in the other command, which of course, I've also provided,
and we're going to use those instead of just PowerShell and bash. So we'll say var dot host OS
is Windows, then what we want is in brackets here PowerShell comma, dash command, just like so
and close that bracket. Or if it's not windows, if this is false, then we just use bash,
comma dash c, just like so. Let's hit Enter. And perfect even though the formatting is a
little wonky there, this will be perfectly fine. So go ahead and just copy this directly Ctrl C,
that and for interpreter, I'm just going to paste that in just like so. And that's all we have to
do. So let's go ahead and exit the console there. And let's go up to our terraform.tf
VARS. Make sure that is set to your OS. I'm gonna go ahead and change this to Windows
since that is the OS I'm using variables.tf. The default is Windows, which is fine because
terraform.tf Ours is going to override it anyway. So if that's different, that is perfectly
fine, but you may want to change this as well. And then once again, with that our main TF,
everything looks good. So let's go ahead and run a TerraForm plan. All right, everything looks like
it went through fine. So let's go ahead and apply it TerraForm apply, auto approve, and hopefully
by the time our instance is fully initialized, we will be able to SSH into it just like we were
able to before so go ahead and run this TerraForm apply, pause the video and come on back whenever
your EC two instance is all green. All right, everything has come back just fine. We're
running in all green. So let's go ahead and see if this new IP address is available for SSH. I'll
actually take a quick peek three 4.219 for this one. So I will click on View command palette,
I've already got remote, SSH ready to go. And there it is 342219224 6.58.
Let's go ahead and see if it works. This is a Linux machine, I
would like to continue Yes. And everything is looking absolutely fantastic. We
once again, have our development environment all ready to go. But this time, it's dynamic. Based on
the host OS that we're using, we're going to add a nice little convenience feature to our script. By
utilizing outputs to display information we need, as you well know, we've been manually finding the
public IP address of our instances to verify them. Well, that is incredibly inefficient.
So let's go ahead and add an output to make this a little easier. So as you can see,
we've got output values here. And basically, it's incredibly simple to do. So this, of course,
is how to access a private IP, well, we're just going to access the public IP. As you can see,
we've got a lot of other features as well, such as the ability to mark an output sensitive
so that it doesn't show up on the command line, you've also got a depends on feature as well,
we're not going to dive into that. But we are just going to go ahead and access that public IP
of our instance. So if you run TerraForm console, you can then access all those attributes
of our instance and kind of play with them to see what output we're going to get. As
you remember, it is AWS instance dev node. So if we just type AWS underscore instance, dot
dev underscore node, dot public underscore IP, there it is. So that's very, very simple. And as
you know, you can use TerraForm, show or TerraForm state show to get all of these attributes
that you could use for outputs. So if I get out of this console, and run a TerraForm, state
show, and of course, we'll just use once again, AWS instance, dot dev node, just like so we can
see all of the possibilities that we can use to output. As you can see, we get output instance
types, and here is public IP. So that's what we did, we just accessed that. So let's go ahead
and create this output, what we're going to do is just create a new file output.tf. Once again,
you could add it to our main.tf. But we just want to clean things up a little. So output. Here,
we'll just call this dev IP, open and close those braces, value equals AWS instance, dot dev
underscore node dot public IP, just like so that's all we have to do. Now to access this output, we
may not want to destroy our entire deployment, just because we added an output, what we can do
is just run a TerraForm, apply dash refresh only. And that's basically just going to consider this
output and add it to the state so that we can get to it, just like so as you can see, we've got
changes to outputs. So that's perfect. So let's go ahead and run this. Apply complete. That's it.
And then we can run TerraForm output. Just like so to see our output once again. And this is very,
very useful in automation. Now, if we take a look in our TF state, scroll all the way to the top,
we can see our outputs are right here. So it's very easy to see what we need to see. So outputs
are incredibly useful. And there's a whole lot you can do. You can get very creative with what types
of output you get. But for our purposes, all we need to know is that IP address which matches
the one that we use to SSH into that instance.