Posted on Leave a comment

Azure DevOps Terraform Provider

If you work everywhere as a code you will probably need to check Azure DevOps terraform provider. It is created and maintained from Microsoft and you can use it in order to have your DevOps tool as a code.

https://registry.terraform.io/providers/microsoft/azuredevops/latest/docs

In order to getting started you will need to create a PAT token and give it the access based on the actions that you need to do.

When the token is ready you will need to set two environmental variables on the machine that you work. The first one is AZDO_PERSONAL_ACCESS_TOKEN which should be your token. The second one will be your org URL AZDO_ORG_SERVICE_URL

export AZDO_PERSONAL_ACCESS_TOKEN= TOKEN
export AZDO_ORG_SERVICE_URL= https://dev.azure.com/geralexgr

Finally you are ready to deploy your IAC Azure DevOps configurations.

Lets see the below example.

# Make sure to set the following environment variables:
#   AZDO_PERSONAL_ACCESS_TOKEN
#   AZDO_ORG_SERVICE_URL
terraform {
  required_providers {
    azuredevops = {
      source = "microsoft/azuredevops"
      version = ">=0.1.0"
    }
  }
}

resource "azuredevops_project" "project" {
  name = "My Awesome Project"
  description  = "All of my awesomee things"
}

resource "azuredevops_git_repository" "repository" {
  project_id = azuredevops_project.project.id
  name       = "My Awesome Repo"
  initialization {
    init_type = "Clean"
  }
}

resource "azuredevops_build_definition" "build_definition" {
  project_id = azuredevops_project.project.id
  name       = "My Awesome Build Pipeline"
  path       = "\\"

  repository {
    repo_type   = "TfsGit"
    repo_id     = azuredevops_git_repository.repository.id
    branch_name = azuredevops_git_repository.repository.default_branch
    yml_path    = "azure-pipelines.yml"
  }
}

When above code runs it will create a new project with the name My Awesome Project. Inside the project a new git repo will be initialized and a new pipeline will be created inside this repository.

You can find the usage example below.

https://github.com/microsoft/terraform-provider-azuredevops

Youtube video:

Posted on Leave a comment

Deploy azurerm function app with zip_deploy_file terraform

When you need to deploy code in a function app using terraform you can use the zip_deploy_file parameter. Using this you can specify a zip file that will be created from your committed code and by doing so you can dynamically deploy code using terraform.

The first thing that you will need to do is to create a folder with the code that you want to commit in the function_app. In my example I have the terraform files inside the aws and azure folders and in the same directory I have a folder called resources where the code is located. This code need to be deployed in the serverless function app.

Create a data archive_file with terraform and specify where your code is located. You should correctly point where the files are stored.

data "archive_file" "python_function_package" {  
  type = "zip"  
  source_file = "../resources/function.py" 
  output_path = "function.zip"
}

Then you should use the above data archive and use it along with zip_deploy_file.

resource "azurerm_linux_function_app" "functionapp" {
  name                = var.serviceplan_name
  resource_group_name = azurerm_resource_group.rg.name
  location            = azurerm_resource_group.rg.location

  storage_account_name       = azurerm_storage_account.sg.name
  storage_account_access_key = azurerm_storage_account.sg.primary_access_key
  service_plan_id            = azurerm_service_plan.serviceplan.id
  
  zip_deploy_file = data.archive_file.python_function_package.output_path
  app_settings              = "${var.app_settings}"

  site_config {
    application_stack {
        python_version = "3.10"
    }
  }

}

When you deploy your terraform code the function app will correctly upload the code in your infra component and you can check that by navigating inside the code on azure portal.

azurerm_linux_function_app | Resources | hashicorp/azurerm | Terraform | Terraform Registry

Posted on Leave a comment

Function Apps are not supported in Free and Shared plans. Please choose a different plan

When you use terraform and functions apps in azure you may end up with the below issue.

Creating Linux Function App: (Site Name "multicloud-serviceplan" / Resource
│ Group "multicloudrg"): web.AppsClient#CreateOrUpdate: Failure sending
│ request: StatusCode=400 -- Original Error: Code="BadRequest" Message="You
│ tried creating a function app in the 'Free' SKU. Function Apps are not
│ supported in Free and Shared plans. Please choose a different plan."
│ Details=[{"Message":"You tried creating a function app in the 'Free' SKU.
│ Function Apps are not supported in Free and Shared plans. Please choose a
│ different
│ plan.

The issue indicates that a Function app cannot be created using the Free tier F1 of the service plan.

In order to fix the issue you must select one of the additional plans Consumption, Premium or Dedicated.

In Consumption plan hosting, each function app typically runs in its own plan. In the Azure portal or in code, you may also see the Consumption plan referred to as Dynamic or Y1.

https://learn.microsoft.com/en-us/azure/azure-functions/consumption-plan

The details of each plans are described below.

https://learn.microsoft.com/en-us/azure/azure-functions/functions-scale?WT.mc_id=Portal-WebsitesExtension

The terraform issue will be resolved when you select Y1 instead of F1 which is the free tier.

Posted on Leave a comment

Create and use terraform modules

Terraform modules are useful in various scenarios when working with Infrastructure as Code (IaC) using Terraform. Modules provide a way to encapsulate and reuse infrastructure configurations, making it easier to manage and scale your infrastructure code.

Every Terraform configuration has at least one module, known as its root module, which consists of the resources defined in the .tf files in the main working directory.

A module can call other modules, which lets you include the child module’s resources into the configuration in a concise way. Modules can also be called multiple times, either within the same configuration or in separate configurations, allowing resource configurations to be packaged and re-used.

Lets take a look how we can create and use terraform modules. The first thing that you will need to do is to structure your code somehow. A most common way to create a structure would be to create folders and name them after your module. For example if you have to deploy a cloud solution with multiple components you could create a module for each component. In my structure you can find two folders with the name module1 and module2. The module2 will call module1 to reuse its code inside the terraform configuration.

The module1 folder contains the files that are shown.

provider.tf file will be used to fetch all the necessary providers. In my example I use the random provider to generate a random string with terraform.

terraform {
  required_providers {
    random = {
      source  = "hashicorp/random"
      version = "~> 3.5"
    }
  }
}

kati.tf will call the random code to generate the string.

resource "random_string" "module1_random" {
  length           = 16
  special          = true
  override_special = "/@£$"
}

And finally the outputs.tf file will be used to mark the string as an output and print it in the console.

The module2 folder will only include a main.tf which will call module1. In order to make a module in terraform we will only need to specify the location of the folder. We do not need complex actions or definitions. In this example module2 will call module1 to generate the random string.

the main.tf file will only call the module1

module "kati" {
    source = "../module1"
}

In order to call the module I will need to perform an apply on module2.

cd module2; terraform apply

As we have not specified an output variable in module2 the result will not be printed in the console, you can see from below screenshot that module2 is calling kati file from module1 to generate the random string.

However we can find the result by navigating in the terraform.tfstate file of module2.

When we have more complex scenarios we will need to pass variables inside the calling modules. In order to learn how to pass variables in the calling modules you can read my previous article.

You can find the example on GitHub

https://github.com/geralexgr/terraform-modules-blog-example

Modules – Configuration Language | Terraform | HashiCorp Developer

Youtube video: