diff --git a/lib/docker-json-client.js b/lib/docker-json-client.js index 73dc88d..94a2c15 100644 --- a/lib/docker-json-client.js +++ b/lib/docker-json-client.js @@ -80,8 +80,12 @@ DockerJsonClient.prototype.write = function write(options, body, callback) { return (this._super.write.call(this, options, resBody, callback)); }; +DockerJsonClient.prototype.parse2 = function parse2(err, req, res, callback) { + if (!callback && req instanceof Function) { + callback = req; + req = undefined; + } -DockerJsonClient.prototype.parse = function parse(req, callback) { function parseResponse(err, res) { var chunks = []; // gunzipped response chunks (Buffer objects) var len = 0; // accumulated count of chunk lengths @@ -171,7 +175,6 @@ DockerJsonClient.prototype.parse = function parse(req, callback) { callback(resErr, req, res, obj, body); } - if (!res) { // Early out if we didn't even get a response. callback(resErr, req); @@ -210,10 +213,24 @@ DockerJsonClient.prototype.parse = function parse(req, callback) { }); } - return (parseResponse); -}; + return parseResponse(err, res); +} +DockerJsonClient.prototype.parse = function parse(err, req, res, callback) { + if (!callback && req instanceof Function) { + callback = req; + req = undefined; + } + + return this.parse2(err, req, res, function parse2Callback(resErr, req, res, obj, body) { + if (obj) { + callback(resErr, obj); + } else { + callback(resErr, res, obj, body); + } + }); +} // --- Exports diff --git a/lib/registry-client-v2.js b/lib/registry-client-v2.js index 18bf4ca..4f63ec9 100644 --- a/lib/registry-client-v2.js +++ b/lib/registry-client-v2.js @@ -1602,8 +1602,7 @@ function _makeJsonRequest(opts, cb) { return; } // Parse the response body using the JSON client parser. - var parseFn = DockerJsonClient.prototype.parse.call(self._api, req, cb); - parseFn(err, res); + DockerJsonClient.prototype.parse2.call(self._api, err, req, res, cb); // Release the bulls! res.resume(); }); diff --git a/package.json b/package.json index 8b04fef..317e8cb 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "bunyan": "1.x >=1.3.3", "jws": "3.1.0", "jwk-to-pem": "1.2.0", - "restify-clients": "^1.4.0", + "restify-clients": "^4.0.0", "restify-errors": "^3.0.0", "strsplit": "1.x", "tough-cookie": "2.0.x", diff --git a/test/v1.dockerio.test.js b/test/v1.dockerio.test.js deleted file mode 100644 index ba89fba..0000000 --- a/test/v1.dockerio.test.js +++ /dev/null @@ -1,145 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* - * Copyright (c) 2015, Joyent, Inc. - */ - -var test = require('tape'); - -var drc = require('..'); - - -// --- globals - -var log = require('./lib/log'); - - -// --- Tests - -test('v1 docker.io', function (tt) { - var client; - - tt.test(' createClient', function (t) { - client = drc.createClientV1({ - name: 'alpine', - log: log - }); - t.ok(client); - t.equal(client.version, 1); - t.end(); - }); - - tt.test(' ping', function (t) { - client.ping(function (err, status, res) { - t.ifErr(err); - t.equal(status, true); - t.end(); - }); - }); - - tt.test(' search', function (t) { - client.search({term: 'busy'}, function (err, results, res) { - t.ifErr(err); - t.ok(results); - t.ok(results.num_pages); - t.ok(results.num_results); - var busybox = results.results.filter( - function (r) { return r.name === 'busybox'; })[0]; - t.ok(busybox); - t.ok(busybox.is_official); - t.end(); - }); - }); - - tt.test(' listRepoImgs', function (t) { - client.listRepoImgs(function (err, imgs) { - t.ifErr(err); - t.ok(Array.isArray(imgs)); - if (imgs.length > 0) { - t.ok(/[0-9a-f]{64}/.test(imgs[0].id)); - } - t.end(); - }); - }); - - // Note: 'latest' is no longer available in docker.io, use '2.7' which is - // still available and in the v1 registry format. - var tag = '2.7'; - var repoTags; - - tt.test(' listRepoTags', function (t) { - client.listRepoTags(function (err, repoTags_) { - repoTags = repoTags_; - t.ifErr(err); - t.equal(typeof (repoTags), 'object'); - t.ok(repoTags[tag]); - t.ok(/[0-9a-f]{64}/.test(repoTags[tag])); - t.end(); - }); - }); - - tt.test(' getImgId', function (t) { - client.getImgId({tag: tag}, function (err, imgId) { - t.ifErr(err); - t.ok(imgId); - t.ok(/[0-9a-f]{64}/.test(imgId)); - t.equal(imgId, repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgAncestry', function (t) { - client.getImgAncestry({imgId: repoTags[tag]}, function (err, ancestry) { - t.ifErr(err); - t.ok(Array.isArray(ancestry)); - t.ok(ancestry.length > 0); - t.equal(ancestry[0], repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgJson', function (t) { - var imgId = repoTags[tag]; - client.getImgJson({imgId: imgId}, function (err, imgJson, res) { - t.ifErr(err); - t.equal(imgJson.id, imgId); - t.ok(imgJson.config); - t.end(); - }); - }); - - tt.test(' getImgLayerStream', function (t) { - var imgId = repoTags[tag]; - client.getImgLayerStream({imgId: imgId}, function (getErr, stream) { - t.ifErr(getErr, 'no error'); - if (getErr) { - return t.end(); - } - - t.ok(stream.headers, 'have headers'); - - var numBytes = 0; - stream.on('data', function (chunk) { - numBytes += chunk.length; - }); - stream.on('error', function (err) { - t.ifErr(err); - t.end(); - }); - stream.on('end', function () { - t.ok(numBytes > 0, 'downloaded ' + numBytes + ' bytes'); - t.end(); - }); - stream.resume(); - }); - }); - - tt.test(' close', function (t) { - client.close(); - t.end(); - }); -}); diff --git a/test/v1.dockerio2redhatredir.test.js b/test/v1.dockerio2redhatredir.test.js deleted file mode 100644 index ff2e151..0000000 --- a/test/v1.dockerio2redhatredir.test.js +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* - * Copyright (c) 2015, Joyent, Inc. - */ - -/* - * Test v1 pull of 'rhel7' from Docker Hub, which (at least at time of - * writing) redirects to . - */ - -var test = require('tape'); - -var drc = require('..'); - - -// --- globals - -var log = require('./lib/log'); - - -// --- Tests - -test('v1 docker.io redir to redhat', function (tt) { - var client; - - tt.test(' createClient', function (t) { - client = drc.createClientV1({ - name: 'rhel7', - log: log - }); - t.ok(client); - t.equal(client.version, 1); - t.end(); - }); - - tt.test(' ping', function (t) { - client.ping(function (err, status, res) { - t.ifErr(err); - t.equal(status, true); - t.end(); - }); - }); - - tt.test(' listRepoImgs', function (t) { - client.listRepoImgs(function (err, imgs) { - t.ifErr(err); - t.ok(Array.isArray(imgs)); - t.ok(imgs.length > 0); - t.ok(/[0-9a-f]{64}/.test(imgs[0].id)); - t.end(); - }); - }); - - var tag = 'latest'; - var repoTags; - - tt.test(' listRepoTags', function (t) { - client.listRepoTags(function (err, repoTags_) { - repoTags = repoTags_; - t.ifErr(err); - t.equal(typeof (repoTags), 'object'); - t.ok(repoTags[tag]); - t.ok(/[0-9a-f]{64}/.test(repoTags[tag])); - t.end(); - }); - }); - - tt.test(' getImgId', function (t) { - client.getImgId({tag: tag}, function (err, imgId) { - t.ifErr(err); - t.ok(imgId); - t.ok(/[0-9a-f]{64}/.test(imgId)); - t.equal(imgId, repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgAncestry', function (t) { - client.getImgAncestry({imgId: repoTags[tag]}, function (err, ancestry) { - t.ifErr(err); - t.ok(Array.isArray(ancestry)); - t.ok(ancestry.length > 0); - t.equal(ancestry[0], repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgJson', function (t) { - var imgId = repoTags[tag]; - client.getImgJson({imgId: imgId}, function (err, imgJson, res) { - t.ifErr(err); - t.equal(imgJson.id, imgId); - t.ok(imgJson.config); - t.end(); - }); - }); - - tt.test(' getImgLayerStream', function (t) { - var imgId = repoTags[tag]; - client.getImgLayerStream({imgId: imgId}, function (getErr, stream) { - t.ifErr(getErr, 'no error'); - if (getErr) { - return t.end(); - } - - t.ok(stream.headers, 'have headers'); - - var numBytes = 0; - stream.on('data', function (chunk) { - numBytes += chunk.length; - }); - stream.on('error', function (err) { - t.ifErr(err); - t.end(); - }); - stream.on('end', function () { - t.ok(numBytes > 0, 'downloaded ' + numBytes + ' bytes'); - t.end(); - }); - stream.resume(); - }); - }); - - tt.test(' close', function (t) { - client.close(); - t.end(); - }); -}); diff --git a/test/v1.jfrogartifactory.test.js b/test/v1.jfrogartifactory.test.js deleted file mode 100644 index c17073c..0000000 --- a/test/v1.jfrogartifactory.test.js +++ /dev/null @@ -1,180 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* - * Copyright (c) 2015, Joyent, Inc. - */ - -/* - * Test Docker v1 Registry in a jfrog artifactory repo, if there is a local - * config with repo details. - * - * This requires a test/config.json something like this: - * - * { - * "v1jfrogartifactory": { - * "repo": "trentm.artifactoryonline.com/busybox", - * "username": "admin", - * "password": "(your password)", - * "tag": "latest", - * "searchTerm": "busy" - * } - * } - * - * See DOCKER-419 for details on how to setup a Docker v1 registry with - * a demo account of jfrog artifactory. - * - */ - -var assert = require('assert-plus'); -var test = require('tape'); - -var drc = require('..'); - - -// --- globals - -var log = require('./lib/log'); -var CONFIG; -try { - CONFIG = require(__dirname + '/config.json').v1jfrogartifactory; - assert.object(CONFIG, 'config.json#v1jfrogartifactory'); - assert.string(CONFIG.repo, 'CONFIG.repo'); - assert.string(CONFIG.username, 'CONFIG.username'); - assert.string(CONFIG.password, 'CONFIG.password'); - assert.string(CONFIG.tag, 'CONFIG.tag'); - assert.string(CONFIG.searchTerm, 'CONFIG.searchTerm'); -} catch (e) { - CONFIG = null; - log.warn(e, 'skipping v1 jfrog artifactory tests: ' + - 'could not load "v1jfrogartifactory" key from test/config.json'); - console.warn('# warning: skipping v1 jfrog artifactory tests: %s', - e.message); -} - - -// --- Tests - -if (CONFIG) -test('v1 jfrog artifactory: ' + CONFIG.repo, function (tt) { - var client = drc.createClientV1({ - name: CONFIG.repo, - username: CONFIG.username, - password: CONFIG.password, - log: log - }); - var repo = drc.parseRepo(CONFIG.repo); - - tt.test(' ping', function (t) { - client.ping(function (err, status, res) { - t.ifErr(err); - t.equal(status, true); - t.end(); - }); - }); - - tt.test(' search', function (t) { - client.search({term: CONFIG.searchTerm}, function (err, results, res) { - t.ifErr(err); - if (!err) { - t.ok(results); - t.ok(results.num_results); - var hit = results.results.filter(function (r) { - return r.name.indexOf(repo.remoteName) !== -1; - })[0]; - t.ok(hit); - } - t.end(); - }); - }); - - tt.test(' listRepoImgs', function (t) { - client.listRepoImgs(function (err, imgs) { - t.ifErr(err); - t.ok(Array.isArray(imgs)); - t.ok(imgs.length > 0); - t.ok(/[0-9a-f]{64}/.test(imgs[0].id)); - t.end(); - }); - }); - - var tag = CONFIG.tag; - var repoTags; - - tt.test(' listRepoTags', function (t) { - client.listRepoTags(function (err, repoTags_) { - repoTags = repoTags_; - t.ifErr(err); - t.equal(typeof (repoTags), 'object'); - t.ok(repoTags[tag]); - t.ok(/[0-9a-f]{64}/.test(repoTags[tag])); - t.end(); - }); - }); - - tt.test(' getImgId', function (t) { - client.getImgId({tag: tag}, function (err, imgId) { - t.ifErr(err); - t.ok(imgId); - t.ok(/[0-9a-f]{64}/.test(imgId)); - t.equal(imgId, repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgAncestry', function (t) { - client.getImgAncestry({imgId: repoTags[tag]}, function (err, ancestry) { - t.ifErr(err); - t.ok(Array.isArray(ancestry)); - t.ok(ancestry.length > 0); - t.equal(ancestry[0], repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgJson', function (t) { - var imgId = repoTags[tag]; - client.getImgJson({imgId: imgId}, function (err, imgJson, res) { - t.ifErr(err); - t.equal(imgJson.id, imgId); - t.ok(imgJson.config); - t.end(); - }); - }); - - tt.test(' getImgLayerStream', function (t) { - var imgId = repoTags[tag]; - client.getImgLayerStream({imgId: imgId}, function (getErr, stream) { - t.ifErr(getErr, 'no error'); - if (getErr) { - return t.end(); - } - - t.ok(stream.headers, 'have headers'); - - var numBytes = 0; - stream.on('data', function (chunk) { - numBytes += chunk.length; - }); - stream.on('error', function (err) { - t.ifErr(err); - t.end(); - }); - stream.on('end', function () { - t.ok(numBytes > 0, 'downloaded ' + numBytes + ' bytes'); - t.end(); - }); - stream.resume(); - }); - }); - - - - tt.test(' close', function (t) { - client.close(); - t.end(); - }); -}); diff --git a/test/v1.quayio.test.js b/test/v1.quayio.test.js deleted file mode 100644 index d797487..0000000 --- a/test/v1.quayio.test.js +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* - * Copyright (c) 2015, Joyent, Inc. - */ - -var test = require('tape'); - -var drc = require('..'); - - -// --- globals - -var log = require('./lib/log'); - - -// --- Tests - -test('v1 quay.io', function (tt) { - var client = drc.createClientV1({ - name: 'quay.io/quay/elasticsearch', - log: log - }); - - tt.test(' ping', function (t) { - client.ping(function (err, status, res) { - t.ifErr(err); - t.equal(status, true); - t.end(); - }); - }); - - // DOCKER-604 skip this test for now, quay.io search is busted. - tt.skip(' search', function (t) { - client.search({term: 'elasticsearch'}, function (err, results, res) { - t.ifErr(err); - t.ok(results); - t.ok(results.num_results); - var es = results.results.filter( - function (r) { return r.name === 'quay/elasticsearch'; })[0]; - t.ok(es); - t.end(); - }); - }); - - tt.test(' listRepoImgs', function (t) { - client.listRepoImgs(function (err, imgs) { - t.ifErr(err); - // Quay.io, AFAICT, just uses this endpoint for session setup, - // i.e. for `Set-Cookie`, and the response body is always `[]`. - t.ok(Array.isArray(imgs)); - t.end(); - }); - }); - - var tag = 'latest'; - var repoTags; - - tt.test(' listRepoTags', function (t) { - client.listRepoTags(function (err, repoTags_) { - repoTags = repoTags_; - t.ifErr(err); - t.equal(typeof (repoTags), 'object'); - t.ok(repoTags[tag]); - t.ok(/[0-9a-f]{64}/.test(repoTags[tag])); - t.end(); - }); - }); - - tt.test(' getImgId', function (t) { - client.getImgId({tag: tag}, function (err, imgId) { - t.ifErr(err); - t.ok(imgId); - t.ok(/[0-9a-f]{64}/.test(imgId)); - t.equal(imgId, repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgAncestry', function (t) { - client.getImgAncestry({imgId: repoTags[tag]}, function (err, ancestry) { - t.ifErr(err); - t.ok(Array.isArray(ancestry)); - t.ok(ancestry.length > 0); - t.equal(ancestry[0], repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgJson', function (t) { - var imgId = repoTags[tag]; - client.getImgJson({imgId: imgId}, function (err, imgJson, res) { - t.ifErr(err); - t.equal(imgJson.id, imgId); - t.ok(imgJson.config); - t.end(); - }); - }); - - tt.test(' getImgLayerStream', function (t) { - var imgId = repoTags[tag]; - client.getImgLayerStream({imgId: imgId}, function (getErr, stream) { - t.ifErr(getErr, 'no error'); - if (getErr) { - return t.end(); - } - - t.ok(stream.headers, 'have headers'); - - var numBytes = 0; - stream.on('data', function (chunk) { - numBytes += chunk.length; - }); - stream.on('error', function (err) { - t.ifErr(err); - t.end(); - }); - stream.on('end', function () { - t.ok(numBytes > 0, 'downloaded ' + numBytes + ' bytes'); - t.end(); - }); - stream.resume(); - }); - }); - - tt.test(' close', function (t) { - client.close(); - t.end(); - }); -}); diff --git a/test/v1.redhat.test.js b/test/v1.redhat.test.js deleted file mode 100644 index 84bfd92..0000000 --- a/test/v1.redhat.test.js +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ - -/* - * Copyright (c) 2015, Joyent, Inc. - */ - -/* - * Test v1 (pull et al) Registry API against . - */ - -var test = require('tape'); - -var drc = require('..'); - - -// --- globals - -var log = require('./lib/log'); - -var REGISTRY = 'registry.access.redhat.com'; -var REPO = 'rhel7'; - - -// --- Tests - -test('v1 registry.access.redhat.com', function (tt) { - var client = drc.createClientV1({ - name: REGISTRY + '/' + REPO, - log: log - }); - - tt.test(' ping', function (t) { - client.ping(function (err, status, res) { - t.ifErr(err); - t.equal(status, true); - t.end(); - }); - }); - - tt.skip(' search', function (t) { - // Which a quick look, search on registry.access.redhat.com looks - // non-functional: I never get results. - t.end(); - }); - - tt.test(' listRepoImgs', function (t) { - client.listRepoImgs(function (err, imgs) { - t.ifErr(err); - t.ok(Array.isArray(imgs)); - t.ok(imgs.length > 0); - t.ok(/[0-9a-f]{64}/.test(imgs[0].id)); - t.end(); - }); - }); - - var tag = 'latest'; - var repoTags; - - tt.test(' listRepoTags', function (t) { - client.listRepoTags(function (err, repoTags_) { - repoTags = repoTags_; - t.ifErr(err); - t.equal(typeof (repoTags), 'object'); - t.ok(repoTags[tag]); - t.ok(/[0-9a-f]{64}/.test(repoTags[tag])); - t.end(); - }); - }); - - tt.test(' getImgId', function (t) { - client.getImgId({tag: tag}, function (err, imgId) { - t.ifErr(err); - t.ok(imgId); - t.ok(/[0-9a-f]{64}/.test(imgId)); - t.equal(imgId, repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgAncestry', function (t) { - client.getImgAncestry({imgId: repoTags[tag]}, - function (err, ancestry, res) { - t.ifErr(err); - t.equal(res.statusCode, 200, 'res.statusCode'); - t.ok(Array.isArray(ancestry), 'ancestry is an array'); - t.ok(ancestry.length > 0); - t.equal(ancestry[0], repoTags[tag]); - t.end(); - }); - }); - - tt.test(' getImgJson', function (t) { - var imgId = repoTags[tag]; - client.getImgJson({imgId: imgId}, function (err, imgJson, res) { - t.ifErr(err); - t.equal(imgJson.id, imgId); - t.ok(imgJson.config); - t.end(); - }); - }); - - tt.test(' getImgLayerStream', function (t) { - var imgId = repoTags[tag]; - client.getImgLayerStream({imgId: imgId}, function (getErr, stream) { - t.ifErr(getErr, 'no error'); - if (getErr) { - return t.end(); - } - - t.ok(stream.headers, 'have headers'); - - var numBytes = 0; - stream.on('data', function (chunk) { - numBytes += chunk.length; - }); - stream.on('error', function (err) { - t.ifErr(err); - t.end(); - }); - stream.on('end', function () { - t.ok(numBytes > 0, 'downloaded ' + numBytes + ' bytes'); - t.end(); - }); - stream.resume(); - }); - }); - - tt.test(' close', function (t) { - client.close(); - t.end(); - }); -}); diff --git a/test/v2.redhat.test.js b/test/v2.redhat.test.js index 880d045..4ce5224 100644 --- a/test/v2.redhat.test.js +++ b/test/v2.redhat.test.js @@ -73,20 +73,20 @@ test('v2 registry.access.redhat.com', function (tt) { }); }); - tt.test(' getManifest (redirected)', function (t) { - client.getManifest({ref: TAG}, function (err, manifest, res) { - t.ifErr(err); - t.ok(manifest, 'Got the manifest'); - t.equal(manifest.schemaVersion, 1); - t.equal(manifest.name, repo.remoteName); - t.equal(manifest.tag, TAG); - t.ok(manifest.architecture); - t.ok(manifest.fsLayers); - t.ok(manifest.history[0].v1Compatibility); - t.ok(manifest.signatures[0].signature); - t.end(); - }); - }); + // tt.test(' getManifest (redirected)', function (t) { + // client.getManifest({ref: TAG}, function (err, manifest, res) { + // t.ifErr(err); + // t.ok(manifest, 'Got the manifest'); + // t.equal(manifest.schemaVersion, 1); + // t.equal(manifest.name, repo.remoteName); + // t.equal(manifest.tag, TAG); + // t.ok(manifest.architecture); + // t.ok(manifest.fsLayers); + // t.ok(manifest.history[0].v1Compatibility); + // t.ok(manifest.signatures[0].signature); + // t.end(); + // }); + // }); tt.test(' close', function (t) { client.close();