Newsletter zu Aktionen
Trage dich ein um keine Aktionen von uns zu verpassen.
Wir senden 1-2 E-Mails pro Quartal.
In the previous lab (See), we have learn how to deploy solely on Azure using ARM and later Bicep, which are powerful and stable tools. But they have one crucial disadvantage. ARM and Bicep only works for Azure. When dealing with large solution you may want to leverage multiple providers to get the most out of the various services. This also applies even if your company decide to stick solely to the Microsoft universe. Why is that? Well, you probably wants to host your code somewhere? Just to give an example. Maybe Azure DevOps, GitHub, GitLab or similiar. Please mind that Azure DevOps is neither supported by ARM nor by Bicep. So let’s take our case to the next level.
In this lab, we will create a new Azure DevOps project and a storage account using Terraform. Please mind! For simplification, Azure DevOps and Azure were chosen as 2 providers but we could also deploy some AWS, Google Cloud or other resources.
Our Storage Account Explorer from the last lab was quite a big hit, we got at least 5 users right from the start and the number is likely to grow. In addition, management was quite impressed by Infrastructure as Code. Your team and you are now entrusted with the mission to bring Infrastructure as Code to every new feature projects. Even the project setup is meant to be done by Infrastructure as Code. The idea is: if a new Proof-of-Concept project got approved, the respective team just need to run „the“ script and a new DevOps project is created along with a few resources on Azure. This should ease and speed up the deployment process for new projects significantly.
Bash
if it is not already the case.mkdir lab-tf cd lab-tf touch variables.tf touch providers.tf touch main-azurerm.tf touch main-azuredevops.tf touch output.tf code .
The terraform.exe
itself is just a runner and interpreter of the written configuration script. The features and support for Azure and other services is written in the providers. Even for generating random numbers and string, you would need install respective providers. e.g. random
Let’s add Azure Cloud support for our project by adding azurerm
:
providers.tf
(you may find the complete solution for step 2 – 4 below but try to find the solution by yourself for a better learning experience).terraform
block at the beginning of the file.terraform
block, add azurerm
to the list of required_providers (see docs)provider
block for at the end azurerm
The providers.tf
file should look like this at the end:
# Configuring terraform including the list of required_providers terraform { required_providers { azurerm = { source = "hashicorp/azurerm" # optionally you could specify a version # version = "..." } } } # Configure the Microsoft Azure Provider "azurerm" provider "azurerm" { features {} }
We can now ask terraform to download and add the provider azurerm
to the project:
terraform init
at the root of your project folder <your-path>/lab-tf/
.azurerm
provider plugin. It ensures that the version of the provider matches the constraints specified in the configuration if specified..terraform/hashicorp/azurerm
. In which it stores the downloaded providermain-azurerm.tf
. (You can find the complete solution below)azurerm_resource_group
resource block (see docs) and a azurerm_storage_account
resource block (see docs). uniqueString
function but a random_string
resource block (see docs)terraform init
again as your code now have additional dependencies on a new provider – namely random
.azurerm_
and random_
.terraform plan -out .tfplan
to create an execution plan.terraform apply .tfplan
to apply the changes in the plan.static_website
service (see Docs).resource "azurerm_resource_group" "draphony" { name = "azlab-iac-tf" location = "westeurope" } resource "random_string" "draphony" { keepers = { rgid = azurerm_resource_group.draphony.id } length = 13 special = false upper = false } resource "azurerm_storage_account" "draphony" { name = "draphony${random_string.draphony.id}" location = azurerm_resource_group.draphony.location account_replication_type = "LRS" account_tier = "Standard" resource_group_name = azurerm_resource_group.draphony.name }
Bonus: Modify the output.tf
so that it outputs the keys from the storage account
sensitive
in the newer version. This will just affect the output in the CLI but not the capability of other modules and services (such as Azure DevOps) to access the output.Now that our storage account is up and running on Azure, we need to add Azure DevOps to our project.
Please mind that you need an Azure DevOps account for this part. You can create a free account here. Terraform will use a Personal Access Token to gain access, therefore you can use any email / account to signup.
providers.tf
in your project folder.required_providers
and add and new provider block for azuredevops
as shown below:terraform { required_providers { azurerm = { source = "hashicorp/azurerm" } azuredevops = { source = "microsoft/azuredevops" } } } provider "azurerm" { features {} } provider "azuredevops" { personal_access_token = "TO_BE_REPLACED" org_service_url = "TO_BE_REPLACED" }
PAT
with full scope
and the org_service_url
and replace it in the providers.tf
main-azuredevops.tf
in the project so that it deploys:terraform plan -out .tfplan
to create an execution plan.terraform apply .tfplan
to apply the changes.resource "azuredevops_project" "draphony" { name = "Awesome Project" description = "You did it man!" visibility = "private" version_control = "Git" work_item_template = "Scrum" } resource "azuredevops_git_repository" "draphony" { project_id = azuredevops_project.draphony.id name = "webapp" initialization { init_type = "Uninitialized" } } resource "azuredevops_repository_policy_author_email_pattern" "draphony" { project_id = azuredevops_project.draphony.id enabled = true blocking = true author_email_patterns = ["*@draphony.com", "*@draphony.de"] }
for_each
Let’s add some configurability to our configuration script by allowing the amount of repository to be configurable.
variables.tf
file (the complete file can be found at the end).draphony_git_repos
, which ["webapp", "api"]
. type
set to set(string)
main-azuredevops.tf
(the complete file can be found at the end) Modify the azuredevops_git_repository
resource block:var.draphony_git_repos
property
name
to the respective value of the iteration.terraform plan -out .tfplan
to create an execution plan.webapp
repository and recreate it along with the new repository api
. Because the reference variable azuredevops_git_repository.draphony
is now an dictionary azuredevops_git_repository.draphony["webapp"]
and azuredevops_git_repository.draphony["api"]
.terraform state mv
to reflect the latest changes. (see docs)terraform plan -out .tfplan -var "draphony_git_repos=[\"webapp\", \"api\", \"ui-tests\"
]"
to create an execution plan.webapp
repository and recreate it along with the new repositories api
and ui-tests
unless you did the bonus..tfvars
to set the value (see docs)terraform apply .tfplan
to apply the changes.# variables.tf variable "draphony_git_repos" { type = set(string) default = ["webapp", "api"] }
# main-azuredevops.tf resource "azuredevops_project" "draphony" { name = "Awesome Project" description = "You did it man!" visibility = "private" version_control = "Git" work_item_template = "Scrum" } resource "azuredevops_git_repository" "draphony" { for_each = var.draphony_git_repos project_id = azuredevops_project.draphony.id name = each.key initialization { init_type = "Uninitialized" } } resource "azuredevops_repository_policy_author_email_pattern" "draphony" { project_id = azuredevops_project.draphony.id enabled = true blocking = true author_email_patterns = ["*@draphony.com", "*@draphony.de"] }
terraform destroy
at the root of your project folder `<your-path>/lab-tf/`
to teardown everything.As you can see, Terraform is quite easy to learn yet quite powerful. It is quite a popular tool that you find in many companies and projects, which do Infrastructure as Code. Some even use „terraforming“ instead of Infrastructure as Code giving the expression that it is almost defacto standard.
Nevertheless, there are also other interesting alternatives such as
Checkout other labs and courses from Draphony to learn more about Terraform:
If you enjoyed the lab or have any questions / feedback, please leave us a comment.
Trage dich ein um keine Aktionen von uns zu verpassen.
Wir senden 1-2 E-Mails pro Quartal.