googleapis / google-cloud-node

Google Cloud Client Library for Node.js
https://cloud.google.com/nodejs
Apache License 2.0
2.87k stars 584 forks source link

[resource-manager] Add `location` attribute to `tagBindingsClient` functions #4864

Open LoicMoerman opened 7 months ago

LoicMoerman commented 7 months ago

Environment details

Some tag bindings require the location to be specified, ex: compute instances

Steps to reproduce

The location option is missing from all tagBindingsClient functions so we cannot use tag bindings for regional or zonal resources

Related issue in terraform.

This not working :

const [bindings] = await this.tagBindingsClient.listTagBindings({
    parent: `//compute.googleapis.com/projects/${projectId}/zones/${zone}/instances/${instanceId}`,
});

Proposed solution is to add location like this :

const [bindings] = await this.tagBindingsClient.listTagBindings({
    parent: `//compute.googleapis.com/projects/${projectId}/zones/${zone}/instances/${instanceId}`,
    location: zone/region
});

The api endpoint needs to change for regional or zonal bindings like this : northamerica-northeast1-a-cloudresourcemanager.googleapis.com

sofisl commented 6 months ago

Hi @LoicMoerman, would you mind providing reproduction steps to better understand the issue? (We deal with a lot of APIs, it will help me better understand the context). Thank you!

LoicMoerman commented 6 months ago

Hi @sofisl

For example this code doesn't work :

import resourceManager from '@google-cloud/resource-manager';
const tagBindingsClient = new resourceManager.TagBindingsClient();
const [binding] = await tagBindingsClient.listTagBindings({
   parent: `//compute.googleapis.com/projects/${projectId}/zones/${zone}/instances/${instanceId}`,
});
console.log('binding :', binding);

Error is : INVALID_ARGUMENT: field [binding.resource] has issue [Must be a valid One Platform resource name of a tag-compatible global resource. Did you forget to specify the correct location?]

Instead temporary fix is to use api with for example axios like this :

import axios from 'axios';
import { GoogleAuth } from 'google-auth-library';

const axiosGcpInstance = axios.create();
axiosGcpInstance.interceptors.request.use(
  async config => {
    config.headers.Authorization = `Bearer ${await getAccessToken()}`;
    return config;
  },
  error => {
    Promise.reject(error);
  },
);

async function getAccessToken(_forceRetry = false) {
  if (token && !_forceRetry) return token;
  console.log('getAccessToken');
  const auth = new GoogleAuth({ scopes: ['https://www.googleapis.com/auth/cloud-platform'] });
  token = await auth.getAccessToken();
  return token;
}

const res = await axiosGcpInstance.get(`https://${zone}-cloudresourcemanager.googleapis.com/v3/tagBindings`, {
     params: {
       parent: `//compute.googleapis.com/projects/${projectId}/zones/${zone}/instances/${instanceId}`,
     },
});

console.log(res.data)

In the library @google-cloud/resource-manager there is no option to specify location (zone or region) like in the API one.

The URL for API is : ${zone}-cloudresourcemanager.googleapis.com/v3/tagBindings But in the library it is only : cloudresourcemanager.googleapis.com

Maybe its related to this line