Terraform Providers
Tags: terraform, azure
Published: 2022-06-03 15:35:00


This is part-02 of our terraform series, In this one we are discussing terraform providers.

**What is Provider?**
As per the definition of Provider on Terraform documentation:

> _Providers are a logical abstraction of an upstream API. They are responsible for understanding API interactions and exposing resources_. 

What does this means that the providers are responsible for provisioning the resource into cloud platform using the terraform syntax, e.g.: to provision azure resources with terraform you can use azure provider with terraform, I hope this is clear.


![Providers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ibsek3au34pfxjmi6c0k.png)
  
Terraform has so many providers built-in for different cloud providers such as aws, azure, google, oracle, cloud-flare etc. these providers are manage and maintain by the cloud team, for e.g. azure provider is manage by azure team, what does it means is if there are any changes introduced by azure on existing azure services or azure introduces new services then azure team will make those updates into azure provider and and release new version, it means that each provider are declared with its own specific version.
The documents and source code link for each provider can be found in terraform website.
Here is the example of terraform azure provider link

https://registry.terraform.io/providers/hashicorp/azurerm/latest

Here you can find the latest version of specific cloud provider.

**Terraform Provider declaration**

Now let's see: How to declare the terraform provider? In this case we will use the example of azure provider declaration.

```terraform
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      # terraform with version 3.0.0
      version = "=3.0.0"
    }
  }
}
```

the argument reference can be found here

registry.terraform.io/providers/hashicorp/azurerm/latest/docs#argument-reference

Here with terraform provider

1. version - version of terraform provider you can use equal (=) operator for specific version or use >= operator if you want to use version greater then specific version

```terraform
terraform {
  required_providers {
    azurerm = {
      source  = "hashicorp/azurerm"
      version = ">=3.0.0"
    }
  }
}
```
 
2. If you want to stick to specific major version with all latest minor release of terraform provider you can do that with "~>" operator as given below, also it is possible to specify multiple provider within a single terraform provider block as given below

```terraform 
terraform {
  required_providers {
    azurerm = {
      # terraform with version 2.88 and all minor release of 2.88
      version = "~> 2.88.1"
      source = "hashicorp/azurerm"
    }
    # terraform azure caf provider
    azurecaf = {
      source = "aztfmod/azurecaf"
    }
  }

  backend "azurerm" {
  }
}
```

**Terraform with feature block** 

The Azure Provider allows the behaviour of certain resources to be configured using the features block.

This allows different users to select the behaviour they require, for example some users may wish for the OS Disks for a Virtual Machine to be removed automatically when the Virtual Machine is destroyed - whereas other users may wish for these OS Disks to be detached but not deleted.

```terraform
provider "azurerm" {
  features {
    api_management {
      purge_soft_delete_on_destroy = true
      recover_soft_deleted         = true
    }

    application_insights {
      disable_generated_rule = false
    }

    cognitive_account {
      purge_soft_delete_on_destroy = true
    }

    key_vault {
      purge_soft_delete_on_destroy    = true
      recover_soft_deleted_key_vaults = true
    }

    log_analytics_workspace {
      permanently_delete_on_destroy = true
    }

    resource_group {
      prevent_deletion_if_contains_resources = true
    }

    template_deployment {
      delete_nested_items_during_deletion = true
    }

    virtual_machine {
      delete_os_disk_on_deletion     = true
      graceful_shutdown              = false
      skip_shutdown_and_force_delete = false
    }

    virtual_machine_scale_set {
      force_delete                  = false
      roll_instances_when_required  = true
      scale_to_zero_before_deletion = true
    }
  }
}
```

Each resource specific block mentioned above is optional, you can specify based on the infrastructure behavior you want for these specifc resources.


**How Provider it works?**

As I have mentioned in the beginning you need at least one provider block to provision resource with terraform.

When you run terraform initialization command it downloads the terraform provider executable under dot terraform directory (.terraform directory will be created if it doesn't exists), along with terraform modules if you have any modules used in your terraform code.

```terraform 
🦄  terraform init
Initializing modules...

Initializing the backend...

Initializing provider plugins...
- Finding latest version of aztfmod/azurecaf...
- Finding hashicorp/azurerm versions matching "~> 2.88.1"...
- Installing aztfmod/azurecaf v1.2.18...
- Installed aztfmod/azurecaf v1.2.18 (self-signed, key ID 3D457F4D69B172D6)
- Installing hashicorp/azurerm v2.88.1...
- Installed hashicorp/azurerm v2.88.1 (signed by HashiCorp)

Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html

Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
```

![Providers](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3kzhufsv5wrh5459nm8e.png)
 
**Summary** 

Here is the summary of terraform provider.

- You need atleast one provider in your terraform code to provision resources with terraform into your cloud environment.

- It's also possible to have multiple provider with your terraform such as local provider, azure provider etc.

- It's also possible to write your own custom providers with terraform.

With our discussion above we have discussed about terraform init command with respect to the provider, in our next section we will discuss about terraform commands.