terraform-provider-azurerm icon indicating copy to clipboard operation
terraform-provider-azurerm copied to clipboard

Unable to create azurerm_api_management_api with imported content file with azurerm > 3.69.0

Open mennlo opened this issue 1 year ago • 62 comments

Is there an existing issue for this?

  • [X] I have searched the existing issues

Community Note

  • Please vote on this issue by adding a :thumbsup: reaction to the original issue to help the community and maintainers prioritize this request
  • Please do not leave "+1" or "me too" comments, they generate extra noise for issue followers and do not help prioritize the request
  • If you are interested in working on this issue or have submitted a pull request, please leave a comment and review the contribution guide to help.

Terraform Version

1.5.7

AzureRM Provider Version

3.69.0

Affected Resource(s)/Data Source(s)

azurerm_api_management_api

Terraform Configuration Files

data "azurerm_api_management" "apim" {
  name                = var.apim_name
  resource_group_name = var.resource_group_name
}

resource "azurerm_api_management_api" "api" {
  for_each = var.managed_apis

  name                  = var.instance_id != null ? "${each.key}-${var.instance_id}" : each.key
  display_name          = "${each.value.display_name} [${upper(var.env)}]"
  resource_group_name   = data.azurerm_api_management.apim.resource_group_name
  api_management_name   = data.azurerm_api_management.apim.name
  revision              = "current"
  soap_pass_through     = each.value.import_type == "wsdl" ? true : false
  path                  = local.is_shared_service ? "${local.app_context}/${each.value.service_path}" : each.value.service_path
  protocols             = ["https"]
  subscription_required = each.value.subscription_required
  version               = each.value.version != null ? each.value.version : null
  version_set_id        = each.value.version_set != null ? azurerm_api_management_api_version_set.version_set[each.value.version_set].id : null

  dynamic "import" {
    for_each = each.value.api_file == null ? [] : [1]
    content {
      content_format = each.value.import_type
      content_value  = file("${var.paths.apis}/${each.value.api_file}")

      dynamic "wsdl_selector" {
        for_each = each.value.wsdl_selector

        content {
          service_name  = wsdl_selector.value.service_name
          endpoint_name = wsdl_selector.value.endpoint_name
        }
      }
    }
  }
  depends_on = [azurerm_api_management_api_version_set.version_set]
}

EXAMPLE managed_apis var:

managed_apis = {
  "testapi" = {
    display_name = "test"
    service_path = "test"
    import_type  = "openapi"
    // This product id will have to match one of the the product id's in the 
    // Azure Portal in the APIs -> Products section of the APIM.  If you don't
    // see one that matches the project your API is for then reach out your
    // team lead (if not using a shared services apim) or the Cloud Services
    // team in MS Teams (if using share services apim)
    product_id            = "test"
    api_file              = "test.openapi.yaml"
    subscription_required = false
    wsdl_selector         = []
  },
}

EXAMPLE test.openapi.yaml

openapi: 3.0.0
info:
  title: title
  description: endpoint
  version: 1.0.0
servers:
  - url: "https://redacted.com/test/v1/test/test"
    description: environment
paths:
  /default:
    post:
      operationId: default
      summary: Default
      description: Default operation
      responses:
        "200":
          description: Accepted
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/response"
components:
  schemas:
    response:
      type: object
      properties:
        status:
          type: string
          example: success
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic

Debug Output/Panic Output

