@intuitionrobotics/google-services
Version:
153 lines • 7.34 kB
JavaScript
import { __stringify, BadImplementationException, ImplementationMissingException, Module, ThisShouldNotHappenException, timeout, filterInstances } from "@intuitionrobotics/ts-common";
import { cloudresourcemanager_v1, cloudresourcemanager_v2, serviceusage_v1 } from "googleapis";
import { AuthModule } from "./AuthModule.js";
const Serviceusage = serviceusage_v1.Serviceusage;
const Cloudresourcemanager = cloudresourcemanager_v2.Cloudresourcemanager;
const CloudresourcemanagerV1 = cloudresourcemanager_v1.Cloudresourcemanager;
import { GCPScope, ServiceKey } from "./consts.js";
export class GoogleCloudManager_Class extends Module {
cloudServicesManagerAPI;
cloudResourcesManagerAPI;
cloudResourcesManagerAPIv1;
constructor() {
super("GoogleCloudManager");
this.setDefaultConfig({ scopes: [GCPScope.CloudPlatform] });
}
init() {
this.cloudServicesManagerAPI = new Serviceusage(AuthModule.getAuth(this.config.authKey, this.config.scopes, 'v1'));
this.cloudResourcesManagerAPI = new Cloudresourcemanager(AuthModule.getAuth(this.config.authKey, this.config.scopes));
this.cloudResourcesManagerAPIv1 = new CloudresourcemanagerV1(AuthModule.getAuth(this.config.authKey, this.config.scopes, 'v1'));
}
// FOLDERS
async getOrCreateFolder(parentFolderId, folderName) {
if (parentFolderId === undefined)
throw new BadImplementationException("MUST provide a parentFolderId");
if (folderName === undefined)
throw new BadImplementationException("MUST provide a folderName");
const folders = await this.queryFolders({ parentId: parentFolderId, folderName });
let parentFolder;
if (folders.length > 1)
throw new 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 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 timeout(2000);
const res = await this.cloudResourcesManagerAPI.operations.get({ name });
if (res.data.done)
return res.data.response;
retry--;
}
throw new 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 = 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 timeout(2000);
const res = await this.cloudResourcesManagerAPIv1.operations.get({ name });
if (res.data.done)
return res.data.response;
retry--;
}
throw new 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: ${__stringify(projectIds)}`);
return Promise.all(projectIds.map(projectId => this._enableService(serviceKey, projectId, enable)));
}
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) {
let retry = 5;
while (retry >= 0) {
await timeout(2000);
const res = await this.cloudServicesManagerAPI.operations.get({ name });
if (res.data.done)
return res.data.response?.service;
retry--;
}
throw new 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";
}
}
export const GoogleCloudManager = new GoogleCloudManager_Class();
//# sourceMappingURL=GoogleCloudModule.js.map