From ad5a50a1730e888b4a21140f28cc436569b7aa95 Mon Sep 17 00:00:00 2001 From: Wyatt Preul Date: Wed, 11 Jan 2017 10:43:08 -0600 Subject: [PATCH] Update consul, ContainerPilot, alpine versions (#28) * Update consul, ContainerPilot versions * Fix tests * Remove log statement --- Dockerfile | 12 ++-- etc/consul.json | 2 +- test/package.json | 6 +- test/raft-test.js | 142 ++++++++++++++++++++++++++-------------------- 4 files changed, 92 insertions(+), 70 deletions(-) diff --git a/Dockerfile b/Dockerfile index 81ebcb1..021ea72 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.4 +FROM alpine:3.5 # Alpine packages RUN apk --no-cache \ @@ -8,8 +8,8 @@ RUN apk --no-cache \ ca-certificates # The Consul binary -ENV CONSUL_VERSION=0.7.0 -RUN export CONSUL_CHECKSUM=b350591af10d7d23514ebaa0565638539900cdb3aaa048f077217c4c46653dd8 \ +ENV CONSUL_VERSION=0.7.2 +RUN export CONSUL_CHECKSUM=aa97f4e5a552d986b2a36d48fdc3a4a909463e7de5f726f3c5a89b8a1be74a58 \ && export archive=consul_${CONSUL_VERSION}_linux_amd64.zip \ && curl -Lso /tmp/${archive} https://releases.hashicorp.com/consul/${CONSUL_VERSION}/${archive} \ && echo "${CONSUL_CHECKSUM} /tmp/${archive}" | sha256sum -c \ @@ -19,7 +19,7 @@ RUN export CONSUL_CHECKSUM=b350591af10d7d23514ebaa0565638539900cdb3aaa048f077217 && rm /tmp/${archive} # The Consul web UI -RUN export CONSUL_UI_CHECKSUM=42212089c228a73a0881a5835079c8df58a4f31b5060a3b4ffd4c2497abe3aa8 \ +RUN export CONSUL_UI_CHECKSUM=c9d2a6e1d1bb6243e5fd23338d92f5c71cdf0a4077f7fcc95fd81800fa1f42a9 \ && export archive=consul_${CONSUL_VERSION}_web_ui.zip \ && curl -Lso /tmp/${archive} https://releases.hashicorp.com/consul/${CONSUL_VERSION}/${archive} \ && echo "${CONSUL_UI_CHECKSUM} /tmp/${archive}" | sha256sum -c \ @@ -29,10 +29,10 @@ RUN export CONSUL_UI_CHECKSUM=42212089c228a73a0881a5835079c8df58a4f31b5060a3b4ff && rm /tmp/${archive} # Add Containerpilot and set its configuration -ENV CONTAINERPILOT_VERSION 2.4.1 +ENV CONTAINERPILOT_VERSION 2.6.0 ENV CONTAINERPILOT file:///etc/containerpilot.json -RUN export CONTAINERPILOT_CHECKSUM=198d96c8d7bfafb1ab6df96653c29701510b833c \ +RUN export CONTAINERPILOT_CHECKSUM=c1bcd137fadd26ca2998eec192d04c08f62beb1f \ && export archive=containerpilot-${CONTAINERPILOT_VERSION}.tar.gz \ && curl -Lso /tmp/${archive} \ "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/${archive}" \ diff --git a/etc/consul.json b/etc/consul.json index 70482ca..825cd92 100644 --- a/etc/consul.json +++ b/etc/consul.json @@ -4,7 +4,7 @@ "ui_dir": "/ui", "client_addr": "0.0.0.0", "ports": { - "dns": 53 + "dns": 53 }, "recursor": "8.8.8.8", "disable_update_check": true diff --git a/test/package.json b/test/package.json index 586be60..7b28150 100644 --- a/test/package.json +++ b/test/package.json @@ -9,8 +9,8 @@ "author": "Joyent, Inc.", "license": "Mozilla Public License 2.0", "dependencies": { - "async": "^1.5.0", - "consul": "^0.18.1", - "dockerode": "^2.2.3" + "async": "2.1.4", + "consul": "0.27.0", + "dockerode": "2.3.1" } } diff --git a/test/raft-test.js b/test/raft-test.js index fe80586..42cf00e 100755 --- a/test/raft-test.js +++ b/test/raft-test.js @@ -1,14 +1,14 @@ #!/usr/local/bin/node var Docker = require('dockerode'); var Consul = require('consul'); -var async = require('async'); +var Async = require('async'); // dockerode will automatically pick up your DOCKER_HOST, DOCKER_CERT_PATH // but we need to set the version explicitly to support Triton // ref https://github.com/apocas/dockerode/issues/154 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; var docker = new Docker(); -docker.version = 'v1.20'; +docker.version = 'v1.24'; listConsul(function (err, consulNodes) { if (err) { @@ -41,7 +41,7 @@ function run3NodeTests(consulNodes) { return; } console.log('raft is healthy: ', result); - async.series([ + Async.series([ function (cb) { test3_1(consulNodes, cb); }, function (cb) { test3_2(consulNodes, cb); }, function (cb) { test3_3(consulNodes, cb); } @@ -70,7 +70,7 @@ function run5NodeTests(consulNodes) { return; } console.log('raft is healthy: ', result); - async.series([ + Async.series([ function (cb) { test5_1(consulNodes, cb); }, function (cb) { test5_2(consulNodes, cb); } ], function (errResult, testResults) { @@ -97,11 +97,11 @@ function test3_1(consulNodes, callback) { consul2 = consulNodes[1], consul3 = consulNodes[2]; - async.series([ - function (cb) { stop(consul3, cb); }, - function (cb) { waitForElection([consul1, consul2], cb); }, - function (cb) { start(consul3, cb); }, - function (cb) { waitForElection(consulNodes, cb); } + Async.series([ + function (next) { stop(consul3, next); }, + function (next) { waitForElection([consul1, consul2], next); }, + function (next) { start(consul3, next); }, + function (next) { waitForElection(consulNodes, next); } ], function (err, results) { callback(err, results[results.length - 1]); }); @@ -114,7 +114,7 @@ function test3_2(consulNodes, callback) { consul2 = consulNodes[1], consul3 = consulNodes[2]; - async.series([ + Async.series([ function (cb) { stop(consul1, cb); }, function (cb) { waitForElection([consul2, consul3], cb); }, function (cb) { start(consul1, cb); }, @@ -132,7 +132,7 @@ function test3_3(consulNodes, callback) { consul2 = consulNodes[1], consul3 = consulNodes[2]; - async.series([ + Async.series([ function (cb) { stop(consul1, cb); }, function (cb) { stop(consul3, cb); }, function (cb) { start(consul3, cb); }, @@ -153,7 +153,7 @@ function test5_1(consulNodes, callback) { consul4 = consulNodes[3], consul5 = consulNodes[4]; - async.series([ + Async.series([ function (cb) { stop(consul1, cb); }, function (cb) { stop(consul2, cb); }, function (cb) { testWrites([consul3, consul4, consul5], @@ -179,7 +179,7 @@ function test5_2(consulNodes, callback) { consul4 = consulNodes[3], consul5 = consulNodes[4]; - async.series([ + Async.series([ function (cb) { createNetsplit([consul1, consul2], [consul3, consul4, consul5], cb); }, function (cb) { testWrites([consul1, consul2], @@ -199,7 +199,7 @@ function test5_2(consulNodes, callback) { // Queries Consul to determine the status of the raft. Compares the status // against a list of containers and verifies that the leader is among those -// nodes. If failing, will retry twice with some backoff and then return +// nodes. If failing, will retry 10 times with some backoff and then return // error to the callback if the raft still has not healed. // @param {containers} array of container objects from our Consul nodes // array that should be members of the raft. @@ -208,29 +208,32 @@ function waitForElection(containers, callback) { var expected = []; containers.forEach(function (container) { - expected.push(container.Ip+':8300'); + expected.push(container.Ip + ':8300'); }); expected.sort(); console.log('expected peers:', expected.toString()); var isMatch = false; var count = 0; - var maxCount = 3; - - async.doUntil( - function (cb) { - getLeader(containers[0], function (err, leader) { - if (err || !leader) { - cb(err); - return; - } - isMatch = (expected.indexOf(leader) != -1); - cb(null); - }); + var maxCount = 10; + + Async.doUntil( + function (next) { + setTimeout(function () { + getLeader(containers[0], function (err, leader) { + if (err && err.statusCode === 409) { // The container is restarting, wait + return next(); + } + if (err || !leader) { + return next(err); + } + isMatch = (expected.indexOf(leader) !== -1); + next(); + }); + }, 1000); }, function () { - count++; - return (isMatch || count >= maxCount); + return (isMatch || (++count >= maxCount)); }, function (err) { if (err) { @@ -277,34 +280,20 @@ function listConsul(callback) { var consul = []; docker.listContainers( {all: false, - filters: ['{"label":["com.docker.compose.service=consul"]}']}, + filters: { label: ['com.docker.compose.service=consul'] }}, function (err, containers) { if (err) { callback(err, null); return; } - async.each(containers, function (container, cb) { - var cmd = ['ip', 'addr', 'show', 'eth0']; - runExec(container, cmd, function (e, ip) { - if (e) { - cb(e); - return; - } - container['Ip'] = matchIp(ip); - cb(null); - }); - }, function (inspectErr) { - if (inspectErr) { - callback(inspectErr, null); - } - containers.forEach(function (container) { - container['Name'] = container.Names[0].replace('/', ''); - consul.push(container); - }); - consul.sort(byName); - callback(null, consul); - return; + + containers.forEach(function (container) { + container.Name = container.Names[0].replace('/', ''); + container.Ip = container.NetworkSettings.Networks.consul_default.IPAddress; + consul.push(container); }); + consul.sort(byName); + callback(null, consul); }); } @@ -316,13 +305,37 @@ function byName(a, b) { // @callback {fn} function(err, result) function stop(container, fn) { console.log('stopping', container.Name); - docker.getContainer(container.Id).stop(fn); + var runningContainer = docker.getContainer(container.Id); + runningContainer.stop(function (err, result) { }); + + runningContainer.wait(fn); } // @callback {fn} function(err, result) -function start(container, fn) { +function start(container, callback) { console.log('starting', container.Name); - docker.getContainer(container.Id).start(fn); + var containerInstance = docker.getContainer(container.Id); + containerInstance.start((function (err) { + if (err) { + return callback(err); + } + + var checkStarted = function () { + containerInstance.inspect(function (err, result) { + if (err) { + return callback(err); + } + + if (result.State.Status === 'running') { + return callback(null, result); + } + + setTimeout(checkStarted, 1000); + }); + }; + + checkStarted(); + })); } // @callback {fn} function(err, leader) @@ -330,10 +343,16 @@ function getLeader(container, fn) { runExec(container, ['curl', '127.0.0.1:8500/v1/status/leader'], function (err, leader) { - if (err || leader === null) { + if (err || !leader) { return fn(err, null); } - return fn(null, matchIpPort(leader)[0]); + + var leaderAddress = matchIpPort(leader); + if (!leaderAddress) { + return fn(); + } + + return fn(null, leaderAddress[0]); }); } @@ -376,14 +395,17 @@ function runExec(container, command, callback) { docker.getContainer(container.Id).exec(options, function (execErr, exec) { if (execErr) { - callback(execErr, null); + return callback(execErr, null); } - exec.start({Tty: true, Detach: true}, function (err, stream) { + + exec.start({hijack: true, stdin: true}, function (err, stream) { if (err) { - callback(err, null); + return callback(err, null); } + + stream.end('\n'); + var body = ''; - stream.setEncoding('utf8'); stream.once('error', function (error) { callback(error, null); });