terraform [init -upgrade=false]
  Running command terraform with args [init -upgrade=false]
  
  Initializing the backend...
  
  Initializing provider plugins...
  - Finding hashicorp/azurerm versions matching "< 4.0.0"...
  - Installing hashicorp/azurerm v3.73.0...
  - Installed hashicorp/azurerm v3.73.0 (signed by HashiCorp)
  
  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.
  terraform [apply -input=false -auto-approve -var managed_apis={"test-api-v1" = {"display_name" = "Test API", "service_path" = "test/test", "subscription_required" = false, "wsdl_selector" = [], "product_id" = "test", "api_file" = "test.openapi.yaml", "import_type" = "openapi", "version" = null, "version_set" = null}} -var project_context=testing -var version_sets=[] -var instance_id=256 -var env=dev -var api_operations=[] -var apim_product={} -var api_policies=[] -var operation_policies=[] -var named_values={} -var resource_group_name=rg-redacted-01 -var apim_name=apim-redacted-01 -var paths={"apis" = "/home/runner/work/terraform-azure-managed-api-module/terraform-azure-managed-api-module/test/apis", "policies" = null} -no-color -lock=false]
  Running command terraform with args [apply -input=false -auto-approve -var managed_apis={"test-api-v1" = {"display_name" = "Test API", "service_path" = "test/test", "subscription_required" = false, "wsdl_selector" = [], "product_id" = "test", "api_file" = "test.openapi.yaml", "import_type" = "openapi", "version" = null, "version_set" = null}} -var project_context=testing -var version_sets=[] -var instance_id=256 -var env=dev -var api_operations=[] -var apim_product={} -var api_policies=[] -var operation_policies=[] -var named_values={} -var resource_group_name=rg-redacted-01 -var apim_name=apim-redacted-01 -var paths={"apis" = "/home/runner/work/terraform-azure-managed-api-module/terraform-azure-managed-api-module/test/apis", "policies" = null} -no-color -lock=false]
  data.azurerm_api_management.apim: Reading...
  data.azurerm_api_management.apim: Read complete after 1s [id=/subscriptions/***/resourceGroups/rg-redacted-01/providers/Microsoft.ApiManagement/service/apim-redacted-01]
  
  Terraform used the selected providers to generate the following execution
  plan. Resource actions are indicated with the following symbols:
    + create
  
  Terraform will perform the following actions:
  
    # azurerm_api_management_api.api["test-api-v1"] will be created
    + resource "azurerm_api_management_api" "api" {
        + api_management_name   = "apim-redacted-01"
        + api_type              = (known after apply)
        + display_name          = "Test API [DEV]"
        + id                    = (known after apply)
        + is_current            = (known after apply)
        + is_online             = (known after apply)
        + name                  = "test-api"
        + path                  = "test/test"
        + protocols             = [
            + "https",
          ]
        + resource_group_name   = "rg-redacted-01"
        + revision              = "current"
        + service_url           = (known after apply)
        + soap_pass_through     = false
        + subscription_required = false
        + version               = (known after apply)
        + version_set_id        = (known after apply)
  
        + import {
            + content_format = "openapi"
            + content_value  = <<-EOT
                  openapi: 3.0.0
                  info:
                    title: title
                    description: endpoint
                    version: 1.0.0
                  servers:
                    - url: "https://redacted.com/test/v1/test/test"
                      description: sandbox environment
                  paths:
                    /default:
                      post:
                        operationId: default
                        summary: Default
                        description: Default operation
                        responses:
                          "200":
                            description: Accepted
                            content:
                              application/json:
                                schema:
                                  $ref: "#/components/schemas/response"
                  components:
                    schemas:
                      response:
                        type: object
                        properties:
                          status:
                            type: string
                            example: success
                    securitySchemes:
                      basicAuth:
                        type: http
                        scheme: basic
              EOT
          }
      }
  
    # azurerm_api_management_product_api.product_api["test-api-v1"] will be created
    + resource "azurerm_api_management_product_api" "product_api" {
        + api_management_name = "apim-redacted-01"
        + api_name            = "test-api"
        + id                  = (known after apply)
        + product_id          = "test"
        + resource_group_name = "rg-redacted-01"
      }
  
  Plan: 2 to add, 0 to change, 0 to destroy.
  azurerm_api_management_api.api["test-api-v1"]: Creating...
  azurerm_api_management_api.api["test-api-v1"]: Still creating... [10s elapsed]
  
  Warning: Argument is deprecated
  
    with azurerm_api_management_api.api["test-api-v1"],
    on main.tf line 14, in resource "azurerm_api_management_api" "api":
    14:   soap_pass_through     = each.value.import_type == "wsdl" ? true : false
  
  `soap_pass_through` will be removed in favour of the property `api_type` in
  version 4.0 of the AzureRM Provider
  
  (and one more similar warning elsewhere)
  
  Error: creating/updating Api (Subscription: "***"
  Resource Group Name: "rg-redacted-01"
  Service Name: "apim-redacted-01"
  Api: "test-api"): polling after CreateOrUpdate: executing request: unexpected status 404 with error: ResourceNotFound: Api not found.
  
    with azurerm_api_management_api.api["test-api-v1"],
    on main.tf line 6, in resource "azurerm_api_management_api" "api":

