import type { Cloudly } from '../classes.cloudly.js'; import * as plugins from '../plugins.js'; import * as paths from '../paths.js'; import { Image } from './classes.image.js'; export class ImageManager { cloudlyRef: Cloudly; public typedrouter = new plugins.typedrequest.TypedRouter(); public smartbucketInstance: plugins.smartbucket.SmartBucket; public imageDir: plugins.smartbucket.Directory; public dockerImageStore: plugins.docker.DockerImageStore; get db() { return this.cloudlyRef.mongodbConnector.smartdataDb; } public CImage = plugins.smartdata.setDefaultManagerForDoc(this, Image); constructor(cloudlyRefArg: Cloudly) { this.cloudlyRef = cloudlyRefArg; this.cloudlyRef.typedrouter.addTypedRouter(this.typedrouter); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'createImage', async (reqArg, toolsArg) => { await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg); const image = await this.CImage.create({ name: reqArg.name, description: reqArg.description, versions: [], }); return { image: await image.createSavableObject(), }; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler('getImage', async (reqArg, toolsArg) => { await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg); const image = await this.CImage.getInstance({ id: reqArg.imageId, }); return { image: await image.createSavableObject(), }; }) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'deleteImage', async (reqArg, toolsArg) => { await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], reqArg); const image = await this.CImage.getInstance({ id: reqArg.imageId, }); await image.delete(); return {}; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'getAllImages', async (requestArg, toolsArg) => { await toolsArg.passGuards([this.cloudlyRef.authManager.adminIdentityGuard], requestArg); const images = await this.CImage.getInstances({}); return { images: await Promise.all( images.map((image) => { return image.createSavableObject(); }) ), }; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'pushImageVersion', async (reqArg, toolsArg) => { await plugins.smartguard.passGuardsOrReject(reqArg, [ this.cloudlyRef.authManager.validIdentityGuard, ]); const refImage = await this.CImage.getInstance({ id: reqArg.imageId, }); if (!refImage) { throw new plugins.typedrequest.TypedResponseError('Image not found'); } const imageVersion = reqArg.versionString; console.log( `got request to push image version ${imageVersion} for image ${refImage.data.name}` ); const imagePushStream = reqArg.imageStream; (async () => { const smartWebDuplex = new plugins.smartstream.webstream.WebDuplexStream< Uint8Array, Uint8Array >({ writeFunction: async (chunkArg, toolsArg) => { console.log(chunkArg); return chunkArg; }, }); imagePushStream.writeToWebstream(smartWebDuplex.writable); await this.dockerImageStore.storeImage(refImage.id, plugins.smartstream.SmartDuplex.fromWebReadableStream(smartWebDuplex.readable)); })(); return { allowed: true, }; } ) ); this.typedrouter.addTypedHandler( new plugins.typedrequest.TypedHandler( 'pullImageVersion', async (reqArg) => { const image = await this.CImage.getInstance({ id: reqArg.imageId, }); const imageVersion = image.data.versions.find( (version) => version.versionString === reqArg.versionString ); const readable = this.imageDir.fastGetStream( { path: await image.getStoragePath(reqArg.versionString), }, 'webstream' ); const imageVirtualStream = new plugins.typedrequest.VirtualStream(); return { imageStream: imageVirtualStream, }; } ) ); } public async start() { // lets setup s3 const s3Descriptor: plugins.tsclass.storage.IS3Descriptor = await this.cloudlyRef.config.appData.waitForAndGetKey('s3Descriptor'); console.log(this.cloudlyRef.config.data.s3Descriptor); this.smartbucketInstance = new plugins.smartbucket.SmartBucket( this.cloudlyRef.config.data.s3Descriptor ); const bucket = await this.smartbucketInstance.getBucketByName('cloudly-test'); await bucket.fastPut({ path: 'images/00init', contents: 'init' }); this.imageDir = await bucket.getDirectoryFromPath({ path: '/images', }); // lets setup dockerstore await plugins.smartfile.fs.ensureDir(paths.dockerImageStoreDir); this.dockerImageStore = new plugins.docker.DockerImageStore({ localDirPath: paths.dockerImageStoreDir, bucketDir: this.imageDir, }); } }