From 7521ca8408e65f2105729fe9cf8b2d183bbe7292 Mon Sep 17 00:00:00 2001 From: Lalji Kanjareeya <46327204+laljikanjareeya@users.noreply.github.com> Date: Fri, 3 Apr 2020 21:56:45 +0530 Subject: [PATCH] feat: Expose getIamPolicy support for project (#302) * feat: expose getIamPolicy for Project Object --- .../src/project.ts | 104 +++++++++++++++++- .../system-test/resource.ts | 9 ++ .../test/project.ts | 51 +++++++++ 3 files changed, 162 insertions(+), 2 deletions(-) diff --git a/packages/google-cloud-resourcemanager/src/project.ts b/packages/google-cloud-resourcemanager/src/project.ts index 5d937c40e12..09cc7138d1c 100644 --- a/packages/google-cloud-resourcemanager/src/project.ts +++ b/packages/google-cloud-resourcemanager/src/project.ts @@ -35,6 +35,41 @@ export interface ProjectCreateCallback { ): void; } +export interface Expression { + expression: string; + title: string; + description: string; + location: string; +} +export interface Binding { + role: string; + members: string[]; + condition: Expression; +} +export interface AuditLogConfig { + logType: string; + exemptedMembers: string[]; +} +export interface AuditConfig { + service: string; + auditLogConfigs: AuditLogConfig[]; +} + +export interface Policy { + bindings: Binding[]; + auditConfigs: AuditConfig[]; + etag: string; + version: number; +} + +export type GetIamPolicyResponse = [Policy]; +export interface GetIamPolicyCallback { + (err: Error | null, policy?: Policy): void; +} +export interface GetIamPolicyOptions { + requestedPolicyVersion: number; +} + /** * A Project object allows you to interact with a Google Cloud Platform project. * @@ -288,6 +323,73 @@ class Project extends ServiceObject { super.create(callback); } + getIamPolicy(options?: GetIamPolicyOptions): Promise; + getIamPolicy(callback: GetIamPolicyCallback): void; + getIamPolicy( + options: GetIamPolicyOptions, + callback: GetIamPolicyCallback + ): void; + /** + * @typedef {array} GetIamPolicyResponse + * @property {Policy} 0 This project's IAM [policy]{@link https://cloud.google.com/resource-manager/reference/rest/Shared.Types/Policy}. + */ + /** + * @callback GetIamPolicyCallback + * @param {?Error} err Request error, if any. + * @param {Policy} policy This project's IAM [policy]{@link https://cloud.google.com/resource-manager/reference/rest/Shared.Types/Policy}. + */ + /** + * Get the IAM policy for this project. + * + * @see [projects: getIamPolicy API Documentation]{@link https://cloud.google.com/resource-manager/reference/rest/v1/projects/getIamPolicy} + * + * @param {GetIamPolicyOptions} [options] Options object to get IAM policy. + * @param {GetIamPolicyCallback} [callback] Callback function. + * @returns {Promise} + * + * @example + * const {Resource} = require('@google-cloud/resource'); + * const resource = new Resource(); + * const project = resource.project('grape-spaceship-123'); + * + * project.getIamPolicy((err, policy) => { + * if (!err) { + * console.log(policy). + * } + * }); + * + * //- + * // If the callback is omitted, we'll return a Promise. + * //- + * project.getIamPolicy().then((data) => { + * const policy = data[0]; + * }); + */ + getIamPolicy( + optionsOrCallback?: GetIamPolicyCallback | GetIamPolicyOptions, + callback?: GetIamPolicyCallback + ): void | Promise { + const options = + typeof optionsOrCallback === 'object' ? optionsOrCallback : {}; + callback = + typeof optionsOrCallback === 'function' ? optionsOrCallback : callback; + + this.request( + { + method: 'POST', + uri: ':getIamPolicy', + body: { + options, + }, + }, + (err, resp) => { + callback!(err, resp); + } + ); + } + + restore(): Promise; + restore(callback: RestoreCallback): void; /** * Restore a project. * @@ -318,8 +420,6 @@ class Project extends ServiceObject { * const apiResponse = data[0]; * }); */ - restore(): Promise; - restore(callback: RestoreCallback): void; restore(callback?: RestoreCallback): void | Promise { callback = callback || util.noop; this.request( diff --git a/packages/google-cloud-resourcemanager/system-test/resource.ts b/packages/google-cloud-resourcemanager/system-test/resource.ts index 0dbf2c3e438..db5079af1f5 100644 --- a/packages/google-cloud-resourcemanager/system-test/resource.ts +++ b/packages/google-cloud-resourcemanager/system-test/resource.ts @@ -57,6 +57,15 @@ describe('Resource', () => { const [metadata] = await project.getMetadata(); assert.notStrictEqual(metadata.projectId, undefined); }); + + it('should get Iam policy', done => { + project.getIamPolicy((err, policy) => { + assert.ifError(err); + assert.notStrictEqual(policy!.etag, undefined); + assert.strictEqual(typeof policy!.version, 'number'); + done(); + }); + }); }); // Auth through the gcloud SDK is required to: diff --git a/packages/google-cloud-resourcemanager/test/project.ts b/packages/google-cloud-resourcemanager/test/project.ts index c408571774e..d30164b940b 100644 --- a/packages/google-cloud-resourcemanager/test/project.ts +++ b/packages/google-cloud-resourcemanager/test/project.ts @@ -25,6 +25,7 @@ import * as promisify from '@google-cloud/promisify'; import * as assert from 'assert'; import {describe, it} from 'mocha'; import * as proxyquire from 'proxyquire'; +import {Policy} from '../src/project'; let promisified = false; const fakePromisify = Object.assign({}, promisify, { @@ -106,6 +107,56 @@ describe('Project', () => { }); }); + describe('getIamPolicy', () => { + const error = new Error('Error.'); + const policy = { + version: 1, + bindings: [ + { + members: ['serviceAccount:fakeemail@project.iam.gserviceaccount.com'], + role: 'roles/appengine.appAdmin', + }, + ], + auditConfigs: [ + { + auditLogConfigs: [ + { + logType: 'ADMIN_READ', + }, + ], + service: 'spanner.googleapis.com', + }, + ], + etag: 'BwWf8AIJOb4=', + }; + + beforeEach(() => { + project.request = ( + reqOpts: DecorateRequestOptions, + callback: Function + ) => { + callback(error, policy); + }; + }); + + it('should make the correct API request', done => { + project.request = (reqOpts: DecorateRequestOptions) => { + assert.strictEqual(reqOpts.method, 'POST'); + assert.strictEqual(reqOpts.uri, ':getIamPolicy'); + done(); + }; + project.getIamPolicy(assert.ifError); + }); + + it('should execute the callback with error & API response', done => { + project.getIamPolicy((err: Error, apiResponse_: Policy) => { + assert.strictEqual(err, error); + assert.strictEqual(apiResponse_, policy); + done(); + }); + }); + }); + describe('restore', () => { const error = new Error('Error.'); const apiResponse = {a: 'b', c: 'd'};