Skip to content

Commit ea0b98d

Browse files
authored
generate tgz layer
1 parent 2d73709 commit ea0b98d

File tree

3 files changed

+80
-34
lines changed

3 files changed

+80
-34
lines changed

src/spec-configuration/containerFeaturesOCI.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import * as path from 'path';
22
import * as tar from 'tar';
3+
import * as fs from 'fs';
4+
import * as crypto from 'crypto';
35
import { request } from '../spec-utils/httpRequest';
46
import { Log, LogLevel } from '../spec-utils/log';
5-
import { mkdirpLocal, writeLocalFile } from '../spec-utils/pfs';
7+
import { isLocalFile, mkdirpLocal, writeLocalFile } from '../spec-utils/pfs';
68
import { FeatureSet } from './containerFeaturesConfiguration';
79

810
export interface OCIFeatureRef {
@@ -217,4 +219,32 @@ export async function getGHCRtoken(output: Log, id: string) {
217219
const token = JSON.parse((await request(options, output)).toString()).token;
218220

219221
return token;
222+
}
223+
224+
// -- Push
225+
226+
export async function createManifest(output: Log, pathToTgz: string): Promise<OCIManifest | undefined> {
227+
228+
/*const tgzLayer = */calculateTgzLayer(output, pathToTgz);
229+
return undefined;
230+
}
231+
232+
export async function calculateTgzLayer(output: Log, pathToTgz: string): Promise<{ digest: string; size: number; mediaType: string } | undefined> {
233+
output.write(`Creating manifest from ${pathToTgz}`, LogLevel.Trace);
234+
if (!(await isLocalFile(pathToTgz))) {
235+
output.write(`${pathToTgz} does not exist.`, LogLevel.Error);
236+
return undefined;
237+
}
238+
239+
const tarBytes = fs.readFileSync(pathToTgz);
240+
241+
242+
const tarSha256 = crypto.createHash('sha256').update(tarBytes).digest('hex');
243+
output.write(`${pathToTgz}: sha256:${tarSha256} (size: ${tarBytes.byteLength})`, LogLevel.Trace);
244+
245+
return {
246+
digest: `sha256:${tarSha256}`,
247+
size: tarBytes.byteLength,
248+
mediaType: 'application/octet-stream'
249+
};
220250
}
15.5 KB
Binary file not shown.
Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,64 @@
1+
// import { assert } from 'chai';
2+
// import { getFeatureManifest, getFeatureBlob, getFeatureRef, createManifest } from '../../spec-configuration/containerFeaturesOCI';
13
import { assert } from 'chai';
2-
import { getFeatureManifest, getFeatureBlob, getFeatureRef } from '../../spec-configuration/containerFeaturesOCI';
4+
import { calculateTgzLayer } from '../../spec-configuration/containerFeaturesOCI';
35
import { createPlainLog, LogLevel, makeLog } from '../../spec-utils/log';
46

57
export const output = makeLog(createPlainLog(text => process.stdout.write(text), () => LogLevel.Trace));
8+
const testAssetsDir = `${__dirname}/assets`;
69

7-
describe('Test OCI', () => {
10+
// describe('Test OCI Pull', () => {
811

9-
it('Parse OCI identifier', async () => {
10-
const feat = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
11-
output.write(`feat: ${JSON.stringify(feat)}`);
12+
// it('Parse OCI identifier', async () => {
13+
// const feat = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
14+
// output.write(`feat: ${JSON.stringify(feat)}`);
1215

13-
assert.equal(feat.id, 'ghcr.io/codspace/features/ruby');
14-
assert.equal(feat.featureName, 'ruby');
15-
assert.equal(feat.owner, 'codspace');
16-
assert.equal(feat.namespace, 'codspace/features');
17-
assert.equal(feat.registry, 'ghcr.io');
18-
assert.equal(feat.version, '1');
19-
});
16+
// assert.equal(feat.id, 'ghcr.io/codspace/features/ruby');
17+
// assert.equal(feat.featureName, 'ruby');
18+
// assert.equal(feat.owner, 'codspace');
19+
// assert.equal(feat.namespace, 'codspace/features');
20+
// assert.equal(feat.registry, 'ghcr.io');
21+
// assert.equal(feat.version, '1');
22+
// });
2023

21-
it('Get a manifest.', async () => {
22-
const featureRef = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
23-
const manifest = await getFeatureManifest(output, process.env, 'https://ghcr.io/v2/codspace/features/ruby/manifests/1', featureRef);
24-
assert.isNotNull(manifest);
25-
assert.exists(manifest);
24+
// it('Get a manifest.', async () => {
25+
// const featureRef = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
26+
// const manifest = await getFeatureManifest(output, process.env, 'https://ghcr.io/v2/codspace/features/ruby/manifests/1', featureRef);
27+
// assert.isNotNull(manifest);
28+
// assert.exists(manifest);
2629

27-
if (!manifest) {
28-
return;
29-
}
30+
// if (!manifest) {
31+
// return;
32+
// }
3033

31-
output.write(`mediaType: ${manifest.mediaType}`);
32-
manifest.layers.forEach(layer => {
33-
output.write(`Layer mediaType: ${layer.mediaType}`);
34-
output.write(`Layer digest: ${layer.digest}`);
35-
output.write(`Layer size: ${layer.size}`);
34+
// output.write(`mediaType: ${manifest.mediaType}`);
35+
// manifest.layers.forEach(layer => {
36+
// output.write(`Layer mediaType: ${layer.mediaType}`);
37+
// output.write(`Layer digest: ${layer.digest}`);
38+
// output.write(`Layer size: ${layer.size}`);
3639

37-
output.write(`Layer imageTitle: ${layer.annotations['org.opencontainers.image.title']}`);
38-
});
40+
// output.write(`Layer imageTitle: ${layer.annotations['org.opencontainers.image.title']}`);
41+
// });
3942

40-
assert.equal(manifest.layers[0].digest, 'sha256:c33008d0dc12d0e631734082401bec692da809eae2ac51e24f58c1cac68fc0c9');
41-
});
43+
// assert.equal(manifest.layers[0].digest, 'sha256:c33008d0dc12d0e631734082401bec692da809eae2ac51e24f58c1cac68fc0c9');
44+
// });
45+
46+
// it('Download a feature', async () => {
47+
// const featureRef = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
48+
// const result = await getFeatureBlob(output, process.env, 'https://ghcr.io/v2/codspace/features/ruby/blobs/sha256:c33008d0dc12d0e631734082401bec692da809eae2ac51e24f58c1cac68fc0c9', '/tmp', '/tmp/featureTest', featureRef);
49+
// assert.isTrue(result);
50+
// });
51+
// });
52+
53+
describe('Test OCI Push', () => {
4254

43-
it('Download a feature', async () => {
44-
const featureRef = getFeatureRef(output, 'ghcr.io/codspace/features/ruby:1');
45-
const result = await getFeatureBlob(output, process.env, 'https://ghcr.io/v2/codspace/features/ruby/blobs/sha256:c33008d0dc12d0e631734082401bec692da809eae2ac51e24f58c1cac68fc0c9', '/tmp', '/tmp/featureTest', featureRef);
46-
assert.isTrue(result);
55+
it('Generates the correct tgz manifest layer', async () => {
56+
const res = await calculateTgzLayer(output, `${testAssetsDir}/go.tgz`);
57+
const expected = {
58+
digest: 'sha256:b2006e7647191f7b47222ae48df049c6e21a4c5a04acfad0c4ef614d819de4c5',
59+
mediaType: 'application/octet-stream',
60+
size: 15872
61+
};
62+
assert.deepEqual(res, expected);
4763
});
4864
});

0 commit comments

Comments
 (0)