Documentation or feature request for dereferencing URIs in API responses
I use the Python Client Library to automate some tasks in Google Cloud. One issue I run into somewhat regularly is that the API returns URIs as references to other objects and I don't know how to use those to get the object itself.
For example: If I get an instance and want to pull one of the disk objects:
>>> instance = instances_client.get(instance='my-instance', project='my-project', zone='us-central1-a')
>>> instance
...
disks {
...
source: "https://www.googleapis.com/compute/v1/projects/my-project/zones/us-central1-a/disks/my-instance"
...
}
...
I'm not sure how to actually get the disk. I asked on StackOverflow about this and was told to treat the URIs as opaque identifiers. If that is the case, it seems there is no way to get the disk object itself. I have the disk's name and I think I can assume it is in the same zone as the instance, but I would still need the project. I don't think there is any guarantee that the disk is in the same project as the instance, right?
Anyway, I don't want to get too hung up on this specific example. I'd like to know--in general--what is the recommendation for accessing a referenced object when all you have is a URI. If this is working as expected, I'd like for the documentation to explain how such a situation should be handled. If this is not expected, I'd like the SDK or the API to make it possible to dereference the URIs.
For reference, I am currently using these versions:
google-api-core==2.19.0 google-cloud-compute==1.18.0
Hello!
Perhaps this would be useful. I can't guarantee it works for every resource we have, but it should catch most of them.
import re
RESOURCE_URI_PATTERN = re.compile('^https://www.googleapis.com/compute/v1/projects/(?P<project>[^/]+)/(?:(?:zones/(?P<zone>\w+-\w+\d-\w))|(?:regions/(?P<region>\w+-\w+\d))|global)/[\w]+/(?P<name>[^$?/]+)')
def analyze_resource_info(resource_uri: str) -> dict:
"""
Tries to figure out information about the resource pointed at by the
resource_uri string. Returns a dictionary with information about the
project, zone, region and name of the resource.
"""
match = RESOURCE_URI_PATTERN.match(resource_uri)
if not match:
return {'project': None, 'zone': None, 'name': None, 'region': None}
return match.groupdict()
I didn't test it for every possible resource, but should work just fine with disks, images or snapshots. It should also demonstrate, how the naming convention works, so you can deconstruct the self_links yourself in cases this doesn't work :)
Thanks. I'm currently doing something similar to that. I wasn't sure if that was the official recommendation. It feels a little weird to me to be parsing that value but if that is the right thing to do, I can go ahead with that.
It might be nice to build that kind of a function into the SDKs. Assuming I guess that such a function could be made reliable enough for general use.
And it might be nice to indicate in the documentation that parsing the URIs is the right way to handle such a situation.
I'm going to close this issue due to inactivity but please feel free to open a new issue.