Using Terraform to upload Azure APIM - azure

I'm having a bit of problem parsing the differences between Azure's name for things and Terraform's name for things, but overall I'm making a good go of it. I am having some specific problems, though. My situation is that someone built the APIM using the Azure portal, and the company now wants to "make it scalable" by using Terraform to build it out. I've got a pretty good riff going - define, plan, import, plan, modify - but there are some parts of Azure APIM that can't map (mentally) to Terraform commands. My first one is this screen right here (the definitions tab of an API in APIM:)
Since I'm still fresh in terms of rep on Stack, I can't actually show the image. But in the portal at the bottom of the API there is a tab called "definitions". I haven't been able to see a) how to "get" them using Azure Powershell, and b) I how to "set" them with Terraform.
Would someone more knowledgeable about AzureRM and Terraform be able to steer me in the right direction please?

One of the workaround you can follow to deploy an API management instance with api's.
We have tried to create APIM instance with API,
Here is the sample terraform code that we used you can use it by adding resource name according to your requirement.
example.tf:-
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "example-resources"
location = "West Europe"
}
resource "azurerm_api_management" "example" {
name = "example-apimajmt"
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-apiajmt"
resource_group_name = azurerm_resource_group.example.name
api_management_name = azurerm_api_management.example.name
revision = "1"
display_name = "ajtest API"
path = "example"
protocols = ["https"]
import {
content_format = "swagger-link-json"
content_value = "http://conferenceapi.azurewebsites.net/?format=json"
}
}
After creation we can use it for adding tags
/* resource "azurerm_api_management_api_tag" "example" {
api_id = azurerm_api_management_api.example.id
name = "example-tagajmt"
}*/
Once the terraform apply is done then you will able to get the APIM instance along with the API and their tags after sometimes.
NOTE:- Creation of APIM will take upto 45 minutes.
OUTPUT SCREENSHOT FOR REFERENCE:-
For more information with configuration in APIM management by terraform please refer to this HashiCorp| Terraform Registry azurerm_api_management & this Similar SO THREAD|Tag an API in Azure API Management with Terraform.

Related

Azure App Service Plan inconsistently throttling - App Service Plan Create operation is throttled for subscription

When creating an App Service Plan on my new-ish (4 day old) subscription using Terraform, I immediately get a throttling error
App Service Plan Create operation is throttled for subscription <subscription>. Please contact support if issue persists
The thing is, when I then go to the UI and create an identical service plan, I receive no errors and it creates without issue, so it's clear that there is actually no throttling issue for creating the app service plan since I can make it.
I'm wondering if anyone knows why this is occurring?
NOTE
I've gotten around this issue by just creating the resource in the UI and then importing it into my TF state... but since the main point of IaC is automation, I'd like to ensure that this unusual behavior does not persist when I go to create new environments.
EDIT
My code is as follows
resource "azurerm_resource_group" "frontend_rg" {
name = "${var.env}-${var.abbr}-frontend"
location = var.location
}
resource "azurerm_service_plan" "frontend_sp" {
name = "${var.env}-${var.abbr}-sp"
resource_group_name = azurerm_resource_group.frontend_rg.name
location = azurerm_resource_group.frontend_rg.location
os_type = "Linux"
sku_name = "B1"
}
EDIT 2
terraform {
backend "azurerm" {}
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "3.15.0"
}
}
}

How do I add additional APIs to existing Azure API Manager using Terraform?

