174 lines
6.0 KiB
TypeScript
174 lines
6.0 KiB
TypeScript
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<plugins.servezoneInterfaces.requests.image.IRequest_CreateImage>(
|
|
'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<plugins.servezoneInterfaces.requests.image.IRequest_GetImage>(
|
|
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<plugins.servezoneInterfaces.requests.image.IRequest_DeleteImage>(
|
|
'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<plugins.servezoneInterfaces.requests.image.IRequest_GetAllImages>(
|
|
'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<plugins.servezoneInterfaces.requests.image.IRequest_PushImageVersion>(
|
|
'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<plugins.servezoneInterfaces.requests.image.IRequest_PullImageVersion>(
|
|
'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,
|
|
});
|
|
}
|
|
}
|