Using terraform to update existing Azure APIM - azure

I have a no. of API management services setup on Azure already but they are not provisioned using Terraform. Now I want to using terraform to update the backend HTTP endpoint and policies. Is it possible to do so? Is there any data sources for apim I can use? Any example I can refer to?

I tried in my environment and got below results:
Initially, I created Azure APIM management service using below terraform code.
main.tf
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "rg3"
location = "West Europe"
}
resource "azurerm_api_management" "example" {
name = "venkat-demo"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
publisher_name = "My Company"
publisher_email = "company#terraform.io"
sku_name = "Developer_1"
}
resource "azurerm_api_management_api" "example" {
name = "venkatdemo326"
resource_group_name = azurerm_resource_group.example.name
api_management_name = azurerm_api_management.example.name
revision = "1"
display_name = "vjtestAPI"
path = "example"
protocols = ["https"]
import {
content_format = "swagger-link-json"
content_value = "http://conferenceapi.azurewebsites.net/?format=json"
}
}
Portal:
Now I want to using terraform to update the backend HTTP endpoint and policies
You can use the below terraform code to create resources that manage the backend HTTP endpoint and policies of that service.
main.tf
provider "azurerm" {
features {}
}
data "azurerm_api_management" "example" {
name = "venkat-demo"
resource_group_name = data.azurerm_resource_group.example.name
}
resource "azurerm_api_management_backend" "example" {
name = "backend1"
api_management_name = data.azurerm_api_management.example.name
resource_group_name = data.azurerm_api_management.example.resource_group_name
protocol = "http"
url = "https://example.com/api"
}
resource "azurerm_api_management_policy" "example" {
api_management_id = data.azurerm_api_management.example.id
xml_content = <<XML
<policies>
<inbound>
<find-and-replace from="xyz" to="abc" />
</inbound>
</policies>
XML
}
Console:
Portal:
Reference:
azurerm_api_management_backend | Resources | hashicorp/azurerm | Terraform Registry
azurerm_api_management_policy | Resources | hashicorp/azurerm | Terraform Registry

If you want to change an Azure resource (in this case Azure APIM), you'll have to first declare the resource with the corresponding resource type (in this case azurerm_api_management) and then to import your existing resource into your Terraform's state.
After importing, on the subsequent execution of terraform plan, you'll see the changes terraform would like to execute based on the difference between your declaration and the current state of your APIM instance.
You cannot use a terraform data source (like this) if you want to change (=manage) the resource. Data sources can only be used to read attributes from resources.

Related

Multiple version sets and multiple APIs under each of the version sets to Azure APIM using terraform, Currently I get an error mentioned in the body

I have used depends_on version set in my API resource but still get the below error
Error - Future#WaitForCompletion: the number of retries has been exceeded: StatusCode=400 -- Original Error: Code="ValidationError" Message="One or more fields contain incorrect values:" Details=[{"code":"ValidationError","message":"Can't set VersionName when ApiVersionSetId is not set.","target":"ApiVersion
I tried to create APIM using terraform and set the version to that apim.
Whenever you try to create multiple versions of APIM , azure creates a version set for that particular API.
You need to refer that version set Id to the APIM .
see: azurerm_api_management_api_version_set | Resources | hashicorp/azurerm | Terraform Registry
resource "azurerm_api_management_api_version_set" "example" {
name = "kaexample-apimapi"
resource_group_name = data.azurerm_resource_group.example.name
api_management_name = azurerm_api_management.example.name
display_name = "ExampleAPIVersionSet"
versioning_scheme = "Segment"
}
resource "azurerm_api_management" "example" {
name = "kaexample-apim"
location = data.azurerm_resource_group.example.location
resource_group_name = data.azurerm_resource_group.example.name
publisher_name = "My Company"
publisher_email = "xxxx#gmail.com"
sku_name = "Developer_1"
}
resource "azurerm_api_management_api" "example" {
name = "kaexample-api"
resource_group_name = data.azurerm_resource_group.example.name
api_management_name = azurerm_api_management.example.name
revision = "1"
display_name = "My Example API"
path = "example"
protocols = ["https"]
version = "v1"
version_set_id = azurerm_api_management_api_version_set.example.id
import {
content_format = "<>"
content_value = "http://xxxxapi.azurewebsites.net/?format=json"
}
}
In case the version set is not updated ,import it using terraform import for the api having multiple versions
azurerm_api_management_api_version_set.example /subscriptions/xxxx/resourceGroups/group1/providers/Microsoft.ApiManagement/service/service1/apiVersionSets/set1
Reference:
Tutorial - Publish versions of your API using Azure API Management | Microsoft Learn

error deploying resources on azure using terraform cloud