Expected Behaviour

The azurerm_api_management_api should be created successfully.

I'm trying to create an azurerm_api_management_api using an openapi type imported file.

Actual Behaviour

With any version > 3.69.0, The azurerm_api_management_api creation fails with the following error:

  Error: creating/updating Api (Subscription: "***"
  Resource Group Name: "rg-redacted-01"
  Service Name: "apim-dedacted-01"
  Api: "test-api"): polling after CreateOrUpdate: executing request: unexpected status 404 with error: ResourceNotFound: Api not found.

If you used <= 3.69.0 the creation is successful.

Steps to Reproduce

terraform apply

Important Factoids

No response

References

No response

mennlo avatar Sep 19 '23 14:09 mennlo

Screenshot 2023-09-20 at 2 57 21 PM

Im facing this issue too. Whenever we tried to apply changes to the apim, the outcomes are unpredictable as well.

crizzs avatar Sep 20 '23 07:09 crizzs

@mennlo Thanks for taking the time to open this issue. Please subscribe to PR #23348 that @sinbai has created.

rcskosir avatar Sep 21 '23 13:09 rcskosir

It looks like the PR didn't solve the problem. It still occurs to me on v3.75.0.

Can we reopen this issue or should I make a new one?

zhallgato avatar Sep 29 '23 08:09 zhallgato

It looks like the PR didn't solve the problem. It still occurs to me on v3.75.0.

Can we reopen this issue or should I make a new one?

It worked for me after using v3.75.0.

mennlo avatar Sep 29 '23 13:09 mennlo

I also have this issue, also when using AzureRM provider in version 3.75.0 (mbfrahry FYI)

DominikKrissVisma avatar Oct 02 '23 15:10 DominikKrissVisma

@zhallgato, @mennlo, @DominikKrissVisma Thank you for the update, I will reopen this issue.

rcskosir avatar Oct 02 '23 16:10 rcskosir

Hey @sinbai, mind taking another look at this one?

rcskosir avatar Oct 12 '23 16:10 rcskosir

Hi @DominikKrissVisma, @zhallgato , sorry that PR could not solve your problem. Since the PR already addressed mennlo's issue , I assume that your case might be different. Is it possible to provide detailed terraform configuration (easily reproducible and contains variable values - except sensitive information) and reproduce steps to help reproduce and resolve the problem? In addition, it might help a lot if Terraform trace logs could also be provided. Thanks in advance.

sinbai avatar Oct 13 '23 01:10 sinbai

hello, this is terraform file (ranamed from tf to txt): genericapi.txt notice we are using azurerm_api_management_api_version_set, and revision in order to force API recreation. The reason is that when API yaml file changes, like there is new endpoint added, those changes are not always deployed via terraform. When this happens we are expiriencing the 404 issue:

Api: "int-c-client-systems-v2"): polling after CreateOrUpdate: executing request: unexpected status 404 with error: ResourceNotFound: Api not found.

  with azurerm_api_management_api.generic_client_systems["ccc"],
  on api_management_generic.tf line 31, in resource "azurerm_api_management_api" "generic_client_systems":
  31: resource "azurerm_api_management_api" "generic_client_systems"

the issue is that API is actualy created during that run, but not tracked in the TF state file, therefore after this happes we need to import the API into state file.

DominikKrissVisma avatar Nov 01 '23 05:11 DominikKrissVisma

