UNPKG

@nu-art/google-services

Version:
177 lines (176 loc) 8.36 kB
"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();