mulesoft-anypoint / terraform-provider-anypoint

The Anypoint Platform Terraform Provider
https://registry.terraform.io/providers/mulesoft-anypoint/anypoint/latest
MIT License
12 stars 6 forks source link

Failure to import APIM Instances #36

Closed TomChapple closed 6 months ago

TomChapple commented 7 months ago

The most recent release of this provider has me very excited and I have been experimenting with its usage for APIM Instances, but it appears that I cannot use the import command for the "anypoint_apim_mule4" resources.

Problem

It appears as though the terraform import anypoint_apim_mule4.<resource> <id> command generates a malformed URL for the APIM Instance in question, thereby resulting in a "NotFoundError" from Anypoint.

Symptoms

For the purposes of these symptoms, I am using dummy GUIDs and IDs. Be aware that I am using (to the best of my knowledge) accurate GUIDs and IDs for the platform I am working with and that these examples will need to be modified to use other values to work on an arbitrary machine. Despite this, the symptoms described will appear with these stub values.

I have a Terraform configuration with the following content describing an APIM Instance:

resource "anypoint_apim_mule4" "hello-world" {
    env_id = "12345678-90ab-cdef-1234-567890abcdef"
    org_id = "12345678-90ab-cdef-1234-567890abcdef"

    asset_group_id = "12345678-90ab-cdef-1234-567890abcdef"
    asset_id       = "my-api"
    asset_version  = "1.0.0"

    endpoint_uri   = "https://hello.world/"
}

Given this, when I attempt to run an import command such as terraform import anypoint_apim_mule4.hello-world 12345678 (the 12345678 can even be invalid such as abc), I get the following response:

% terraform import anypoint_apim_mule4.hello-world 12345678
anypoint_apim_mule4.hello-world: Importing from ID "12345678"...
anypoint_apim_mule4.hello-world: Import prepared!
  Prepared anypoint_apim_mule4 for import
anypoint_apim_mule4.hello-world: Refreshing state... [id=12345678]
╷
│ Error: Unable to get API manager's mule4 instance 12345678
│ 
│ {"name":"NotFoundError","message":"\"Organization\" could not be found using \"id: environments\""}
╵

Note that I can use the terraform plan command to get valid output:

% terraform plan                                                                                    

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:

  # anypoint_apim_mule4.hello-world will be created
  + resource "anypoint_apim_mule4" "hello-world" {
      + asset_group_id              = "12345678-90ab-cdef-1234-567890abcdef"
      + asset_id                    = "my-api"
      + asset_version               = "1.0.0"
      + audit                       = (known after apply)
      + autodiscovery_instance_name = (known after apply)
      + deprecated                  = false
      + endpoint_audit              = (known after apply)
      + endpoint_deployment_type    = "HY"
      + endpoint_id                 = (known after apply)
      + endpoint_type               = (known after apply)
      + endpoint_uri                = "https://hello.world/"
      + env_id                      = "12345678-90ab-cdef-1234-567890abcdef"
      + id                          = (known after apply)
      + is_public                   = (known after apply)
      + last_active_date            = (known after apply)
      + last_updated                = (known after apply)
      + master_organization_id      = (known after apply)
      + order                       = (known after apply)
      + org_id                      = "12345678-90ab-cdef-1234-567890abcdef"
      + product_version             = (known after apply)
      + status                      = (known after apply)
      + technology                  = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.

────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't
guarantee to take exactly these actions if you run "terraform apply" now.

Theories

The output mentioning that the organisation ID be searched for is "environments", which is very odd. However, the line in the Anypoint Go Client that describes this URL template has /environments as the immediate next path element. My theory is that the org_id is somehow blanked out and so Anypoint just uses the next path element available. This looks feasible to me as the Anypoint Go Client has a function called parameterValueToString that contains logic to blank out the string under certain conditions.

I'm not super familiar with Go or this framework, so I would take any of this analysis with a grain of salt.

Technical Information

I am using the following Terraform providers for my testing:

terraform {
  required_providers {
    anypoint = {
      source = "mulesoft-anypoint/anypoint"
      version = "1.6.0"
    }
  }
}

provider "anypoint" {}

Anypoint Credentials are being passed in via the exported variables ANYPOINT_CLIENT_ID and ANYPOINT_CLIENT_SECRET and have been granted permission to the business group and environment in question.

When running terraform version I get the following output:

Terraform v1.7.3
on darwin_arm64
+ provider registry.terraform.io/mulesoft-anypoint/anypoint v1.6.0
soufi commented 6 months ago

Hi @TomChapple for your example, you have to use a composed id. the resource APIM is located under other resources and the URL cannot be generated with only the id of the APIM.

here's an example:

# In order for the import to work, you should provide a ID composed of the following:
#  {ORG_ID}/{ENV_ID}/{API_ENV_ID}

terraform import \
  -var-file params.tfvars.json \    #variables file
  anypoint_apim_mule4.mule \                #resource name
  aa1f55d6-213d-4f60-845c-201282484cd1/7074fcdd-9b23-4ab6-97r8-5db5f4adf17d/19218070    #resource ID

replace with your own values.

TomChapple commented 6 months ago

Awesome, thanks for the clarification! I was able to import it successfully using that method you described. I'm happy to close this issue.