This issue still persists in 3.80, I had to downgrade to 3.68 for the resource to create. Any timeline to fix this issue?

hieumoscow avatar Nov 10 '23 06:11 hieumoscow

I tried to work-around this by downgrading from 3.80 to 3.68 but it seems the state is no longer compatible, so it's not the easiest work-around.

I get a bunch of

│ The current state of azurerm_api_management_product_policy.<policyName>
│ was created by a newer provider version than is currently selected. Upgrade
│ the azurerm provider to work with this state.

│ The current state of azurerm_api_management_api_policy.<policyName>
│ was created by a newer provider version than is currently selected. Upgrade
│ the azurerm provider to work with this state.

Sorry for the noise :-)

christianfosli avatar Nov 13 '23 15:11 christianfosli

@sinbai looks like the original PR didn't resolve this issue - since you sent the original PR to fix this, can you take another look into this one? Thanks!

tombuildsstuff avatar Nov 13 '23 15:11 tombuildsstuff

Can anyone here provide more contexts in terms of step-by-step-repro-this-issue?

sinbai avatar Nov 14 '23 05:11 sinbai

Can anyone here provide more contexts in terms of step-by-step-repro-this-issue?

I can probably make one, but I can't make the time the next couple of days.

I can start by sharing some more information about the resource were this issue occurred to me on azurerm 3.80, though.

The resource looks like this

resource "azurerm_api_management_api" "api" {
  name                  = "clientname-${var.env}-api-${var.api_name}" # e.g. "clientname-d-api-clientapi-internal"
  api_management_name   = var.api_management_name         # e.g. "clientname-d-apim-common"
  resource_group_name   = var.resource_group_name         # e.g. "clientname-d-rg-common"
  revision              = var.revision                    # e.g. "50923", "50930", ...
  display_name          = var.display_name                # e.g. "clientname clientapi internal dev"
  path                  = "${var.api_name}"               # e.g. "clientapi"
  protocols             = ["https"]
  subscription_required = var.subscription_required       # e.g. true
  service_url           = var.service_url                 # e.g. https://clientname-d-aks.norwayeast.cloudapp.azure.com/clientapi
  import {
    content_format = "openapi"
    content_value  = file(var.openapi_definition)         # a fairly ordinary OpenAPI v3 spec in json format
                                                          # with info.version set to "internal"
  }
  lifecycle {
    # The version number is pulled from the BUILD_ID, so it changes constantly.
    # This will only update if the actual API has changed.
    ignore_changes = [revision]
  }
}

We have just one azurerm_api_management_api resource with this name+api_management_name, so the "revision" property is just being used to track which CI pipeline run it came from.

christianfosli avatar Nov 14 '23 13:11 christianfosli

I have some new information.

We had 6 APIMs in different environments (4 of them in East US and 2 of them in East US 2 Azure regions).

We only experienced the above-mentioned issue on those APIMs which were in East US 2 region.

So, we recreated these two APIMs in East US, and since the recreation we no longer experience the issue. Everything works fine.

Maybe the issue is related only to specific Azure regions. (maybe there are some delays in these regions?)

zhallgato avatar Nov 14 '23 17:11 zhallgato

This is happening to me too. We are in US East 2 as well and running azurerm 3.80. We are also importing a fairly large openapi definition.

cbruce80 avatar Nov 15 '23 05:11 cbruce80

For us, it seems to happen when trying to add apis with "large" (openapi) definition files (+300KB, +90 operations). Smaller definition files worked fine, and reverting to 3.69.0 works for everything. Location Norway East.

kjetiloen avatar Nov 15 '23 09:11 kjetiloen

I really appreciate everyone's help. It has been reproduced and is under investigation. Thank you so much!

sinbai avatar Nov 16 '23 01:11 sinbai

I am hitting this issue as well, on 3.81.0. My openai definition is quite small, having only 3 operations

celsocoutinho-tangany avatar Nov 23 '23 15:11 celsocoutinho-tangany

base-layer: the PollUntilDone of CreateOrUpdateThenPoll stops polling when the API returns resource not found error on first poll hashicorp/go-azure-sdk

