You've already forked devops-exercises
Add Terraform and AWS exercises
In addition to multiple new questions.
This commit is contained in:
@@ -1,112 +1,90 @@
|
||||
## Terraform
|
||||
# Terraform
|
||||
|
||||
- [Terraform](#terraform)
|
||||
- [Exercises](#exercises)
|
||||
- [Terraform 101](#terraform-101)
|
||||
- [AWS](#aws)
|
||||
- [Questions](#questions)
|
||||
- [Terraform 101](#terraform-101-1)
|
||||
- [Providers](#providers)
|
||||
- [Provisioners](#provisioners)
|
||||
- [Modules](#modules)
|
||||
- [Variables](#variables)
|
||||
- [State](#state)
|
||||
- [Import](#import)
|
||||
- [Real Life Scenarios](#real-life-scenarios)
|
||||
|
||||
## Exercises
|
||||
|
||||
<a name="exercises-terraform-101"></a>
|
||||
### Terraform 101
|
||||
|
||||
|Name|Topic|Objective & Instructions|Solution|Comments|
|
||||
|--------|--------|------|----|----|
|
||||
| Local Provider | Basics | [Exercise](terraform_local_provider/exercise.md) | [Solution](terraform_local_provider/solution.md) | |
|
||||
|
||||
### AWS
|
||||
|
||||
The following exercises require account in AWS and might cost you $$$
|
||||
|
||||
|Name|Topic|Objective & Instructions|Solution|Comments|
|
||||
|--------|--------|------|----|----|
|
||||
| Launch EC2 web instance | EC2 | [Exercise](launch_ec2_web_instance/exercise.md) | [Solution](launch_ec2_web_instance/solution.md) | |
|
||||
| Rename S3 bucket | S3 | [Exercise](s3_bucket_rename/exercise.md) | [Solution](s3_bucket_rename/solution.md) | |
|
||||
|
||||
## Questions
|
||||
|
||||
<a name="questions-terraform-101"></a>
|
||||
### Terraform 101
|
||||
|
||||
<details>
|
||||
<summary>Explain what Terraform is and how does it works</summary><br><b>
|
||||
<summary>What are the advantages in using Terraform or IaC in general?</summary><br><b>
|
||||
|
||||
[Terraform.io](https://www.terraform.io/intro/index.html#what-is-terraform-): "Terraform is an infrastructure as code (IaC) tool that allows you to build, change, and version infrastructure safely and efficiently."<br>
|
||||
- Full automation: In the past, resource creation, modification and removal were handled manually or by using a set of tooling. With Terraform or other IaC technologies, you manage the full lifecycle in an automated fashion.<br>
|
||||
- Modular and Reusable: Code that you write for certain purposes can be used and assembled in different ways. You can write code to create resources on a public cloud and it can be shared with other teams who can also use it in their account on the same (or different) cloud><br>
|
||||
- Improved testing: Concepts like CI can be easily applied on IaC based projects and code snippets. This allow you to test and verify operations beforehand
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Why one would prefer using Terraform and not other technologies? (e.g. Ansible, Puppet, CloudFormation)</summary><br><b>
|
||||
<summary>What are some of Terraform features?</summary><br><b>
|
||||
|
||||
A common *wrong* answer is to say that Ansible and Puppet are configuration management tools
|
||||
and Terraform is a provisioning tool. While technically true, it doesn't mean Ansible and Puppet can't
|
||||
be used for provisioning infrastructure. Also, it doesn't explain why Terraform should be used over
|
||||
CloudFormation if at all.
|
||||
|
||||
The benefits of Terraform over the other tools:
|
||||
|
||||
* It follows the immutable infrastructure approach which has benefits like avoiding a configuration drift over time
|
||||
* Ansible and Puppet are more procedural (you mention what to execute in each step) and Terraform is declarative since you describe the overall desired state and not per resource or task. You can give the example of going from 1 to 2 servers in each tool. In Terraform you specify 2, in Ansible and puppet you have to only provision 1 additional server so you need to explicitly make sure you provision only another one server.
|
||||
- Declarative: Terraform uses the declarative approach (rather than the procedural one) in order to define end-status of the resources
|
||||
- No agents: as opposed to other technologies (e.g. Puppet) where you use a model of agent and server, with Terraform you use the different APIs (of clouds, services, etc.) to perform the operations
|
||||
- Community: Terraform has strong community who constantly publishes modules and fixes when needed. This ensures there is good modules maintenance and users can get support quite quickly at any point
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>How do you structure your Terraform projects?</summary><br><b>
|
||||
<summary>In what language infrastructure in Terraform is defined?</summary><br><b>
|
||||
|
||||
terraform_directory
|
||||
providers.tf -> List providers (source, version, etc.)
|
||||
variables.tf -> any variable used in other files such as main.tf
|
||||
main.tf -> Lists the resources
|
||||
HCL (Hashiciorp Configuration Language). A declarative language for defining infrastructure.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>True or False? Terraform follows the mutable infrastructure paradigm</summary><br><b>
|
||||
<summary>What's a typical Terraform workflow?</summary><br><b>
|
||||
|
||||
False. Terraform follows immutable infrastructure paradigm.
|
||||
1. Write Terraform definitions: `.tf` files written in HCL that described the desired infrastructure state
|
||||
2. Review: With command such as `terraform plan` you can get a glance at what Terraform will perform with the written definitions
|
||||
3. Apply definitions: With the command `terraform apply` Terraform will apply the given definitions, by adding, modifying or removing the resources
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>True or False? Terraform uses declarative style to describe the expected end state</summary><br><b>
|
||||
True
|
||||
<summary>What are some use cases for using Terraform?</summary><br><b>
|
||||
|
||||
- Multi-cloud environment: You manage infrastructure on different clouds, but looking for a consistent way to do it across the clouds
|
||||
- Consistent environments: You manage environments such as test, production, staging, ... and looking for a way to have them consistent so any modification in one of them, applies to other environments as well
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is HCL?</summary><br><b>
|
||||
HCL stands for Hashicorp Configuration Language. It is the language Hashicorp made to use as the configuration language for a number of its tools, including terraform.
|
||||
<summary>What's the difference between Terraform and technologies such as Ansible, Puppet, Chef, etc.</summary><br><b>
|
||||
|
||||
Terraform is considered to be an IaC technology. It's used for provisioning resources, for managing infrastructure on different platforms.
|
||||
|
||||
Ansible, Puppet and Chef are Configuration Management technologies. They are used once there is an instance running and you would like to apply some configuration on it like installing an application, applying security policy, etc.
|
||||
|
||||
To be clear, CM tools can be used to provision resources so in the end goal of having infrastructure, both Terraform and something like Ansible, can achieve the same result. The difference is in the how. Ansible doesn't saves the state of resources, it doesn't know how many instances there are in your environment as opposed to Terraform. At the same time while Terraform can perform configuration management tasks, it has less modules support for that specific goal and it doesn't track the task execution state as Ansible. The differences are there and it's most of the time recommended to mix the technologies, so Terraform used for managing infrastructure and CM technologies used for configuration on top of that infrastructure.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain what is "Terraform configuration"</summary><br><b>
|
||||
|
||||
A configuration is a root module along with a tree of child modules that are called as dependencies from the root module.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain what the following commands do:
|
||||
|
||||
* <code>terraform init</code>
|
||||
* <code>terraform plan</code>
|
||||
* <code>terraform validate</code>
|
||||
* <code>terraform apply</code>
|
||||
</summary><br><b>
|
||||
|
||||
<code>terraform init</code> scans your code to figure which providers are you using and download them.
|
||||
<code>terraform plan</code> will let you see what terraform is about to do before actually doing it.
|
||||
<code>terraform validate</code> checks if configuration is syntactically valid and internally consistent within a directory.
|
||||
<code>terraform apply</code> will provision the resources specified in the .tf files.
|
||||
</b></details>
|
||||
|
||||
#### Terraform - Resources
|
||||
|
||||
<details>
|
||||
<summary>What is a "resource"?</summary><br><b>
|
||||
|
||||
HashiCorp: "Terraform uses resource blocks to manage infrastructure, such as virtual networks, compute instances, or higher-level components such as DNS records. Resource blocks represent one or more infrastructure objects in your Terraform configuration."
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain each part of the following line: `resource "aws_instance" "web_server" {...}`</summary><br><b>
|
||||
|
||||
- resource: keyword for defining a resource
|
||||
- "aws_instance": the type of the resource
|
||||
- "web_server": the name of the resource
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is the ID of the following resource: `resource "aws_instance" "web_server" {...}`</summary><br><b>
|
||||
|
||||
`aws_instance.web_server`
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>True or False? Resource ID must be unique within a workspace</summary><br><b>
|
||||
|
||||
True
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain each of the following in regards to resources
|
||||
|
||||
* Arguments
|
||||
* Attributes
|
||||
* Meta-arguments</summary><br><b>
|
||||
|
||||
- Arguments: resource specific configurations
|
||||
- Attributes: values exposed by the resource in a form of `resource_type.resource_name.attribute_name`. They are set by the provider or API usually.
|
||||
- Meta-arguments: Functions of Terraform to change resource's behavior
|
||||
</b></details>
|
||||
|
||||
#### Terraform - Providers
|
||||
### Providers
|
||||
|
||||
<details>
|
||||
<summary>Explain what is a "provider"</summary><br><b>
|
||||
@@ -114,13 +92,177 @@ True
|
||||
[terraform.io](https://www.terraform.io/docs/language/providers/index.html): "Terraform relies on plugins called "providers" to interact with cloud providers, SaaS providers, and other APIs...Each provider adds a set of resource types and/or data sources that Terraform can manage. Every resource type is implemented by a provider; without providers, Terraform can't manage any kind of infrastructure."
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Where can you find publicly available providers?</summary><br><b>
|
||||
|
||||
In the [Terraform Registry](https://registry.terraform.io/browse/providers)
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is the name of the provider in this case: `resource "libvirt_domain" "instance" {...}`</summary><br><b>
|
||||
|
||||
libvirt
|
||||
</b></details>
|
||||
|
||||
#### Terraform - Variables
|
||||
<details>
|
||||
<summary>Write a configuration of a Terraform provider (any type you would like)</summary><br><b>
|
||||
|
||||
AWS is one of the most popular providers in Terraform. Here is an example of how to configure it to use one specific region and specifying a specific version of the provider
|
||||
|
||||
```
|
||||
terraform {
|
||||
required_providers {
|
||||
aws = {
|
||||
source = "hashicorp/aws"
|
||||
version = "~> 3.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Configure the AWS Provider
|
||||
provider "aws" {
|
||||
region = "us-west-2"
|
||||
}
|
||||
```
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is the Terraform Registry?</summary><br><b>
|
||||
|
||||
The Terraform Registry provides a centralized location for official and community-managed providers and modules.
|
||||
</b></details>
|
||||
|
||||
### Provisioners
|
||||
|
||||
<details>
|
||||
<summary>What are "Provisioners"? What they are used for?</summary><br><b>
|
||||
|
||||
Provisioners can be described as plugin to use with Terraform, usually focusing on the aspect of service configuration and make it operational.
|
||||
|
||||
Few example of provisioners:
|
||||
|
||||
* Run configuration management on a provisioned instance using technology like Ansible, Chef or Puppet.
|
||||
* Copying files
|
||||
* Executing remote scripts
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Why is it often recommended to use provisioners as last resort?</summary><br><b>
|
||||
|
||||
Since a provisioner can run a variety of actions, it's not always feasible to plan and understand what will happen when running a certain provisioner. For this reason, it's usually recommended to use Terraform built-in option, whenever's possible.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is <code>local-exec</code> and <code>remote-exec</code> in the context of provisioners?</summary><br><b>
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is a "tainted resource"?</summary><br><b>
|
||||
|
||||
It's a resource which was successfully created but failed during provisioning. Terraform will fail and mark this resource as "tainted".
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What <code>terraform taint</code> does?</summary><br><b>
|
||||
<code>terraform taint resource.id</code> manually marks the resource as tainted in the state file. So when you run <code>terraform apply</code> the next time, the resource will be destroyed and recreated.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is a data source? In what scenarios for example would need to use it?</summary><br><b>
|
||||
Data sources lookup or compute values that can be used elsewhere in terraform configuration.
|
||||
|
||||
There are quite a few cases you might need to use them:
|
||||
* you want to reference resources not managed through terraform
|
||||
* you want to reference resources managed by a different terraform module
|
||||
* you want to cleanly compute a value with typechecking, such as with <code>aws_iam_policy_document</code>
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What are output variables and what <code>terraform output</code> does?</summary><br><b>
|
||||
Output variables are named values that are sourced from the attributes of a module. They are stored in terraform state, and can be used by other modules through <code>remote_state</code>
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain <code>remote-exec</code> and <code>local-exec</code></summary><br><b>
|
||||
</b></details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Explain "Remote State". When would you use it and how?</summary><br><b>
|
||||
Terraform generates a `terraform.tfstate` json file that describes components/service provisioned on the specified provider. Remote
|
||||
State stores this file in a remote storage media to enable collaboration amongst team.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain "State Locking"</summary><br><b>
|
||||
State locking is a mechanism that blocks an operations against a specific state file from multiple callers so as to avoid conflicting operations from different team members. Once the first caller's operation's lock is released the other team member may go ahead to
|
||||
carryout his own operation. Nevertheless Terraform will first check the state file to see if the desired resource already exist and
|
||||
if not it goes ahead to create it.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Aside from <code>.tfvars</code> files or CLI arguments, how can you inject dependencies from other modules?</summary><br><b>
|
||||
The built-in terraform way would be to use <code>remote-state</code> to lookup the outputs from other modules.
|
||||
It is also common in the community to use a tool called <code>terragrunt</code> to explicitly inject variables between modules.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>How do you import existing resource using Terraform import?</summary><br><b>
|
||||
|
||||
1. Identify which resource you want to import.
|
||||
2. Write terraform code matching configuration of that resource.
|
||||
3. Run terraform command <code>terraform import RESOURCE ID</code><br>
|
||||
|
||||
eg. Let's say you want to import an aws instance. Then you'll perform following:
|
||||
1. Identify that aws instance in console
|
||||
2. Refer to it's configuration and write Terraform code which will look something like:
|
||||
```
|
||||
resource "aws_instance" "tf_aws_instance" {
|
||||
ami = data.aws_ami.ubuntu.id
|
||||
instance_type = "t3.micro"
|
||||
|
||||
tags = {
|
||||
Name = "import-me"
|
||||
}
|
||||
}
|
||||
```
|
||||
3. Run terraform command <code>terraform import aws_instance.tf_aws_instance i-12345678</code>
|
||||
</b></details>
|
||||
|
||||
### Modules
|
||||
|
||||
<details>
|
||||
<summary>Explain Modules</summary>
|
||||
|
||||
[Terraform.io](https://www.terraform.io/language/modules/develop): "A module is a container for multiple resources that are used together. Modules can be used to create lightweight abstractions, so that you can describe your infrastructure in terms of its architecture, rather than directly in terms of physical objects."
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>How do you test a terraform module?</summary><br><b>
|
||||
|
||||
Many examples are acceptable, but the most common answer would likely to be using the tool <code>terratest</code>, and to test that a module can be initialized, can create resources, and can destroy those resources cleanly.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Where can you obtain Terraform modules?<summary><br><b>
|
||||
|
||||
Terraform modules can be found at the [Terrafrom registry](https://registry.terraform.io/browse/modules)
|
||||
</b></details>
|
||||
|
||||
### Variables
|
||||
|
||||
<details>
|
||||
<summary>What types of variables are supported in Terraform?</summary><br><b>
|
||||
|
||||
string
|
||||
number
|
||||
bool
|
||||
list(<TYPE>)
|
||||
set(<TYPE>)
|
||||
map(<TYPE>)
|
||||
object({<ATTR_NAME> = <TYPE>, ... })
|
||||
tuple([<TYPE>, ...])
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What are Input Variables in Terraform? Why one should use them?</summary><br><b>
|
||||
@@ -230,7 +372,13 @@ z = "luigi"
|
||||
```
|
||||
</b></details>
|
||||
|
||||
#### Terraform - State
|
||||
### State
|
||||
|
||||
<details>
|
||||
<summary>What's Terraform State?</summary><br><b>
|
||||
|
||||
[Terraform.io](https://www.terraform.io/language/state): "Terraform must store state about your managed infrastructure and configuration. This state is used by Terraform to map real world resources to your configuration, keep track of metadata, and to improve performance for large infrastructures."
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What <code>terraform.tfstate</code> file is used for?</summary><br><b>
|
||||
@@ -267,6 +415,12 @@ As such, tfstate shouldn't be stored in git repositories. secured storage such a
|
||||
- The state is stored by default in a local file named terraform.tfstate.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is Terraform import?</summary><br><b>
|
||||
|
||||
Terraform import is used to import existing infrastructure. It allows you to bring resources created by some other means (eg. manually launched cloud resources) and bring it under Terraform management.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Can we store tfstate file at remote location? If yes, then in which condition you will do this?</summary><br><b>
|
||||
|
||||
@@ -309,129 +463,23 @@ You use it this way: <code>variable “my_var” {}</code>
|
||||
[Provisioners](https://www.terraform.io/docs/language/resources/provisioners)
|
||||
</b></details>
|
||||
|
||||
#### Terraform - Provisioners
|
||||
### Import
|
||||
|
||||
<details>
|
||||
<summary>What are "Provisioners"? What they are used for?</summary><br><b>
|
||||
<summary>Explain Terraform's import functionality</summary><br><b>
|
||||
|
||||
Provisioners used to execute actions on local or remote machine. It's extremely useful in case you provisioned an instance and you want to make a couple of changes in the machine you've created without manually ssh into it after Terraform finished to run and manually run them.
|
||||
`terraform import` is a CLI command used for importing an existing infrastructure into Terraform's state.
|
||||
|
||||
It's does NOT create the definitions/configuration for creating such infrastructure
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is <code>local-exec</code> and <code>remote-exec</code> in the context of provisioners?</summary><br><b>
|
||||
<summary>State two use cases where you would use <code>terraform import</code></summary><br><b>
|
||||
|
||||
1. You have existing resources in the cloud and they are not managed by Terraform (as in not included in the state)
|
||||
2. You lost your tfstate file and need to rebuild it
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is a "tainted resource"?</summary><br><b>
|
||||
|
||||
It's a resource which was successfully created but failed during provisioning. Terraform will fail and mark this resource as "tainted".
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What <code>terraform taint</code> does?</summary><br><b>
|
||||
<code>terraform taint resource.id</code> manually marks the resource as tainted in the state file. So when you run <code>terraform apply</code> the next time, the resource will be destroyed and recreated.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What types of variables are supported in Terraform?</summary><br><b>
|
||||
|
||||
string
|
||||
number
|
||||
bool
|
||||
list(<TYPE>)
|
||||
set(<TYPE>)
|
||||
map(<TYPE>)
|
||||
object({<ATTR_NAME> = <TYPE>, ... })
|
||||
tuple([<TYPE>, ...])
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is a data source? In what scenarios for example would need to use it?</summary><br><b>
|
||||
Data sources lookup or compute values that can be used elsewhere in terraform configuration.
|
||||
|
||||
There are quite a few cases you might need to use them:
|
||||
* you want to reference resources not managed through terraform
|
||||
* you want to reference resources managed by a different terraform module
|
||||
* you want to cleanly compute a value with typechecking, such as with <code>aws_iam_policy_document</code>
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What are output variables and what <code>terraform output</code> does?</summary><br><b>
|
||||
Output variables are named values that are sourced from the attributes of a module. They are stored in terraform state, and can be used by other modules through <code>remote_state</code>
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain Modules</summary>
|
||||
|
||||
A Terraform module is a set of Terraform configuration files in a single directory. Modules are small, reusable Terraform configurations that let you manage a group of related resources as if they were a single resource. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module. So in this sense, every Terraform configuration is part of a module.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is the Terraform Registry?</summary><br><b>
|
||||
|
||||
The Terraform Registry provides a centralized location for official and community-managed providers and modules.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain <code>remote-exec</code> and <code>local-exec</code></summary><br><b>
|
||||
</b></details>
|
||||
|
||||
|
||||
<details>
|
||||
<summary>Explain "Remote State". When would you use it and how?</summary><br><b>
|
||||
Terraform generates a `terraform.tfstate` json file that describes components/service provisioned on the specified provider. Remote
|
||||
State stores this file in a remote storage media to enable collaboration amongst team.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Explain "State Locking"</summary><br><b>
|
||||
State locking is a mechanism that blocks an operations against a specific state file from multiple callers so as to avoid conflicting operations from different team members. Once the first caller's operation's lock is released the other team member may go ahead to
|
||||
carryout his own operation. Nevertheless Terraform will first check the state file to see if the desired resource already exist and
|
||||
if not it goes ahead to create it.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is the "Random" provider? What is it used for</summary><br><b>
|
||||
The random provider aids in generating numeric or alphabetic characters to use as a prefix or suffix for a desired named identifier.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>How do you test a terraform module?</summary><br><b>
|
||||
Many examples are acceptable, but the most common answer would likely to be using the tool <code>terratest</code>, and to test that a module can be initialized, can create resources, and can destroy those resources cleanly.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>Aside from <code>.tfvars</code> files or CLI arguments, how can you inject dependencies from other modules?</summary><br><b>
|
||||
The built-in terraform way would be to use <code>remote-state</code> to lookup the outputs from other modules.
|
||||
It is also common in the community to use a tool called <code>terragrunt</code> to explicitly inject variables between modules.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>What is Terraform import?</summary><br><b>
|
||||
|
||||
Terraform import is used to import existing infrastructure. It allows you to bring resources created by some other means (eg. manually launched cloud resources) and bring it under Terraform management.
|
||||
</b></details>
|
||||
|
||||
<details>
|
||||
<summary>How do you import existing resource using Terraform import?</summary><br><b>
|
||||
|
||||
1. Identify which resource you want to import.
|
||||
2. Write terraform code matching configuration of that resource.
|
||||
3. Run terraform command <code>terraform import RESOURCE ID</code><br>
|
||||
|
||||
eg. Let's say you want to import an aws instance. Then you'll perform following:
|
||||
1. Identify that aws instance in console
|
||||
2. Refer to it's configuration and write Terraform code which will look something like:
|
||||
```
|
||||
resource "aws_instance" "tf_aws_instance" {
|
||||
ami = data.aws_ami.ubuntu.id
|
||||
instance_type = "t3.micro"
|
||||
|
||||
tags = {
|
||||
Name = "import-me"
|
||||
}
|
||||
}
|
||||
```
|
||||
3. Run terraform command <code>terraform import aws_instance.tf_aws_instance i-12345678</code>
|
||||
</b></details>
|
||||
### Real Life Scenarios
|
||||
|
||||
TODO
|
||||
20
exercises/terraform/s3_bucket_rename/exercise.md
Normal file
20
exercises/terraform/s3_bucket_rename/exercise.md
Normal file
@@ -0,0 +1,20 @@
|
||||
# Rename S3 Bucket
|
||||
|
||||
## Requirements
|
||||
|
||||
* An existing S3 bucket tracked by Terraform.
|
||||
If you don't have it, you can use the following block and run `terraform apply`:
|
||||
|
||||
```terraform
|
||||
resource "aws_s3_bucket" "some_bucket" {
|
||||
bucket = "some-old-bucket"
|
||||
}
|
||||
```
|
||||
|
||||
## Objectives
|
||||
|
||||
1. Rename an existing S3 bucket and make sure it's still tracked by Terraform
|
||||
|
||||
## Solution
|
||||
|
||||
Click [here to view the solution](solution.md)
|
||||
49
exercises/terraform/s3_bucket_rename/solution.md
Normal file
49
exercises/terraform/s3_bucket_rename/solution.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Rename S3 Bucket
|
||||
|
||||
## Requirements
|
||||
|
||||
* An existing S3 bucket tracked by Terraform.
|
||||
If you don't have it, you can use the following block and run `terraform apply`:
|
||||
|
||||
```terraform
|
||||
resource "aws_s3_bucket" "some_bucket" {
|
||||
bucket = "some-old-bucket"
|
||||
}
|
||||
```
|
||||
|
||||
## Objectives
|
||||
|
||||
1. Rename an existing S3 bucket and make sure it's still tracked by Terraform
|
||||
|
||||
## Solution
|
||||
|
||||
```sh
|
||||
# A bucket name is immutable in AWS so we'll have to create a new bucket
|
||||
aws s3 mb s3://some-new-bucket-123
|
||||
|
||||
# Sync old bucket to new bucket
|
||||
aws s3 sync s3://some-old-bucket s3://some-new-bucket-123
|
||||
|
||||
# Remove the old bucket from Terraform's state
|
||||
terraform state rm aws_s3_bucket.some_bucket
|
||||
|
||||
# Import new bucket to Terraform's state
|
||||
terraform import aws_s3_bucket.some_bucket some-new-bucket-123
|
||||
|
||||
: '
|
||||
aws_s3_bucket.some_bucket: Refreshing state... [id=some-new-bucket-123]
|
||||
|
||||
Import successful!
|
||||
The resources that were imported are shown above. These resources are now in
|
||||
your Terraform state and will henceforth be managed by Terraform.
|
||||
'
|
||||
|
||||
# Modify the Terraform definition to include the new name
|
||||
# resource "aws_s3_bucket" "some_bucket" {
|
||||
# bucket = "some-new-bucket-123"
|
||||
# }
|
||||
|
||||
# Remove old bucket
|
||||
aws s3 rm s3://some-old-bucket --recursive
|
||||
aws s3 rb s3://some-old-bucket
|
||||
```
|
||||
22
exercises/terraform/terraform_local_provider/exercise.md
Normal file
22
exercises/terraform/terraform_local_provider/exercise.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# Local Provider
|
||||
|
||||
## Objectives
|
||||
|
||||
Learn how to use and run Terraform basic commands
|
||||
|
||||
1. Create a directory called "my_first_run"
|
||||
2. Inside the directory create a file called "main.tf" with the following content
|
||||
|
||||
```terraform
|
||||
resource "local_file" "mario_local_file" {
|
||||
content = "It's a me, Mario!"
|
||||
filename = "/tmp/who_is_it.txt"
|
||||
}
|
||||
```
|
||||
3. Run `terraform init`. What did it do?
|
||||
4. Run `terraform plan`. What Terraform is going to perform?
|
||||
5. Finally, run 'terraform apply' and verify the file was created
|
||||
|
||||
## Solution
|
||||
|
||||
Click [here to view the solution](solution.md)
|
||||
63
exercises/terraform/terraform_local_provider/solution.md
Normal file
63
exercises/terraform/terraform_local_provider/solution.md
Normal file
@@ -0,0 +1,63 @@
|
||||
# Local Provider
|
||||
|
||||
## Objectives
|
||||
|
||||
Learn how to use and run Terraform basic commands
|
||||
|
||||
1. Create a directory called "my_first_run"
|
||||
2. Inside the directory create a file called "main.tf" with the following content
|
||||
|
||||
```terraform
|
||||
resource "local_file" "mario_local_file" {
|
||||
content = "It's a me, Mario!"
|
||||
filename = "/tmp/who_is_it.txt"
|
||||
}
|
||||
```
|
||||
3. Run `terraform init`. What did it do?
|
||||
4. Run `terraform plan`. What Terraform is going to perform?
|
||||
5. Finally, run 'terraform apply' and verify the file was created
|
||||
|
||||
## Solution
|
||||
|
||||
```sh
|
||||
# Create a directory
|
||||
mkdir my_first_run && cd my_first_run
|
||||
|
||||
# Create the file 'main.tf'
|
||||
cat << EOT >> main.tf
|
||||
resource "local_file" "mario_local_file" {
|
||||
content = "It's a me, Mario!"
|
||||
filename = "/tmp/who_is_it.txt"
|
||||
}
|
||||
EOT
|
||||
|
||||
# Run 'terraform init'
|
||||
terraform init
|
||||
# Running 'ls -la' you'll it created '.terraform' and '.terraform.lock.hcl'
|
||||
# In addition, it initialized (downloaded and installed) the relevant provider plugins. In this case, the "hashicorp/local"
|
||||
|
||||
# Run 'terraform plan'
|
||||
terraform plan
|
||||
# It shows what Terraform is going to perform once you'll run 'terraform apply'
|
||||
|
||||
<< terraform_plan_output
|
||||
Terraform will perform the following actions:
|
||||
|
||||
# local_file.mario_local_file will be created
|
||||
+ resource "local_file" "mario_local_file" {
|
||||
+ content = "It's a me, Mario!"
|
||||
+ directory_permission = "0777"
|
||||
+ file_permission = "0777"
|
||||
+ filename = "/tmp/who_is_it.txt"
|
||||
+ id = (known after apply)
|
||||
}
|
||||
|
||||
Plan: 1 to add, 0 to change, 0 to destroy.
|
||||
terraform_plan_output
|
||||
|
||||
# Apply main.tf (it's better to run without -auto-approve if you are new to Terraform)
|
||||
terraform apply -auto-approve
|
||||
|
||||
ls /tmp/who_is_it.txt
|
||||
# /tmp/who_is_it.txt
|
||||
```
|
||||
Reference in New Issue
Block a user