diff --git a/docker-compose.yml b/docker-compose.yml index aab29420..e73031d6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -95,11 +95,20 @@ compose-api: restart: always rethinkdb: - image: rethinkdb + image: autopilotpattern/rethinkdb:2.3.5r1 restart: always mem_limit: 1g + links: + - consul:consul + env_file: + - _env + environment: + - CONSUL=consul + - CONSUL_AGENT=1 ports: - 8080:8080 expose: - 28015 - 29015 + dns: + - 127.0.0.1 diff --git a/docker/api/Dockerfile b/docker/api/Dockerfile index bf701b6f..fad65601 100644 --- a/docker/api/Dockerfile +++ b/docker/api/Dockerfile @@ -16,13 +16,15 @@ RUN curl --retry 7 --fail -vo /tmp/consul.zip "https://releases.hashicorp.com/co && rm /tmp/consul.zip \ && mkdir /config -# Install ContainerPilot -ENV CP_SHA1 056d45f728e9b9c61793d6f994da291d5eebeabd -ENV CONTAINERPILOT_VERSION 3.3.2 -RUN curl -Lo /tmp/containerpilot.tar.gz "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/containerpilot-${CONTAINERPILOT_VERSION}.tar.gz" \ - && echo "${CP_SHA1} /tmp/containerpilot.tar.gz" | sha1sum -c \ - && tar zxf /tmp/containerpilot.tar.gz -C /bin \ - && rm /tmp/containerpilot.tar.gz +# Install Containerpilot +ENV CONTAINERPILOT_VERSION 3.4.1 +RUN export CONTAINERPILOT_CHECKSUM=4d13cfb345de86135ab2271b77516c6b6a7bed3a \ + && export archive=containerpilot-${CONTAINERPILOT_VERSION}.tar.gz \ + && curl -Lso /tmp/${archive} \ + "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/${archive}" \ + && echo "${CONTAINERPILOT_CHECKSUM} /tmp/${archive}" | sha1sum -c \ + && tar zxf /tmp/${archive} -C /bin \ + && rm /tmp/${archive} # Copy required files RUN mkdir -p /opt/app/ @@ -41,4 +43,4 @@ ENV BUILD=production ENV NODE_ENV=production RUN npm install -CMD ["/bin/containerpilot"] +CMD ["containerpilot"] diff --git a/docker/api/bootstrap-data.js b/docker/api/bootstrap-data.js index a58f6a3b..14156d93 100644 --- a/docker/api/bootstrap-data.js +++ b/docker/api/bootstrap-data.js @@ -1,78 +1,85 @@ 'use strict'; +const Data = require('portal-api/lib/data'); +const Fs = require('fs'); +const Path = require('path'); +const Piloted = require('piloted'); const Triton = require('triton'); const Url = require('url'); -const Path = require('path'); -const Fs = require('fs'); -const Data = require('portal-api/lib/data'); -const { - DOCKER_HOST, - DOCKER_CERT_PATH, - SDC_URL, - SDC_ACCOUNT, - SDC_KEY_ID -} = process.env; -const DOCKER_HOST_URL = DOCKER_HOST ? Url.parse(DOCKER_HOST) : {}; +let bootstrapped = false; +let timeoutId; +const loadConfig = function () { + const docker = Piloted.service('docker-compose-api'); + const rethink = Piloted.service('rethinkdb'); -const settings = { - db: { - host: process.env.RETHINK_HOST || 'localhost' - }, - docker: { - protocol: 'https', - host: DOCKER_HOST_URL.hostname, - port: DOCKER_HOST_URL.port, - ca: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'ca.pem')) - : undefined, - cert: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'cert.pem')) - : undefined, - key: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'key.pem')) - : undefined - }, - triton: { - url: SDC_URL, - account: SDC_ACCOUNT, - keyId: SDC_KEY_ID + if (docker && rethink && !bootstrapped) { + bootstrapped = true; + bootstrap({ docker, rethink }); + } else if (!bootstrapped && !timeoutId) { + timeoutId = setTimeout(() => { + timeoutId = null; + Piloted.refresh(); + }, 1000); } }; -const ifError = function(err) { - if (err) { - console.error(err); - process.exit(1); - } -}; +Piloted.on('refresh', () => { + loadConfig(); +}); + + +const bootstrap = function ({ docker, rethink }) { + const settings = { + db: { + host: rethink.address + }, + docker: { + protocol: 'https', + host: docker.address, + port: docker.port, + ca: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'ca.pem')) + : undefined, + cert: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'cert.pem')) + : undefined, + key: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'key.pem')) + : undefined + }, + triton: { + url: process.env.SDC_URL, + account: process.env.SDC_ACCOUNT, + keyId: process.env.SDC_KEY_ID + } + }; -const bootstrap = function() { const data = new Data(settings); const region = process.env.TRITON_DC || 'us-sw-1'; data.connect(err => { - ifError(err); + handlerError(err); data.createDatacenter({ region, name: region }, (err, datacenter) => { - ifError(err); + handlerError(err); Triton.createClient( { profile: settings.triton }, (err, { cloudapi }) => { - ifError(err); + handlerError(err); cloudapi.getAccount((err, { firstName, lastName, email, login }) => { - ifError(err); + handlerError(err); data.createUser( { firstName, lastName, email, login }, (err, user) => { - ifError(err); + handlerError(err); data.createPortal( { @@ -80,7 +87,7 @@ const bootstrap = function() { datacenter }, (err, portal) => { - ifError(err); + handlerError(err); console.log('data bootstrapped'); process.exit(0); } @@ -94,4 +101,11 @@ const bootstrap = function() { }); }; -bootstrap(); +const handlerError = function (err) { + if (err) { + console.error(err); + process.exit(1); + } +}; + +loadConfig(); diff --git a/docker/api/package.json b/docker/api/package.json index e05991e1..0958977e 100644 --- a/docker/api/package.json +++ b/docker/api/package.json @@ -19,9 +19,9 @@ "hapi": "^16.1.0", "hoek": "^4.1.1", "joi": "^10.6.0", - "joyent-cp-gql-schema": "^1.2.0", + "joyent-cp-gql-schema": "^1.5.0", "piloted": "^3.1.1", - "portal-api": "^1.3.3", + "portal-api": "^1.4.0", "toppsy": "^1.1.0", "triton": "^5.2.0" } diff --git a/docker/api/server.js b/docker/api/server.js index 9779cece..97ef1db9 100644 --- a/docker/api/server.js +++ b/docker/api/server.js @@ -1,106 +1,126 @@ 'use strict'; const Brule = require('brule'); +const Fs = require('fs'); const Good = require('good'); const Hapi = require('hapi'); -const Toppsy = require('toppsy'); -const Portal = require('portal-api'); const Path = require('path'); -const Fs = require('fs'); +const Piloted = require('piloted'); +const Portal = require('portal-api'); +const Toppsy = require('toppsy'); const Url = require('url'); -const server = new Hapi.Server(); -server.connection({ port: 3000 }); -const { - DOCKER_HOST, - DOCKER_CERT_PATH, - SDC_URL, - SDC_ACCOUNT, - SDC_KEY_ID -} = process.env; +let started = false; +let timeoutId; +const loadConfig = function () { + const docker = Piloted.service('docker-compose-api'); + const rethink = Piloted.service('rethinkdb'); -const DOCKER_HOST_URL = DOCKER_HOST ? Url.parse(DOCKER_HOST) : {}; - -const portalOptions = { - data: { - db: { - host: process.env.RETHINK_HOST || 'localhost' - }, - docker: { - protocol: 'https', - host: DOCKER_HOST_URL.hostname, - port: DOCKER_HOST_URL.port, - ca: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'ca.pem')) - : undefined, - cert: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'cert.pem')) - : undefined, - key: DOCKER_CERT_PATH - ? Fs.readFileSync(Path.join(DOCKER_CERT_PATH, 'key.pem')) - : undefined - }, - triton: { - url: SDC_URL, - account: SDC_ACCOUNT, - keyId: SDC_KEY_ID - } - }, - watch: { - url: SDC_URL, - account: SDC_ACCOUNT, - keyId: SDC_KEY_ID + if (docker && rethink && !started) { + started = true; + startServer({ docker, rethink }); + } else if (!started && !timeoutId) { + timeoutId = setTimeout(() => { + timeoutId = null; + Piloted.refresh(); + }, 1000); } }; -const goodOptions = { - ops: { - interval: 1000 - }, - reporters: { - consoleReporter: [ - { - module: 'good-squeeze', - name: 'Squeeze', - args: [{ response: '*', error: '*' }] - }, - { - module: 'good-console' - }, - 'stdout' - ] - } -}; +Piloted.on('refresh', () => { + loadConfig(); +}); -server.register( - [ - Brule, - { - register: Good, - options: goodOptions + +const startServer = function ({ docker, rethink }) { + const port = process.env.PORT ? Number.parseInt(process.env.PORT, 10) : 3000; + + const server = new Hapi.Server(); + server.connection({ port }); + + const portalOptions = { + data: { + db: { + host: rethink.address + }, + docker: { + protocol: 'https', + host: docker.address, + port: docker.port, + ca: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'ca.pem')) + : undefined, + cert: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'cert.pem')) + : undefined, + key: process.env.DOCKER_CERT_PATH + ? Fs.readFileSync(Path.join(process.env.DOCKER_CERT_PATH, 'key.pem')) + : undefined + }, + triton: { + url: process.env.SDC_URL, + account: process.env.SDC_ACCOUNT, + keyId: process.env.SDC_KEY_ID + } }, - { - register: Portal, - options: portalOptions - }, - { - register: Toppsy, - options: { namespace: 'portal', subsystem: 'api' } + watch: { + url: process.env.SDC_URL, + account: process.env.SDC_ACCOUNT, + keyId: process.env.SDC_KEY_ID } - ], - err => { - handlerError(err); - server.start(err => { + }; + + const goodOptions = { + ops: { + interval: 1000 + }, + reporters: { + consoleReporter: [ + { + module: 'good-squeeze', + name: 'Squeeze', + args: [{ response: '*', error: '*' }] + }, + { + module: 'good-console' + }, + 'stdout' + ] + } + }; + + server.register( + [ + Brule, + { + register: Good, + options: goodOptions + }, + { + register: Portal, + options: portalOptions + }, + { + register: Toppsy, + options: { namespace: 'portal', subsystem: 'api' } + } + ], + (err) => { handlerError(err); - console.log(`server started at http://localhost:${server.info.port}`); - }); - } -); + server.start((err) => { + handlerError(err); + console.log(`server started at http://localhost:${server.info.port}`); + }); + } + ); +}; -function handlerError(error) { - if (error) { - console.error(error); +const handlerError = function (err) { + if (err) { + console.error(err); process.exit(1); } -} +}; + +loadConfig(); diff --git a/docker/compose-api/Dockerfile b/docker/compose-api/Dockerfile index 9ef04bf0..1bf24c20 100644 --- a/docker/compose-api/Dockerfile +++ b/docker/compose-api/Dockerfile @@ -10,16 +10,14 @@ RUN export CONSUL_VERSION=0.7.0 \ && rm /tmp/consul.zip \ && mkdir /config -# Add Containerpilot and set its configuration -ENV CONTAINERPILOT_VERSION 3.3.1 -ENV CONTAINERPILOT /etc/containerpilot.json - -RUN export CONTAINERPILOT_CHECKSUM=e27c1b9cd1023e622f77bb19914606dee3c9b22c \ +# Install Containerpilot +ENV CONTAINERPILOT_VERSION 3.4.1 +RUN export CONTAINERPILOT_CHECKSUM=4d13cfb345de86135ab2271b77516c6b6a7bed3a \ && export archive=containerpilot-${CONTAINERPILOT_VERSION}.tar.gz \ && curl -Lso /tmp/${archive} \ "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/${archive}" \ && echo "${CONTAINERPILOT_CHECKSUM} /tmp/${archive}" | sha1sum -c \ - && tar zxf /tmp/${archive} -C /usr/local/bin \ + && tar zxf /tmp/${archive} -C /bin \ && rm /tmp/${archive} # Add Containerpilot configuration @@ -28,4 +26,4 @@ ENV CONTAINERPILOT /etc/containerpilot.json COPY bin /bin ENTRYPOINT [] -CMD ["/usr/local/bin/containerpilot"] +CMD ["containerpilot"] diff --git a/docker/frontend/Dockerfile b/docker/frontend/Dockerfile index cccc01f4..e47dced9 100644 --- a/docker/frontend/Dockerfile +++ b/docker/frontend/Dockerfile @@ -26,13 +26,15 @@ RUN curl --retry 7 --fail -vo /tmp/consul.zip "https://releases.hashicorp.com/co && rm /tmp/consul.zip \ && mkdir /config -# Install ContainerPilot -ENV CP_SHA1 e27c1b9cd1023e622f77bb19914606dee3c9b22c -ENV CONTAINERPILOT_VERSION 3.3.1 -RUN curl -Lo /tmp/containerpilot.tar.gz "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/containerpilot-${CONTAINERPILOT_VERSION}.tar.gz" \ - && echo "${CP_SHA1} /tmp/containerpilot.tar.gz" | sha1sum -c \ - && tar zxf /tmp/containerpilot.tar.gz -C /bin \ - && rm /tmp/containerpilot.tar.gz +# Install Containerpilot +ENV CONTAINERPILOT_VERSION 3.4.1 +RUN export CONTAINERPILOT_CHECKSUM=4d13cfb345de86135ab2271b77516c6b6a7bed3a \ + && export archive=containerpilot-${CONTAINERPILOT_VERSION}.tar.gz \ + && curl -Lso /tmp/${archive} \ + "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/${archive}" \ + && echo "${CONTAINERPILOT_CHECKSUM} /tmp/${archive}" | sha1sum -c \ + && tar zxf /tmp/${archive} -C /bin \ + && rm /tmp/${archive} ENV NODE_ENV=production @@ -47,4 +49,4 @@ WORKDIR /opt/app/ RUN npm pack joyent-cp-frontend RUN tar -xzf joyent-cp-frontend*.tgz -CMD ["/bin/containerpilot"] +CMD ["containerpilot"] diff --git a/local-compose.yml b/local-compose.yml index a225b2cf..bf7952d8 100644 --- a/local-compose.yml +++ b/local-compose.yml @@ -96,6 +96,10 @@ rethinkdb: image: autopilotpattern/rethinkdb:2.3.5r1 restart: always mem_limit: 1g + links: + - consul:consul + env_file: + - _env environment: - CONSUL=consul - CONSUL_AGENT=1 diff --git a/packages/cp-gql-schema/package.json b/packages/cp-gql-schema/package.json index 84286a43..5efb1c69 100644 --- a/packages/cp-gql-schema/package.json +++ b/packages/cp-gql-schema/package.json @@ -1,6 +1,6 @@ { "name": "joyent-cp-gql-schema", - "version": "1.5.0", + "version": "1.5.1", "license": "MPL-2.0", "repository": "github:yldio/joyent-portal", "main": "index.js", diff --git a/packages/portal-api/package.json b/packages/portal-api/package.json index ae448428..d1c61756 100644 --- a/packages/portal-api/package.json +++ b/packages/portal-api/package.json @@ -1,6 +1,6 @@ { "name": "portal-api", - "version": "1.3.3", + "version": "1.4.0", "description": "", "main": "./lib/index.js", "scripts": { diff --git a/triton-compose.yml b/triton-compose.yml index 69c1b9e9..a38e8c8e 100644 --- a/triton-compose.yml +++ b/triton-compose.yml @@ -45,6 +45,18 @@ prometheus: env_file: - _env +rethinkdb: + image: autopilotpattern/rethinkdb:2.3.5r1 + restart: always + mem_limit: 1g + env_file: + - _env + environment: + - CONSUL_AGENT=1 + expose: + - 28015 + - 29015 + ############################################################################# # FRONTEND