I have deployed resources on Microsoft Azure using terraform. I'm using azure storage account container to save my terraform states. I tried to configure terraform cloud to automate the deployment but I get this error.
Error: A resource with the ID "/subscriptions/{SUBSCRIPTION_ID}/resourceGroups/msk-stage-keyvault" already exists - to be managed via Terraform this resource needs to be imported into the State. Please see the resource documentation for "azurerm_resource_group" for more information.
with module.keyvault.azurerm_resource_group.msk-keyvault
on ../../modules/az-keyvault/main.tf line 2, in resource "azurerm_resource_group" "msk-keyvault":
resource "azurerm_resource_group" "msk-keyvault" {
It seems that terraform cloud is not using my backend state in my provider.tf. How do I make terraform cloud use my backend state in provider.tf.
My Backend Provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "=2.91.0"
}
}
backend "azurerm" {
resource_group_name = "msk-configurations"
storage_account_name = "mskconfigurations"
container_name = "key-vault"
key = "stage.tfstate"
}
}
provider "azurerm" {
features {}
subscription_id = var.subscription
tenant_id = var.ternant_id
}
It looks like your main.tf has already existing keyvault state.
So Initially please check if you have already configured keyvault resource in main.tf file or if you have already imported the state.
If its already present in main.tf file , and if you are again giving it in the backend , please try to remove the one from main.tf file and then execute again.
Also please note that terraform backend needs azure storage account credentials before hand in order to store into the tfstate.
So please avoid creating storage simultaneously all account, container and then the keyvault resource to tfstate.
So if storage account is already created first , then terraform can refer it later in backend.
To preconfigure the storage account and container :
Example:
1. Create storage account and container one after the other instead in the same file:
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "example" {
name = "resourcegroupname"
}
resource "azurerm_storage_account" "example" {
name = "<yourstorageaccountname>"
resource_group_name = data.azurerm_resource_group.example.name
location = data.azurerm_resource_group.example.location
account_tier = "Standard"
account_replication_type = "LRS"
}
resource "azurerm_storage_container" "example" {
name = "newterraformcont"
storage_account_name = azurerm_storage_account.example.name
container_access_type = "private"
}
Then create the msk-keyvault resource group and store the tfstate in container.
This is my already created state file in terraform (terraform.tf)
provider "azurerm" {
features {}
}
terraform {
# Configure Terraform State Storage
backend "azurerm" {
resource_group_name = "<resourcegroup>"
storage_account_name = "<storage-earliercreated>"
container_name = " newterraformcont "
key = "terraform.tfstate"
}
}
resource "azurerm_resource_group" " msk-keyvault" {
name = "<msk-keyvault>"
location = "west us"
}
Reference:
azurerm_resource_group | Resources | hashicorp/azurerm | Terraform
Registry
https://www.jorgebernhardt.com/terraform-backend

Terraform can't create free web app on azure

Trying to setup my first web app using terraform on Azure using there freetier.
The Resource group, and app service plan were able to be created but the app creation gives an error that says:
creating Linux Web App: (Site Name "testazurermjay" / Resource Group "test-resources"): web.AppsClient#C. Status=<nil> <nil>
Here is the terraform main.tf file:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "test-resources"
location = "Switzerland North"
}
resource "azurerm_service_plan" "test" {
name = "test"
resource_group_name = azurerm_resource_group.test.name
location = "UK South" #azurerm_resource_group.test.location
os_type = "Linux"
sku_name = "F1"
}
resource "azurerm_linux_web_app" "test" {
name = "testazurermjay"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_service_plan.test.location
service_plan_id = azurerm_service_plan.test.id
site_config {}
}
At first I thought the name was the issue for the azurerm_linux_web_app so I changed it from test to testazurermjay however that was not able to work.
I was able to get it to work BUT I had to use a depreciated resource called azurerm_app_service instead of azurerm_linux_web_app. I ALSO had to make sure that my resource-group and app service plan were in the same location. When I originally tried to set both the resource group and the app plan to Switzerland North it would give me an error when creating the app service plan (That is why you see me change the plan to UK South in the Original question). HOWEVER - after I set BOTH resource group and app service plan to UK South they were able to be created in the same location. Then I used azurerm_app_service to create a free tier service using the use_32_bit_worker_process = true variable in the site_config object.
Here is the full terraform file now:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "test" {
name = "test-resources"
location = "UK South"
}
resource "azurerm_service_plan" "test" {
name = "test"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
os_type = "Linux"
sku_name = "F1"
}
resource "azurerm_app_service" "test" {
name = "sofcvlepsaipd"
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
app_service_plan_id = azurerm_service_plan.test.id
site_config {
use_32_bit_worker_process = true
}
}
I MUST STRESS THAT THIS ISN'T BEST PRACTICE AS THE azurerm_app_service IS GOING TO BE REMOVED IN THE NEXT VERSION. THIS SEEMS TO INDICATE THAT TERRAFORM WONT BE ABLE TO CREATE FREE TIER APP SERVICES IN THE NEXT UPDATE.
If someone knows how to do this with azurerm_linux_web_app or knows a better approach to this let me know.
I just encountered a similar issue, "always_on" setting defaults to true, but that is not supported in the free tier. As stated here, you must explicitly set it to false when using free tier
resource "azurerm_linux_web_app" "test" {
name = "testazurermjay"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_service_plan.test.location
service_plan_id = azurerm_service_plan.test.id
site_config {
always_on = false
}
}

Azure Terraform API Management Graphql Support

