diff --git a/docker/api/Dockerfile b/docker/api/Dockerfile new file mode 100644 index 00000000..a15203e4 --- /dev/null +++ b/docker/api/Dockerfile @@ -0,0 +1,44 @@ +FROM node:8-alpine + +# Install dependencies +RUN set -x \ + && apk update \ + && apk add --update curl bash build-base python zeromq-dev openssh \ + && apk upgrade \ + && rm -rf /var/cache/apk/* + +# Install Consul agent +ENV CONSUL_VERSION 0.7.0 +ENV CONSUL_CHECKSUM b350591af10d7d23514ebaa0565638539900cdb3aaa048f077217c4c46653dd8 +RUN curl --retry 7 --fail -vo /tmp/consul.zip "https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip" \ + && echo "${CONSUL_CHECKSUM} /tmp/consul.zip" | sha256sum -c \ + && unzip /tmp/consul -d /usr/local/bin \ + && rm /tmp/consul.zip \ + && mkdir /config + +# Install ContainerPilot +ENV CP_SHA1 d06e289e6e0ca82156d77cea36ff0f0246fcca60 +ENV CONTAINERPILOT_VERSION 3.1.0 +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 + +# Copy required files +RUN mkdir -p /opt/app/ +COPY *.js /opt/app/ +COPY package.json /opt/app/ +COPY bin /bin +COPY etc /etc +ENV CONTAINERPILOT /etc/containerpilot.json5 + + +# Install dependencies + +WORKDIR /opt/app/ + +ENV BUILD=production +ENV NODE_ENV=production +RUN npm install + +CMD ["/bin/containerpilot"] diff --git a/packages/portal-api/bin/prestart.sh b/docker/api/bin/prestart.sh similarity index 100% rename from packages/portal-api/bin/prestart.sh rename to docker/api/bin/prestart.sh diff --git a/docker/api/bin/sensors.sh b/docker/api/bin/sensors.sh new file mode 100755 index 00000000..1a68bbd9 --- /dev/null +++ b/docker/api/bin/sensors.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -e + +help() { + echo 'Uses cli tools free and top to determine current CPU and memory usage' + echo 'for the telemetry service.' +} + +# memory usage in percent +memory() { + # awk oneliner to get memory usage + # free -m | awk 'NR==2{printf "Memory Usage: %s/%sMB (%.2f%%)\n", $3,$2,$3*100/$2 }' + # output: + # Memory Usage: 15804/15959MB (99.03%) + local memory=$(free -m | awk 'NR==2{printf "%.2f", $3*100/$2 }') + /bin/containerpilot -putmetric "frontend_memory_percent=$memory" +} + +# cpu load +cpu() { + # oneliner to display cpu load + # top -bn1 | grep load | awk '{printf "CPU Load: %.2f\n", $(NF-2)}' + local cpuload=$(uptime | awk '{printf "%.2f", $6}') + /bin/containerpilot -putmetric "frontend_cpu_load=$cpuload" +} + +diskusage() { + local usage=$(df -P | grep '/$' | awk 'NR=2{print $3}' | sed 's/[^0-9\.]*//g') + /bin/containerpilot -putmetric "frontend_disk_usage=$usage" +} + +diskcapacity() { + local capacity=$(df -P | grep '/$' | awk 'NR=2{print $2}' | sed 's/[^0-9\.]*//g') + /bin/containerpilot -putmetric "frontend_disk_capacity=$capacity" +} + +cmd=$1 +if [ ! -z "$cmd" ]; then + shift 1 + $cmd "$@" + exit +fi + +help diff --git a/docker/api/bootstrap-data.js b/docker/api/bootstrap-data.js new file mode 100644 index 00000000..32419b93 --- /dev/null +++ b/docker/api/bootstrap-data.js @@ -0,0 +1,57 @@ +'use strict'; + +const Data = require('portal-data'); + + +const ifError = function (err) { + if (err) { + console.error(err); + process.exit(1); + } +}; + +const bootstrap = function () { + const data = new Data({ + db: { + host: process.env.RETHINK_HOST || 'localhost' + } + }); + + const region = process.env.TRITON_DC || 'us-sw-1'; + const login = process.env.TRITON_USER || 'nikola'; + + data.connect(() => { + data.createDatacenter({ region, name: region }, (err, datacenter) => { + ifError(err); + + data.createUser({ firstName: 'Nikola', lastName: 'Tesla', email: 'nikola@tesla.com', login }, (err, user) => { + ifError(err); + + data.createPortal({ + user, + datacenter + }, (err, portal) => { + ifError(err); + console.log('data bootstrapped'); + process.exit(0); + }); + }); + }); + }); +}; +/* +const main = function () { + const dropData = new Data({ + db: { + host: process.env.RETHINK_HOST || 'localhost' + } + }); + + dropData.connect(() => { + dropData._db.r.dbDrop('portal').run(dropData._db._connection, () => { + bootstrap(); + }); + }); +}; +*/ +bootstrap(); diff --git a/packages/portal-api/etc/containerpilot.json5 b/docker/api/etc/containerpilot.json5 similarity index 94% rename from packages/portal-api/etc/containerpilot.json5 rename to docker/api/etc/containerpilot.json5 index dc477675..c8aa0029 100644 --- a/packages/portal-api/etc/containerpilot.json5 +++ b/docker/api/etc/containerpilot.json5 @@ -47,7 +47,7 @@ }, { name: 'sensor_memory_usage', - exec: '/bin/sensors memory', + exec: '/bin/sensors.sh memory', timeout: '5s', when: { interval: '5s' @@ -56,7 +56,7 @@ }, { name: 'sensor_cpu_load', - exec: '/bin/sensors cpu', + exec: '/bin/sensors.sh cpu', timeout: '5s', when: { interval: '5s' @@ -65,7 +65,7 @@ }, { name: 'sensor_disk_capacity', - exec: '/bin/sensors diskcapacity', + exec: '/bin/sensors.sh diskcapacity', timeout: '5s', when: { interval: '60s' @@ -74,7 +74,7 @@ }, { name: 'sensor_disk_usage', - exec: '/bin/sensors diskusage', + exec: '/bin/sensors.sh diskusage', timeout: '5s', when: { interval: '60s' @@ -87,8 +87,7 @@ when: { source: 'watch.docker-compose-api', each: 'changed' - }, - restarts: 'unlimited' + } }, ], watches: [ diff --git a/docker/api/package.json b/docker/api/package.json new file mode 100644 index 00000000..5bfac7f3 --- /dev/null +++ b/docker/api/package.json @@ -0,0 +1,29 @@ +{ + "name": "api", + "version": "1.0.0", + "description": "", + "main": "./server.js", + "scripts": { + "start": "node server.js" + }, + "keywords": [], + "author": "wyatt", + "license": "MPL-2.0", + "dependencies": { + "boom": "^5.1.0", + "brule": "^2.0.0", + "good": "^7.2.0", + "good-console": "^6.4.0", + "good-squeeze": "^5.0.2", + "graphi": "^2.2.1", + "hapi": "^16.1.0", + "hoek": "^4.1.1", + "joi": "^10.6.0", + "joyent-cp-gql-schema": "^1.0.4", + "piloted": "^3.1.1", + "portal-api": "^1.1.0", + "portal-data": "^1.1.0", + "portal-watch": "^1.0.0", + "toppsy": "^1.1.0" + } +} diff --git a/docker/api/server.js b/docker/api/server.js new file mode 100644 index 00000000..fb59a053 --- /dev/null +++ b/docker/api/server.js @@ -0,0 +1,95 @@ +'use strict'; + +const Fs = require('fs'); +const Path = require('path'); +const Brule = require('brule'); +const Good = require('good'); +const Hapi = require('hapi'); +const Toppsy = require('toppsy'); +const Pack = require('./package'); +const Portal = require('portal-api'); + + +const server = new Hapi.Server(); +server.connection({ port: process.env.PORT || 3000 }); + +const { + DOCKER_HOST, + DOCKER_CERT_PATH, + DOCKER_CLIENT_TIMEOUT, + SDC_URL, + SDC_ACCOUNT, + SDC_KEY_ID +} = process.env; + +const portalOptions = { + data: { + db: { + host: process.env.RETHINK_HOST || 'localhost' + }, + docker: { + host: DOCKER_HOST, + 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, + timeout: DOCKER_CLIENT_TIMEOUT + } + }, + watch: { + url: SDC_URL, + account: SDC_ACCOUNT, + keyId: SDC_KEY_ID + } +}; + +const goodOptions = { + ops: { + interval: 1000 + }, + reporters: { + consoleReporter: [{ + module: 'good-squeeze', + name: 'Squeeze', + args: [{ log: '*', 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); + server.start((err) => { + handlerError(err); + console.log(`server started at http://localhost:${server.info.port}`); + }); + } +); + +function handlerError (error) { + if (error) { + console.error(error); + process.exit(1); + } +} diff --git a/docker-compose-api/Dockerfile b/docker/compose-api/Dockerfile similarity index 90% rename from docker-compose-api/Dockerfile rename to docker/compose-api/Dockerfile index a9776dfc..c4a8078e 100644 --- a/docker-compose-api/Dockerfile +++ b/docker/compose-api/Dockerfile @@ -1,9 +1,7 @@ FROM quay.io/yldio/docker-compose-api - RUN apk add --update bash - RUN export CONSUL_VERSION=0.7.0 \ && export CONSUL_CHECKSUM=b350591af10d7d23514ebaa0565638539900cdb3aaa048f077217c4c46653dd8 \ && curl --retry 7 --fail -vo /tmp/consul.zip "https://releases.hashicorp.com/consul/${CONSUL_VERSION}/consul_${CONSUL_VERSION}_linux_amd64.zip" \ @@ -12,12 +10,11 @@ RUN export CONSUL_VERSION=0.7.0 \ && rm /tmp/consul.zip \ && mkdir /config - # Add Containerpilot and set its configuration -ENV CONTAINERPILOT_VERSION 3.0.0 +ENV CONTAINERPILOT_VERSION 3.1.0 ENV CONTAINERPILOT /etc/containerpilot.json -RUN export CONTAINERPILOT_CHECKSUM=6da4a4ab3dd92d8fd009cdb81a4d4002a90c8b7c \ +RUN export CONTAINERPILOT_CHECKSUM=d06e289e6e0ca82156d77cea36ff0f0246fcca60 \ && export archive=containerpilot-${CONTAINERPILOT_VERSION}.tar.gz \ && curl -Lso /tmp/${archive} \ "https://github.com/joyent/containerpilot/releases/download/${CONTAINERPILOT_VERSION}/${archive}" \ diff --git a/docker-compose-api/bin/prestart.sh b/docker/compose-api/bin/prestart.sh similarity index 100% rename from docker-compose-api/bin/prestart.sh rename to docker/compose-api/bin/prestart.sh diff --git a/docker-compose-api/etc/containerpilot.json b/docker/compose-api/etc/containerpilot.json similarity index 100% rename from docker-compose-api/etc/containerpilot.json rename to docker/compose-api/etc/containerpilot.json diff --git a/local-compose.yml b/local-compose.yml index 2705ed1a..75173536 100644 --- a/local-compose.yml +++ b/local-compose.yml @@ -43,8 +43,8 @@ prometheus: # Docker-compose wrapper # Create _env file from running ./setup.sh -docker-compose-api: - build: ./docker-compose-api +compose-api: + build: ./docker/compose-api links: - consul:consul expose: @@ -87,8 +87,7 @@ frontend: # BACKEND ############################################################################# api: - build: ./ - dockerfile: packages/portal-api/Dockerfile + build: docker/api mem_limit: 512m links: - consul:consul diff --git a/packages/cp-gql-schema/package.json b/packages/cp-gql-schema/package.json index 7969d10f..33b771a8 100644 --- a/packages/cp-gql-schema/package.json +++ b/packages/cp-gql-schema/package.json @@ -1,7 +1,6 @@ { "name": "joyent-cp-gql-schema", - "version": "1.0.4", - "private": true, + "version": "1.1.0", "license": "MPL-2.0", "repository": "github:yldio/joyent-portal", "main": "index.js", diff --git a/packages/docker-compose-client/package.json b/packages/docker-compose-client/package.json index 7e3afeda..2840fceb 100644 --- a/packages/docker-compose-client/package.json +++ b/packages/docker-compose-client/package.json @@ -1,6 +1,6 @@ { "name": "docker-compose-client", - "version": "1.0.8", + "version": "1.0.9", "license": "MPL-2.0", "repository": "github:yldio/joyent-portal", "main": "lib", diff --git a/packages/portal-api/Dockerfile b/packages/portal-api/Dockerfile deleted file mode 100644 index 07dae923..00000000 --- a/packages/portal-api/Dockerfile +++ /dev/null @@ -1,21 +0,0 @@ -FROM quay.io/yldio/alpine-node-containerpilot:latest - -ENV CONTAINERPILOT /etc/containerpilot.json5 - -RUN set -x \ - && apk update \ - && apk add curl bash build-base python zeromq-dev openssh \ - && rm -rf /var/cache/apk/* - -RUN npm install -g npm@^4 \ - && npm config set loglevel info \ - && yarn add lerna@^2.0.0-rc.5 \ - && ./node_modules/.bin/lerna clean --yes --scope portal-api --include-filtered-dependencies \ - && ./node_modules/.bin/lerna bootstrap --scope portal-api --include-filtered-dependencies - -COPY packages/portal-api/etc/containerpilot.json5 ${CONTAINERPILOT} -COPY packages/portal-api/bin /bin - -WORKDIR /opt/app/packages/portal-api - -CMD ["/bin/containerpilot"] diff --git a/packages/portal-api/package.json b/packages/portal-api/package.json index 09426686..4cc96958 100644 --- a/packages/portal-api/package.json +++ b/packages/portal-api/package.json @@ -1,6 +1,6 @@ { "name": "portal-api", - "version": "1.0.0", + "version": "1.1.0", "description": "", "main": "./lib/index.js", "scripts": { diff --git a/packages/portal-data/package.json b/packages/portal-data/package.json index c326de0f..5cb2291a 100644 --- a/packages/portal-data/package.json +++ b/packages/portal-data/package.json @@ -1,6 +1,6 @@ { "name": "portal-data", - "version": "1.1.0", + "version": "1.2.0", "description": "portal data layer", "main": "lib", "scripts": { diff --git a/packages/portal-watch/package.json b/packages/portal-watch/package.json index e41bfda2..04ac40a9 100644 --- a/packages/portal-watch/package.json +++ b/packages/portal-watch/package.json @@ -1,7 +1,6 @@ { "name": "portal-watch", "version": "1.0.0", - "private": true, "license": "MPL-2.0", "description": "resolver of triton change events", "repository": "github:yldio/joyent-portal",