New to Terraform and as the question states I want to add additional APIs to an existing API Manager instance. Below is the example Terraform and this works fine. But I want to add a second api. Is it absolutely required that I put it inline in this Terraform script? The reason I ask is, If my team develops "example api" and a second team develops "awesomeexample api" can they have the Terraform code they need just for the api resource in their repository? Do I need to get the name of the API Manager through Powershell or GraphAPI? Edit: Right now when I add an additional api resource it destroys the first. I am guessing this is because of Terraform state...but that is not the behavior I want. I just want to keep adding apis or altering them independently of the api manager.
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 = "swagger-link-json"
content_value = "http://conferenceapi.azurewebsites.net/?format=json"
}
}
Me, I've been putting each API in it's own tf file.
Like for your example api, I'd create a api-example.tf file, cut/paste the azurerm_api_management_api block into it.
terraform init/plan/apply should still just work.
To add a new API into this API Mgmt instance, just copy api-example.tf to api-newapi.tf, edit as appropriate (name/displayname/path/import, and poof, new api.
I don't like using the same instance name for multiple different resources. here you used example three times, an RG, APIM, and APIM_API. it gets confusing and may break the minute you add a new API also referenced as 'example'. I use thisrg, ex-apim, and example-api (since your original API is called example). Your awsomeexample api I'd call awesome-api or something like that to differentiate example-api vs awesomeexample-api
Just ran into a similar thing that led me here.
One of our developers had added his resource by modifying our terraform files, planned it and applied it. By doing that he modified the remote state, but he never commited his changes. Thus when we were going to apply the terraform files from master, the locally planned state did not match what was in the remote.
In your case though, it is hard to tell. If you define two APIs in the same file that collide (e.g. 2x resource "azurerm_api_management_api" "example") that might cause you issues.

Getting Terraform resource already exists error with resource just created by Terraform

I'm setting up a virtual network in Azure with Terraform.
I have several VNets each with their own Network Security Group 100% managed in Terraform, no resources except the Resource Group exist prior to running Terraform.
When I run Terraform apply the first time all the resources are created correctly. However if I try and run apply again to update other resources I get an error saying the NSG resources already exist.
Error: A resource with the ID
"/subscriptions/0000000000000000/resourceGroups/SynthArtInfra/providers/Microsoft.Network/networkSecurityGroups/SynthArtInfra_ServerPoolNSG"
already exists - to be managed via Terraform this resource needs to be
imported into the State. Please see the resource documentation for
"azurerm_network_security_group" for more information.
Why is Terraform complaining about an existing resource when it should already be under it's control?
Edit:
This is the code related to the NSG, everything else is to do with a VPN gatway:
# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = ">= 2.26"
}
}
}
provider "azurerm" {
features {}
}
data "azurerm_resource_group" "SynthArtInfra" {
name = "SynthArtInfra"
location = "Somewhere" # not real
most_recent = true
}
resource "azurerm_virtual_network" "SynthArtInfra_ComputePool" {
name = "SynthArtInfra_ComputePool"
location = azurerm_resource_group.SynthArtInfra.location
resource_group_name = azurerm_resource_group.SynthArtInfra.name
address_space = ["10.6.0.0/16"]
}
resource "azurerm_subnet" "ComputePool_default" {
name = "ComputePool_default"
resource_group_name = azurerm_resource_group.SynthArtInfra.name
virtual_network_name = azurerm_virtual_network.SynthArtInfra_ComputePool.name
address_prefixes = ["10.6.0.0/24"]
}
resource "azurerm_network_security_group" "SynthArtInfra_ComputePoolNSG" {
name = "SynthArtInfra_ComputePoolNSG"
location = azurerm_resource_group.SynthArtInfra.location
resource_group_name = azurerm_resource_group.SynthArtInfra.name
security_rule {
name = "CustomSSH"
priority = 119
direction = "Inbound"
access = "Allow"
protocol = "*"
source_port_range = "*"
destination_port_range = "0000" # not the real port number
source_address_prefix = "*"
destination_address_prefix = "*"
}
}
The other odd thing is our subscription has a security policy that automatically adds NSGs to resources that don't have one. But weirdly after applying my terraform script the NSGs are created but aren't actually associated with the Subnets and the security policy has created new NSGs. This needs to be resolved but didn't think it would cause this error.
I think what was going on is this is my first time using Terraform so I was getting a lot of errors midway through apply and destroy operations.
I ended up manually removing all the resources in Azure and deleting Terraform's local cache then everything started working.
TLDR;
Try removing any custom dependencies between resources that you have added yourself.
Hi, I came across this post whilst having a similar problem and will put my solution here in case that helps someone else.
I was working on creating a Cloud Run Service through Terraform. The first time went great and it created the resource I wanted, but as soon as I ran the apply again I would get this error saying that a resource with that name already exists. This was strange because according to the plan it was supposed to delete and then replace that resource.
What happened was that I added an uneccessary depends_on field on a few other resources and this was blocking the Cloud Run Service resource from being deleted before trying to create a new one.
According to the docs the depends_on field is only needed if there is some strange dependency that cannot be inferred by looking at the fields. So I just removed all of the custom ties between the dependencies and can now re-apply as much as I like.

Error while provisioning Terraform subnet using azurerm