I'm creating APIs on the Azure APIM with GraphQL. This is still on preview so until now I only can create them clicking in the portal or using the Azure API Rest with a PUT request.
I'm trying to migrate all of this to Terraform but I don't find any website with information about if there is any way to create GraphQL APIs with Terraform or even using a module.
What I'm trying to do is something like this:
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_api_management" "example" {
name = "example-apim"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
publisher_name = "My Company"
publisher_email = "company#terraform.io"
sku_name = "Developer_1"
}
resource "azurerm_api_management_api" "example" {
name = "example-api"
resource_group_name = azurerm_resource_group.example.name
api_management_name = azurerm_api_management.example.name
revision = "1"
display_name = "Example API"
path = "example"
protocols = ["https"]
import {
content_format = "graphql-file"
content_value = "schema.graphql"
}
}
I'm kind of newbie at Terraform and I'm a little lost as I can't find any doc about this on the official page or anywhere.
EDIT: What I'm trying to find is to automate with Terraform this process:
GraphQL Import
Thanks.
Here is the Plugin provider of GraphQL API resources using terraform.
This provider has several configuration inputs.
In most cases, only url & headers are used,
provider "graphql" {
url = "https://your-graphql-server-url"
headers = {
"header1" = "header1-value"
"header2" = "header2-value"
...
}
}
Here is the Argument Reference document for GraphQl API with terraform.
And here is the complete document for creating GraphQL api with terraform.

Error on adding a storage share to the Azure storage account

I'm getting the following error on running terraform apply after adding an azurerm_storage_share.
Error: Error checking for existence of existing Storage Share "fileshare"
(Account "sttestforaddingfileshare" / Resource Group "resources"):
shares.Client#GetProperties: Failure responding to request: StatusCode=403
-- Original Error: autorest/azure: Service returned an error.
Status=403 Code="AuthorizationFailure"
Message="This request is not authorized to perform this operation.
\nRequestId:188ae38b-e01a-000b-35b3-a32ea2000000
\nTime:2020-10-16T11:55:16.7337008Z"
I think the reason is most likely that Terraform tries to list existing file shares in the storage account directly accessing the storage account's REST API instead of Azure Resource Manager's REST API.
It failed because there exist firewall rules in place not containing the IP of the host terraform runs on. When I add my laptop's IP to the firewall rules, it works. But it's not the desired behavior.
Do you know any workaround? Any help is appreciated.
My TF configuration is as follows:
provider "azurerm" {
version = "= 2.32.0"
features {}
}
resource "azurerm_resource_group" "rg" {
name = "resources"
location = var.location
}
resource "azurerm_virtual_network" "vnet" {
name = "vnet"
location = var.location
resource_group_name = azurerm_resource_group.rg.name
address_space = ["10.0.0.0/16"]
}
resource "azurerm_subnet" "snet" {
name = "snet"
resource_group_name = azurerm_resource_group.rg.name
virtual_network_name = azurerm_virtual_network.vnet.name
address_prefixes = ["10.0.1.0/24"]
service_endpoints = [ "Microsoft.Storage" ]
}
resource "azurerm_storage_account" "storage" {
name = "sttestforaddingfileshare"
resource_group_name = azurerm_resource_group.rg.name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
network_rules {
default_action = "Deny"
virtual_network_subnet_ids = [ azurerm_subnet.snet.id ]
bypass = [ "None" ]
}
}
resource "azurerm_storage_share" "file_share" {
name = "fileshare"
storage_account_name = azurerm_storage_account.storage.name
quota = 100
}
You can use the azurerm_storage_account_network_rules resource to define the Network Rules and remove the Network Rules block defined directly on the azurerm_storage_account resource.
Also, you can create your file share via using az CLI instead of the separate resource "azurerm_storage_share"
After my validation, with the
PS D:\Terraform> .\terraform.exe -v
Terraform v0.13.4
+ provider registry.terraform.io/hashicorp/azurerm v2.32.0
It worked when terraform apply and terraform destroy.
resource "azurerm_storage_account" "storage" {
name = "nnnstore1"
resource_group_name = azurerm_resource_group.rg.name
location = var.location
account_tier = "Standard"
account_replication_type = "LRS"
provisioner "local-exec" {
command =<<EOT
az storage share create `
--account-name ${azurerm_storage_account.storage.name} `
--account-key ${azurerm_storage_account.storage.primary_access_key} `
--name ${var.myshare} `
--quota 100
EOT
interpreter = [ "Powershell", "-c"]
}
}
resource "azurerm_storage_account_network_rules" "test" {
resource_group_name = azurerm_resource_group.rg.name
storage_account_name = azurerm_storage_account.storage.name
default_action = "Deny"
virtual_network_subnet_ids = [azurerm_subnet.snet.id]
bypass = ["None"]
}
I recently ran into this issue when attempting to create a storage share for a container group. It was pretty much identical code to yours but with the additional container group.
I came across the issue when deploying the stack as new and I bypassed the error by deploying everything but the storage share component and all references to it.
Then when that was completed I introduced the storage share and redeployed without issue.
Crappy work around but its deployed again.

Resources