Files
cloudly/test/test.registrycleanup.node.ts
T

87 lines
3.6 KiB
TypeScript
Raw Normal View History

import { tap, expect } from '@git.zone/tstest/tapbundle';
import { CloudlyRegistryManager } from '../ts/manager.registry/classes.registrymanager.js';
const digest = (fillArg: string): string => `sha256:${fillArg.repeat(64)}`;
class FakeRegistryStorage {
public objects = new Map<string, Buffer>();
public async getObject(pathArg: string): Promise<Buffer | null> {
return this.objects.get(pathArg) || null;
}
public async putObject(pathArg: string, dataArg: Buffer): Promise<void> {
this.objects.set(pathArg, dataArg);
}
public async deleteObject(pathArg: string): Promise<void> {
this.objects.delete(pathArg);
}
public async objectExists(pathArg: string): Promise<boolean> {
return this.objects.has(pathArg);
}
public async listObjects(prefixArg: string): Promise<string[]> {
return Array.from(this.objects.keys()).filter((pathArg) => pathArg.startsWith(prefixArg));
}
public async getOciManifest(repositoryArg: string, digestArg: string): Promise<Buffer | null> {
return this.getObject(`oci/manifests/${repositoryArg}/${digestArg.slice('sha256:'.length)}`);
}
}
const putJson = (storageArg: FakeRegistryStorage, pathArg: string, dataArg: unknown): void => {
storageArg.objects.set(pathArg, Buffer.from(JSON.stringify(dataArg)));
};
tap.test('should delete Cloudly service-owned OCI repository without deleting shared blobs', async () => {
const storage = new FakeRegistryStorage();
const manager = Object.create(CloudlyRegistryManager.prototype) as any;
const service = {
id: 'service-1',
data: {
registryTarget: { repository: 'workloads/ghost-service-1' },
},
};
manager.started = true;
manager.smartRegistry = { getStorage: () => storage };
manager.recordedTagDigests = new Map([
['workloads/ghost-service-1:latest', digest('a')],
]);
manager.cloudlyRef = {
serviceManager: {
CService: { getInstances: async () => [service] },
},
};
const targetDigest = digest('a');
const otherDigest = digest('b');
const sharedLayerDigest = digest('c');
const targetOnlyLayerDigest = digest('d');
const otherOnlyLayerDigest = digest('e');
putJson(storage, 'oci/tags/workloads/ghost-service-1/tags.json', { latest: targetDigest });
putJson(storage, 'oci/tags/workloads/other-service/tags.json', { latest: otherDigest });
putJson(storage, `oci/manifests/workloads/ghost-service-1/${targetDigest.slice('sha256:'.length)}`, {
layers: [{ digest: sharedLayerDigest }, { digest: targetOnlyLayerDigest }],
});
putJson(storage, `oci/manifests/workloads/other-service/${otherDigest.slice('sha256:'.length)}`, {
layers: [{ digest: sharedLayerDigest }, { digest: otherOnlyLayerDigest }],
});
for (const blobDigest of [sharedLayerDigest, targetOnlyLayerDigest, otherOnlyLayerDigest]) {
storage.objects.set(`oci/blobs/sha256/${blobDigest.slice('sha256:'.length)}`, Buffer.from(blobDigest));
}
await manager.deleteServiceRepository(service);
expect(storage.objects.has('oci/tags/workloads/ghost-service-1/tags.json')).toBeFalse();
expect(storage.objects.has(`oci/manifests/workloads/ghost-service-1/${targetDigest.slice('sha256:'.length)}`)).toBeFalse();
expect(storage.objects.has(`oci/blobs/sha256/${targetOnlyLayerDigest.slice('sha256:'.length)}`)).toBeFalse();
expect(storage.objects.has(`oci/blobs/sha256/${sharedLayerDigest.slice('sha256:'.length)}`)).toBeTrue();
expect(storage.objects.has(`oci/blobs/sha256/${otherOnlyLayerDigest.slice('sha256:'.length)}`)).toBeTrue();
expect(manager.recordedTagDigests.has('workloads/ghost-service-1:latest')).toBeFalse();
});
export default tap.start();