Recently i figured out that my AKS cluster holds a subnet which is too small. Therefor im trying to add a second subnet and nodepool which is possible with the Azure CNI nowadays and then create a single proper subnet instead and migrate it back.
During terraform plan all goes well with a valid response however while applying it throws an error.
Error: Error Creating/Updating Subnet "me-test-k8s-subnet2" (Virtual Network "me-test-k8s-vnet" / Resource Group "me-test-k8s-rg"): network.SubnetsClient#CreateOrUpdate: Failure sending request: StatusCode=400 -- Original Error: Code="NetcfgInvalidSubnet" Message="Subnet 'me-test-k8s-subnet2' is not valid in virtual network 'me-test-k8s-vnet'." Details=[]
on main.tf line 28, in resource "azurerm_subnet" "subnet2":
28: resource "azurerm_subnet" "subnet2" {
My original cluster is created with this configuration of Terraform:
name = "${var.cluster_name}-rg"
location = "${var.location}"
}
resource "azurerm_virtual_network" "network" {
name = "${var.cluster_name}-vnet"
location = "${azurerm_resource_group.rg.location}"
resource_group_name = "${azurerm_resource_group.rg.name}"
address_space = ["10.1.0.0/16"]
}
resource "azurerm_subnet" "subnet" {
name = "${var.cluster_name}-subnet"
resource_group_name = "${azurerm_resource_group.rg.name}"
address_prefixes = ["10.1.0.0/24"]
virtual_network_name = "${azurerm_virtual_network.network.name}"
}
To make things more easy i decided to first add the subnet to the network without the nodepool. This will bring me to this terraform plan:
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# azurerm_subnet.subnet2 will be created
+ resource "azurerm_subnet" "subnet2" {
+ address_prefix = (known after apply)
+ address_prefixes = [
+ "10.2.0.0/22",
]
+ enforce_private_link_endpoint_network_policies = false
+ enforce_private_link_service_network_policies = false
+ id = (known after apply)
+ name = "me-test-k8s-subnet2"
+ resource_group_name = "me-test-k8s-rg"
+ virtual_network_name = "me-test-k8s-vnet"
}
Hope that someone can explain me why this error occurs.
Best,
Pim
When creating a subnet in a virtual network, it is mandatory to check if it is not jumping out of the network range.
You are just out of the range with your network mask: 10.1.0.0/16
First host: 10.1.0.1
Last host: 10.1.255.254
And you are trying to create subnet 10.2.0.0/22.
For not overlapping with subnets that are already created, 10.1.4.0/22, can be accepted, for instance.
As mentioned in my comment and in someone's answer, Azure is throwing this error because you are trying to add a 10.2.0.0/22 subnet to a 10.1.0.0/16 network. ie- 10.2.0.0/22 is not part of that network.
I also want to point out that when you run a plan that is not submitting the actual API calls to Azure to make the changes, which is why things looked fine to you when you ran your plan, but Azure complained when you tried to apply it. I think the explanation is good in this tutorial. The excerpts that are applicable are:
Once you are happy with your declared configuration, you can ask
Terraform to generate an execution plan for it. The plan command in
the CLI is used to generate an execution plan from a configuration.
The execution plan tells you what changes Terraform would need to make
to bring your current infrastructure to the declared state in your
configuration.
If you accept the plan you can instruct Terraform to apply changes. Terraform will make the API calls required to implement the changes. If anything goes wrong terraform will not attempt to automatically rollback the infrastructure to the state it was in before running apply. This is because apply adheres to the plan
You might also run to a similar error if you try to deploy another vnet into a subscription where there already is a vnet with the same address space.

How to set Azure Web Application Firewall (WAF) logs via Terraforn?

I am trying to do this, via Terraform code:
However, I can not find how. Is it some obscure resource or it is not implemented at all ?
You can use the azurerm_monitor_diagnostic_setting to configure the setting as ydaetskcoR said, it works like the screenshot you provided shows. Here is the example code:
resource "azurerm_monitor_diagnostic_setting" "example" {
name = "example"
target_resource_id = "application_gateway_resource_id"
storage_account_id = data.azurerm_storage_account.example.id
log {
category = "ApplicationGatewayFirewallLog"
enabled = true
retention_policy {
enabled = true
days = 30
}
}
}
Terraform does not support Data for application gateway, so you need to input the resource id of the existing application gateway yourself, or quote the id when you create the new application gateway.
It seems like logs are not supported by Terraform for Azure WAF (ApplicationGateway) yet.

Resources