UNPKG

terrac

Version:

A minimal private module registry for Terraform and OpenTofu

116 lines (115 loc) 4.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BackendGCP = exports.configSchemaGCP = void 0; const shared_1 = require("./shared"); const errors_1 = require("../errors"); const storage_1 = require("@google-cloud/storage"); const lodash_1 = require("lodash"); const Joi = require("joi"); exports.configSchemaGCP = Joi.object({ type: Joi.string().allow('gcp').required().description('Backend type'), bucket: Joi.string().required().description('Bucket name'), projectId: Joi.string().required().description('Google Cloud project ID for the bucket'), pathPrefix: Joi.string().optional().allow('').description('Object path prefix'), }); class BackendGCP { constructor(config) { this.config = config; this.apiEndpoint = process.env.TERRAC_BACKEND_GCP_API_ENDPOINT || 'https://www.googleapis.com'; this.client = new storage_1.Storage({ apiEndpoint: process.env.TERRAC_BACKEND_GCP_API_ENDPOINT, projectId: this.config.projectId, }); } async upload(name, version, packagePath) { await this.uploadFile(this.getPackagePath(name, version), packagePath); } async getSourceUrl(name, version) { let targetVersion = version; if (!targetVersion) { const meta = await this.getMeta(name); targetVersion = meta.version; } const path = this.getPackagePath(name, targetVersion); if (!this.pathExists(path)) { throw new errors_1.ModuleNotFoundError(); } return `gcs::${this.apiEndpoint}/storage/v1/${this.config.bucket}/${path}`; } async list(name) { const moduleList = []; const prefix = this.config.pathPrefix || ''; if (name) { if (!(await this.pathExists(this.getMetaPath(name)))) { throw new errors_1.ModuleNotFoundError(); } const meta = await this.getMeta(name); for (const release of meta.releases) { moduleList.push({ name, version: release.version, }); } } else { const keys = await this.listPaths(prefix); const names = (0, lodash_1.uniq)(keys.map(key => key.replace(prefix, '').split('/').shift())); for (const name of names) { moduleList.push({ name, }); } } return moduleList; } async exists(name, version) { const path = version ? this.getPackagePath(name, version) : this.getMetaPath(name); return this.pathExists(path); } async getMeta(name) { const bucket = this.config.bucket; const path = this.getMetaPath(name); if (await this.pathExists(path)) { const result = await this.client.bucket(bucket).file(path).download(); return JSON.parse(result[0].toString()); } return (0, shared_1.getNewMeta)(name); } async saveMeta(meta) { const metaKey = this.getMetaPath(meta.name); await this.uploadObject(metaKey, JSON.stringify(meta)); } async uploadFile(path, localFilePath) { await this.client .bucket(this.config.bucket) .upload(localFilePath, { destination: path, }); } async uploadObject(path, data) { await this.client .bucket(this.config.bucket) .file(path) .save(data); } async pathExists(path) { const result = await this.client.bucket(this.config.bucket).file(path).exists(); return result[0]; } async listPaths(prefix) { const options = { prefix }; const [files] = await this.client.bucket(this.config.bucket).getFiles(options); return files.map(file => file.name); } getMetaPath(name) { const basePath = `${name}/meta.json`; return this.config.pathPrefix ? `${this.config.pathPrefix}${basePath}` : basePath; } getPackagePath(name, version) { var _a; const basePath = `${name}/${version}/module.zip`; const pathPrefix = (_a = this.config.pathPrefix) !== null && _a !== void 0 ? _a : ''; return `${pathPrefix}${basePath}`; } } exports.BackendGCP = BackendGCP;