hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.4k stars 9.5k forks source link

urlparse function to get url parts #23893

Open matti opened 4 years ago

matti commented 4 years ago

a workaround:

https://registry.terraform.io/modules/matti/urlparse/external/0.2.0

apparentlymart commented 4 years ago

Thanks for sharing this, @matti!

Another option with Terraform as it exists today is to use the regular expression given in RFC 3986 Appendix A:

> regex("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", "http://user:pass@www.example.com:8080/path?query1=1&query2=2#frag")
[
  "http:",
  "http",
  "//user:pass@www.example.com:8080",
  "user:pass@www.example.com:8080",
  "/path",
  "?query1=1&query2=2",
  "query1=1&query2=2",
  "#frag",
  "frag",
]

Or, a variant of it using named capture groups for easier consumption of the result:

> regex("(?:(?P<scheme>[^:/?#]+):)?(?://(?P<authority>[^/?#]*))?(?P<path>[^?#]*)(?:\\?(?P<query>[^#]*))?(?:#(?P<fragment>.*))?", "http://user:pass@www.example.com:8080/path?query1=1&query2=2#frag")
{
  "authority" = "user:pass@www.example.com:8080"
  "fragment" = "frag"
  "path" = "/path"
  "query" = "query1=1&query2=2"
  "scheme" = "http"
}

This particular regex pattern doesn't try to decompose the "authority" portion because it's a generic URL match rather than a scheme-specific match. Perhaps that part could be parsed in a subsequent call where needed, as a way to get this done in current Terraform releases.

matti commented 4 years ago

the regexp you provided does not provide the same parts what my module does - I tried to write regexp like that but it is super hard.

ljalbinson commented 3 years ago

I posted on this subject elsewhere and was re-directed by Martin (thank you Martin):

For the hostname only I did the following using the go url.Parse and net.SplitHostPart functions:

+var URLToHostNameFunc = function.New(&function.Spec{

I don't think it would be much of a stretch to cover most of the other cases.

Kind regards, Lawrence

ljalbinson commented 3 years ago

Sorry for the broken code insert.

mkielar commented 2 years ago

How disappointing this simple feature is not getting enough attention. Our use case is this: We deploy AppMesh Virtual Services for all of our external integrations. So let's say we have following setup:

  1. https://example.com:8112
  2. http://foo.bar/askme/anything/
  3. sftp://joe:secret@my.ftp.com

The above is more or less what we keep in out .tfvars files or in SSM secrets, because applications need to know the protocol and port, and path prefix, etc.

However, for appmesh, we also need to specify the backends to tell envoy to look up their definitions. This is where we need to strip stuff and just leave the domain name. And there's no way to do this in terraform, so we have to split our variables into separate protocols, auth, domain, path etc. It's doable, but could be much easier if there was an urlparse() function in terraform.

nibblesnbits commented 1 year ago

I'd love this, too. I need to set a DNS record based on an output that can only be a full URL. Without the ability to natively extract the Authority from that full URL, I can't automate my deployment properly.

flynnhandley commented 1 year ago

I'll have a crack at it @nibblesnbits

flynnhandley commented 1 year ago

@nibblesnbits @mkielar @apparentlymart

Would you mind reviewing this draft PR? If everyone's happy, I'll finish off the docs and convert it to a PR.

https://github.com/hashicorp/terraform/pull/32328

Thanks 🏖️

speller commented 11 months ago

Any updates here?

bflad commented 11 months ago

While I cannot speak to whether this might land as a built-in function in the Terraform configuration language, you might find https://github.com/hashicorp/terraform/issues/27696 an interesting issue to track.

speller commented 11 months ago

@bflad already tracking it :) BTW, this time I needed to extract the host and port from AWS RabbitMQ's endpoint string returned in the URL form.

hanswesterbeek commented 8 months ago

@bflad already tracking it :) BTW, this time I needed to extract the host and port from AWS RabbitMQ's endpoint string returned in the URL form.

same here :)

crw commented 6 months ago

Thank you for your continued interest in this issue.

Terraform version 1.8 launches with support of provider-defined functions. It is now possible to implement your own functions! We would love to see this implemented as a provider-defined function.

Please see the provider-defined functions documentation to learn how to implement functions in your providers. If you are new to provider development, learn how to create a new provider with the Terraform Plugin Framework. If you have any questions, please visit the Terraform Plugin Development category in our official forum.

We hope this feature unblocks future function development and provides more flexibility for the Terraform community. Thank you for your continued support of Terraform!