Hi @tombuildsstuff I assume that this is a base layer issue. For the case of long running operation poller and the API return Location refers to itself, the 404 errors should be additionally handled in the base layer, what do you think? Please refer to issue #740 for details.

sinbai avatar Nov 30 '23 02:11 sinbai

Just started hitting this as well. AzureRM version 3.71, we're only adding one API with a single operation.

If downgrading isn't an option due to state file compatibility, are there any other workarounds besides create manually and import?

tgolly avatar Dec 06 '23 04:12 tgolly

Any update on this issue? We also get this issue with 3.79.0 & 3.85.0. Our yaml file size is 7.4K.

Also if we just rerun the terraform all works fine. Is there any other work around for this?

arsubram-akamai avatar Dec 16 '23 20:12 arsubram-akamai

@sinbai : We have observed something similar. I have created a small reproducer based on one of our real life deployments. I can consistently reproduce the failure/success of an api creation by making a small change to the openapi.yaml descriptor. Given the following parameter in the unique REST resource of our openapi.yaml file, the creation of the corresponding api will fail.

        - description: status
          in: query
          name: status
          schema:
            type: string
            default: P
            enum:
              - PRODUCTIVE
              - ARCHIVED

A summary of the failure pattern is

GET versionset -> 404
PUT versionset -> 201
GET versionset -> 200
GET version -> 404
PUT version -> 202
GET version -> 404

If we modify the default to be default: PRODUCTIVE however, the creation succeeds, with the following success pattern:

GET versionset -> 404
PUT versionset -> 201
GET versionset -> 200
GET version -> 404
PUT version -> 202
GET version -> 200
...

Note that https://apitools.dev/swagger-parser/online/ for instance validates both syntaxes. The Azure portal on the other hand doesn't: If we try to create the API by uploading the file via frontend using default: P, we get the following error message: One or more fields contain incorrect values: Default value must be present in the list of values. Our hypothesis is that the version creation fails silently in Azure API management.

We are currently on version v3.85.0

mrickly avatar Jan 11 '24 17:01 mrickly

@sinbai : Do you plan to take a look at this issue again (see my comment above)? Do you want me to open a new issue?

mrickly avatar Jan 29 '24 14:01 mrickly

@kjetiloen @hieumoscow since this will probably take months to address, can you please share the configuration you used to provision on 3.68.0 or 3.69.0? I am having the same error in those versions...

celsocoutinho-tangany avatar Jan 29 '24 16:01 celsocoutinho-tangany

Latest azurerm provider (version 3.92) still exhibits this behavior. Any progress information on this issue? :)

eugeneromero avatar Feb 19 '24 12:02 eugeneromero

@sinbai : Do you plan to take a look at this issue again (see my comment above)? Do you want me to open a new issue?

Hi @mrickly the best solution to this issue is to modify the implementation of base layer SDK. Could you please track this SDK issue for more updates?

sinbai avatar Feb 20 '24 02:02 sinbai

Latest azurerm provider (version 3.92) still exhibits this behavior. Any progress information on this issue? :)

Hi @eugeneromero Could you please track https://github.com/hashicorp/go-azure-sdk/issues/740 SDK issue for more updates?

sinbai avatar Feb 20 '24 02:02 sinbai

@sinbai : Do you plan to take a look at this issue again (see my comment above)? Do you want me to open a new issue?

Hi @mrickly the best solution to this issue is to modify the implementation of base layer SDK. Could you please track this SDK issue for more updates?

Hi @sinbai : I will do that, although I'm not sure that it covers our case. Unless the azure api systematically returns a delayed response via PollUntilDone (possibly different than 404 and 201, 422 for instance), I would expect to get a validation error already in the CreateOrUpdate step.

mrickly avatar Feb 20 '24 12:02 mrickly

Hi Team, Is there any fixes going on ? Please let me know the solution. I am facing the similar issue, like while I am trying to deploying a new API.

Regards, Nikhil

nikhil0499 avatar Feb 26 '24 09:02 nikhil0499