Add some hacky prototype express work to return a modified hello-world container
Figured some things out, but was mostly just piecing things together by hacking on responses
This commit is contained in:
parent
312625e4b0
commit
d4fe010f13
|
@ -1 +1,2 @@
|
|||
*.sw*
|
||||
node_modules/
|
||||
|
|
|
@ -0,0 +1,221 @@
|
|||
const crypto = require('crypto');
|
||||
const express = require('express');
|
||||
const fs = require('fs');
|
||||
const request = require('request');
|
||||
const winston = require('winston');
|
||||
|
||||
const {chain} = require('stream-chain');
|
||||
const {parser} = require('stream-json');
|
||||
const {streamValues} = require('stream-json/streamers/StreamValues');
|
||||
|
||||
const app = express();
|
||||
const port = 9090;
|
||||
const imageConfig = 'sha256:b0b17eacf99071d7178bbf12d31a556bb3f05b429564c7fc4db33899d3eda85b';
|
||||
|
||||
let alpineResponse = {
|
||||
"manifests": [
|
||||
{
|
||||
"digest": "sha256:acd3ca9941a85e8ed16515bfc5328e4e2f8c128caa72959a58a127b7801ee01f",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "amd64",
|
||||
"os": "linux"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:0489474da8ea22426ece86ace6c1c0026ab2fd3cdfbbd62b7e94650266c37d9a",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "arm",
|
||||
"os": "linux",
|
||||
"variant": "v6"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:1316a4e4b2361242457f4136cc409c38e8a48ffda76e4e1be31896006e5fc4a2",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "arm",
|
||||
"os": "linux",
|
||||
"variant": "v7"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:db7f3dcef3d586f7dd123f107c93d7911515a5991c4b9e51fa2a43e46335a43e",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"os": "linux",
|
||||
"variant": "v8"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:499416c8a5bcb311d75e12fb4667886e32b43aaf11003be2a334cbe265e81ce4",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "386",
|
||||
"os": "linux"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:5abbfe2915ad8c466bf6c9f33d03622cde0298c36cd88f55d16a3aa3d9c2c35e",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "ppc64le",
|
||||
"os": "linux"
|
||||
},
|
||||
"size": 528
|
||||
},
|
||||
{
|
||||
"digest": "sha256:43955d6857268cc948ae9b370b221091057de83c4962da0826f9a2bdc9bd6b44",
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"platform": {
|
||||
"architecture": "s390x",
|
||||
"os": "linux"
|
||||
},
|
||||
"size": 528
|
||||
}
|
||||
],
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.list.v2+json",
|
||||
"schemaVersion": 2
|
||||
}
|
||||
|
||||
let alpineImage = {
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"config": {
|
||||
"mediaType": "application/vnd.docker.container.image.v1+json",
|
||||
"size": 1512,
|
||||
"digest": "sha256:961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4"
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 2789669,
|
||||
"digest": "sha256:9d48c3bd43c520dc2784e868a780e976b207cbf493eaff8c6596eb871cbd9609"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
let response = {
|
||||
"schemaVersion": 2,
|
||||
"mediaType": "application/vnd.docker.distribution.manifest.v2+json",
|
||||
"config": {
|
||||
"mediaType": "application/vnd.docker.container.image.v1+json",
|
||||
"size": 1585,
|
||||
"digest": imageConfig,
|
||||
},
|
||||
"layers": [
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 977,
|
||||
"digest": "sha256:1b930d010525941c1d56ec53b97bd057a67ae1865eebf042686d2a2d18271ced"
|
||||
},
|
||||
{
|
||||
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||
"size": 5808040,
|
||||
"digest": "sha256:cf98438b1781c2be1fde41967959140379c715b75a85723501d0bca82f215a76"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* The specific manifests route we must override
|
||||
*/
|
||||
app.get('/v2/:org/:image/manifests/:digest', (req, res) => {
|
||||
console.log(req.originalUrl);
|
||||
const checksum = crypto.createHash('sha256').update(JSON.stringify(response), 'utf8').digest('hex');
|
||||
res.set('Docker-Content-Digest', `sha256:${checksum}`);
|
||||
|
||||
/*
|
||||
* If we don't explicitly set the content type here, the client will think
|
||||
* that we're sending back a v1 manifest schema and complain about a "missing
|
||||
* signature key"
|
||||
*/
|
||||
res.set('Content-Type', 'application/vnd.docker.distribution.manifest.v2+json');
|
||||
res.send(response);
|
||||
});
|
||||
|
||||
/*
|
||||
* Serve up a custom blob if we've got one!
|
||||
*/
|
||||
app.get('/v2/:org/:image/blobs/:sha', (req, res) => {
|
||||
console.log(`Hitting ${req.originalUrl}`);
|
||||
|
||||
if (req.params.sha == 'sha256:cf98438b1781c2be1fde41967959140379c715b75a85723501d0bca82f215a76') {
|
||||
/*
|
||||
* Requesting our custom blob layer itself
|
||||
*/
|
||||
const filename = 'layer.tar.gz';
|
||||
console.log('hitting our custom blob');
|
||||
fs.createReadStream(filename).pipe(res);
|
||||
} else if (req.params.sha == imageConfig) {
|
||||
/*
|
||||
* Requesting our image configuration
|
||||
*/
|
||||
console.log('hitting our image configuration')
|
||||
let image = '';
|
||||
/*
|
||||
* We need to modify the diff_ids of the image configuration to include the
|
||||
* checksum of the gunzipped version of our custom layer
|
||||
*
|
||||
* https://medium.com/@saschagrunert/demystifying-containers-part-iii-container-images-244865de6fef
|
||||
*
|
||||
*/
|
||||
|
||||
const upstreamBlob = 'sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e'
|
||||
request({
|
||||
url: `https://registry-1.docker.io/v2/library/hello-world/blobs/${upstreamBlob}`,
|
||||
method: req.method,
|
||||
headers: {
|
||||
'Authorization' : req.get('Authorization'),
|
||||
},
|
||||
})
|
||||
.on('response', (response) => {
|
||||
console.log(`Hitting upstream gave a ${response.statusCode}`);
|
||||
})
|
||||
.on('data', (chunk) => {
|
||||
image += chunk;
|
||||
})
|
||||
.on('end', () => {
|
||||
image = JSON.parse(image);
|
||||
image.rootfs.diff_ids.push(
|
||||
'sha256:5f9da7cc9d8d83c96245ac27854466f6ed89fbfade5dd8a4f307861bfb72d1b8',
|
||||
);
|
||||
console.log(image.rootfs);
|
||||
const checksum = crypto.createHash('sha256').update(JSON.stringify(image), 'utf8').digest('hex');
|
||||
console.log(JSON.stringify(image));
|
||||
console.log(`Sending content with a checksum of ${checksum}`);
|
||||
console.log(`Client is expecting ${req.params.sha}`);
|
||||
res.send(image);
|
||||
});
|
||||
} else {
|
||||
console.log(`Piping blob upstream for ${req.originalUrl}`);
|
||||
request({
|
||||
url: `https://registry-1.docker.io${req.originalUrl}`,
|
||||
method: req.method,
|
||||
headers: {
|
||||
'Authorization' : req.get('Authorization'),
|
||||
},
|
||||
}).pipe(res);
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* Pass all v2 API requests on to the upstream Docker registry
|
||||
*/
|
||||
app.get('/v2/*', (req, res) => {
|
||||
console.log(`Piping request through for ${req.originalUrl}`);
|
||||
request({
|
||||
url: `https://registry-1.docker.io${req.originalUrl}`,
|
||||
method: req.method,
|
||||
}).pipe(res);
|
||||
});
|
||||
|
||||
app.listen(port, () => console.log(`Example app listening on port ${port}!`))
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue