@nu-art/google-services
Version:
google-services
177 lines (176 loc) • 8.36 kB
JavaScript
"use strict";
/*
* Permissions management system, define access level for each of
* your server apis, and restrict users by giving them access levels
*
* Copyright (C) 2020 Adam van der Kruk aka TacB0sS
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModuleBE_GcpManager = exports.ModuleBE_GcpManager_Class = void 0;
/**
* Created by tacb0ss on 07/05/2018.
*/
const ts_common_1 = require("@nu-art/ts-common");
const googleapis_1 = require("googleapis");
const ModuleBE_Auth_1 = require("./ModuleBE_Auth");
var Serviceusage = googleapis_1.serviceusage_v1.Serviceusage;
var Cloudresourcemanager = googleapis_1.cloudresourcemanager_v2.Cloudresourcemanager;
var CloudresourcemanagerV1 = googleapis_1.cloudresourcemanager_v1.Cloudresourcemanager;
const consts_1 = require("./consts");
class ModuleBE_GcpManager_Class extends ts_common_1.Module {
constructor() {
super();
this.setDefaultConfig({ scopes: [consts_1.GCPScope.CloudPlatform] });
}
init() {
this.cloudServicesManagerAPI = new Serviceusage(ModuleBE_Auth_1.ModuleBE_Auth.getAuth(this.config.authKey, this.config.scopes, 'v1'));
this.cloudResourcesManagerAPI = new Cloudresourcemanager(ModuleBE_Auth_1.ModuleBE_Auth.getAuth(this.config.authKey, this.config.scopes));
this.cloudResourcesManagerAPIv1 = new CloudresourcemanagerV1(ModuleBE_Auth_1.ModuleBE_Auth.getAuth(this.config.authKey, this.config.scopes, 'v1'));
}
// FOLDERS
async getOrCreateFolder(parentFolderId, folderName) {
if (parentFolderId === undefined)
throw new ts_common_1.BadImplementationException("MUST provide a parentFolderId");
if (folderName === undefined)
throw new ts_common_1.BadImplementationException("MUST provide a folderName");
const folders = await this.queryFolders({ parentId: parentFolderId, folderName });
let parentFolder;
if (folders.length > 1)
throw new ts_common_1.ThisShouldNotHappenException("too many folders for query...");
else if (folders.length === 1)
parentFolder = folders[0];
else
parentFolder = await this.createFolder({ parentId: parentFolderId, folderName });
if (!parentFolder)
throw new ts_common_1.BadImplementationException("MUST be parentFolder");
return this.getFolderId(parentFolder);
}
async createFolder(_request) {
const request = {
parent: `folders/${_request.parentId}`,
requestBody: {
displayName: _request.folderName
}
};
this.logInfo(`Creating GCP folder "${_request.parentId}/${_request.folderName}"`);
const res = await this.cloudResourcesManagerAPI.folders.create(request);
return await this._waitForFolderOperation(res.data.name);
}
async queryFolders(_query) {
const query = { query: `parent=folders/${_query.parentId} AND displayName=${_query.folderName}` };
const res = await this.cloudResourcesManagerAPI.folders.search({ requestBody: query });
return res.data.folders || [];
}
getFolderId(folder) {
return folder.name.replace("folders/", "");
}
async _waitForFolderOperation(name) {
let retry = 5;
while (retry >= 0) {
await (0, ts_common_1.timeout)(2000);
const res = await this.cloudResourcesManagerAPI.operations.get({ name });
if (res.data.done)
return res.data.response;
retry--;
}
throw new ts_common_1.ImplementationMissingException("need better handling here..");
}
// PROJECTS
async listProjects(filter = () => true) {
const results = await this.cloudResourcesManagerAPIv1.projects.list();
const projects = results.data.projects || [];
return projects.filter(filter);
}
async getOrCreateProjects(parentId, ...projects) {
const existingProjects = await this.listProjects(gcproject => !!projects.find(project => project.name === gcproject.name));
const projectsToCreate = projects
.filter((project) => !existingProjects.find((gcproject) => gcproject.name === project.name));
const newProjects = await Promise.all(projectsToCreate.map(project => this.createProject(parentId, project.projectId, project.name)));
const allProjects = (0, ts_common_1.filterInstances)([...existingProjects, ...newProjects]);
return projects.map(project => allProjects.find(gcpProject => gcpProject.name === project.name));
}
async createProject(parentId, projectId, name = projectId) {
const options = {
projectId,
name,
parent: {
type: "folder",
id: parentId
}
};
this.logInfo(`Creating GCP Project "${parentId}/${projectId}/${name}"`);
const response = await this.cloudResourcesManagerAPIv1.projects.create({ requestBody: options });
return this._waitForProjectOperation(response.data.name);
}
async _waitForProjectOperation(name) {
let retry = 5;
while (retry >= 0) {
await (0, ts_common_1.timeout)(2000);
const res = await this.cloudResourcesManagerAPIv1.operations.get({ name });
if (res.data.done)
return res.data.response;
retry--;
}
throw new ts_common_1.ImplementationMissingException("need better handling here..");
}
// SERVICES
async getService(serviceKey, projectId) {
const res = await this.cloudServicesManagerAPI.services.get({ name: `projects/${projectId}/services/${serviceKey}` });
return res.data;
}
async enableService(serviceKey, enable, ...projectIds) {
this.logInfo(`Enabling Service "${serviceKey}" for projects: ${(0, ts_common_1.__stringify)(projectIds)}`);
return Promise.all(projectIds.map(projectId => this._enableService(serviceKey, projectId, enable)));
}
// @ts-ignore
async _enableService(serviceKey, projectId, enable = true) {
let service = await this.getService(serviceKey, projectId);
if (this._isEnabled(service) === enable)
return this.logVerbose(`Service "${serviceKey}" was already enabled for project: ${projectId}`);
const name = service.name;
let res;
if (enable)
res = await this.cloudServicesManagerAPI.services.enable({ name });
else
res = await this.cloudServicesManagerAPI.services.disable({ name });
service = await this._waitForServiceOperation(res.data.name);
if (this._isEnabled(service))
this.logVerbose(`Service "${serviceKey}" is now enabled for project: ${projectId}`);
else
this.logError(`Service "${serviceKey}" is now disabled for project: ${projectId}`);
return service;
}
async _waitForServiceOperation(name) {
var _a;
let retry = 5;
while (retry >= 0) {
await (0, ts_common_1.timeout)(2000);
const res = await this.cloudServicesManagerAPI.operations.get({ name });
if (res.data.done)
return (_a = res.data.response) === null || _a === void 0 ? void 0 : _a.service;
retry--;
}
throw new ts_common_1.ImplementationMissingException("need better handling here..");
}
async isEnabled(serviceKey, projectId) {
const service = await this.getService(serviceKey, projectId);
return this._isEnabled(service);
}
_isEnabled(service) {
return service.state === "ENABLED";
}
}
exports.ModuleBE_GcpManager_Class = ModuleBE_GcpManager_Class;
exports.ModuleBE_GcpManager = new ModuleBE_GcpManager_Class();