Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracting id from URI using id_attribute #205

Open
blairnangle opened this issue Jan 4, 2023 · 4 comments
Open

Extracting id from URI using id_attribute #205

blairnangle opened this issue Jan 4, 2023 · 4 comments

Comments

@blairnangle
Copy link

blairnangle commented Jan 4, 2023

For context, I am working with the Calendly Webhook API.

I can create a webhook fine the first time, but subsequent retries result in a "webhook subscription already exists"-type error originating from Calendly's API, rather than a "remote state is as expected, resource already exists"-type message from Terraform.

This is because the successful response from Calendly is of the form:

"resource": {
  "uri": "https://api.calendly.com/webhook_subscriptions/AAAAAAAAAAAAAAAA",
  "callback_url": "https://blah.foo/bar",
  "created_at": "2019-08-24T14:15:22.123456Z",
  "updated_at": "2019-08-24T14:15:22.123456Z",
  "retry_started_at": "2019-08-24T14:15:22.123456Z",
  "state": "active",
  "events": [
    "invitee.created"
  ],
  "scope": "user",
  "organization": "https://api.calendly.com/organizations/AAAAAAAAAAAAAAAA",
  "user": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA",
  "creator": "https://api.calendly.com/users/AAAAAAAAAAAAAAAA"
}

So I can use the id_attribute field to extract the id as https://api.calendly.com/webhook_subscriptions/AAAAAAAAAAAAAAAA with resource/uri. But this means that my id is a URI, not AAAAAAAAAAAAAAAA which the provider needs to use to interact correctly with Calendly's read and update APIs (the GET and PUT Calendly APIs expect the calls of the form https://api.calendly.com/webhook_subscriptions/AAAAAAAAAAAAAAAA.

Is there a known way to use id_attribute with some native Terraform functions to extract and set an id from a response where the value of the target field is a URI (or any other string that requires some work)?

My first attempt was to try overriding read_path on the restapi_object:

read_path = "https://api.calendly.com/webhook_subscriptions/${element(split("/", "{id}"), length(split("/", "{id}")) - 1)}"

But this just results:

read_path = "https://api.calendly.com/webhook_subscriptions/{id}"

I guess the provider string interpolation is happening in the wrong order with respect to the native Terraform code.

Just wondering if this is a solved problem or a limitation of the provider. Thanks in advance!

@DRuggeri
Copy link
Member

DRuggeri commented Jan 4, 2023

Hi, @blairnangle - good question. I think your inclination is correct: interpolation of the variables is happening in an unexpected order. The provider is doing its own interpolation because of how flexible the location of the URI must be. The downside to this is that the interpolation happens at the very last second just before the request is submitted.

I do think some sort of native terraform solution would be a nice silver bullet. I'm not aware of something that says, "get the value of attribute foo in this resource, slice and dice the value, and insert it elsewhere into the resource"

@blairnangle
Copy link
Author

blairnangle commented Jan 18, 2023

Hey @DRuggeri, thank you for the reply!

Yeah, I guess the issue kind of comes down to the HATEOAS-inspired implementation of the Calendly API where the client is always expected to be passing around URIs.

However, I have also tried setting the read_path as the returned URI in the restapi_object:

resource "restapi_object" "event_created_or_canceled" {
  provider      = restapi
  path          = ""
  create_method = "POST"
  data          = templatefile("${path.module}/templates/webhook.json", {
    backend_url = var.backend_url
  }
  )
  read_path = "{id}"
}

Assuming that {id} will evaluate to https://api.calendly.com/webhook_subscriptions/AAAAAAAAAAAAAAAA. I would then expect the Calendly API to respond with a 200/found under the hood when performing subsequent applys which would result in Terraform not trying to recreate the resource—but this doesn't happen.

Perhaps {id} is not being evaluated correctly?

@stephenpaulger
Copy link

I am having a similar issue right now.

On creating an object the API returns the item without an ID in the fields but there is a url for the object that contains the ID with a "_meta" dict. I could set id_attribute to _meta/href but I'd need a way to read the ID from the end of the URL.

I think I can see how this could be done with a modification to the provider with restapi/api_object.go whenever the ID is read it could be parsed as a URL, either with some clever logic that works if it looks like a URL or with an additional field that tells it that the id attribute is in URL form.

I think I could probably make that change.

@stephenpaulger
Copy link

@blairnangle I've created a PR that might fix the issue you were having. #222

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants