diff --git a/Makefile b/Makefile index 4b77e7a9..ecb32ac1 100644 --- a/Makefile +++ b/Makefile @@ -21,5 +21,9 @@ install-cloudapi-graphql: install-frontend: $(MAKE) -C frontend install +.PHONY: install-backend +install-backend: + $(MAKE) -C backend install + .PHONY: install -install: install-cloudapi-graphql install-frontend +install: install-cloudapi-graphql install-frontend install-backend diff --git a/README.md b/README.md index 0455fba5..6e817320 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ We will also include multiple PoC's of various bits of functionality from UI's p ``` . ├── frontend +├── backend ├── cloudapi-graphql └── spikes ``` @@ -24,6 +25,10 @@ An implementation of the [Joyent CloudAPI](https://apidocs.joyent.com/cloudapi/) The client side code with a dev-server. +### backend + +A simple backend for frontend that serves the static files and fallbacks to `/static/index.html`. To be used in production. + ## spikes Implementation examples from spikes. diff --git a/backend/.eslintignore b/backend/.eslintignore new file mode 100644 index 00000000..f9b9f952 --- /dev/null +++ b/backend/.eslintignore @@ -0,0 +1,4 @@ +/node_modules +coverage +.nyc_output +static \ No newline at end of file diff --git a/backend/.eslintrc b/backend/.eslintrc new file mode 100644 index 00000000..35855997 --- /dev/null +++ b/backend/.eslintrc @@ -0,0 +1,12 @@ +{ + "extends": "semistandard", + "rules": { + "space-before-function-paren": [2, "never"], + "object-curly-newline": ["error", { + "minProperties": 1 + }], + "sort-vars": ["error", { + "ignoreCase": true + }] + } +} diff --git a/backend/.tern-project b/backend/.tern-project new file mode 100644 index 00000000..6d78dea5 --- /dev/null +++ b/backend/.tern-project @@ -0,0 +1,10 @@ +{ + "libs": [ + "ecmascript" + ], + "plugins": { + "doc_comment": true, + "local-scope": true, + "node": true + } +} \ No newline at end of file diff --git a/backend/Dockerfile b/backend/Dockerfile new file mode 100644 index 00000000..cdc33c7d --- /dev/null +++ b/backend/Dockerfile @@ -0,0 +1,32 @@ +FROM node:slim + +RUN set -x \ + && apt-key adv --keyserver pgp.mit.edu --recv D101F7899D41F3C3 \ + && echo "deb http://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \ + && apt-get update && apt-get install -y git yarn --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* \ + && groupadd -g 433 -r nodejs \ + && useradd -u 431 -r -g nodejs -d /home/nodejs -s /sbin/nologin -c "Docker image user" nodejs \ + && mkdir -p /home/nodejs/ \ + && chown -R nodejs:nodejs /home/nodejs/ + +# Get and configure containerpilot +ENV CONTAINERPILOT_VERSION 2.4.1 +ENV CONTAINERPILOT file:///etc/containerpilot.json + +RUN export CP_SHA1=198d96c8d7bfafb1ab6df96653c29701510b833c \ + && curl -Lso /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 ./etc/containerpilot.json /etc/ + +USER nodejs +WORKDIR /home/nodejs/ +ADD package.json . +RUN npm install # yarn +ADD . . + +CMD [ "/bin/containerpilot", "node", "src/index.js" ] diff --git a/backend/Makefile b/backend/Makefile new file mode 100644 index 00000000..43b891a4 --- /dev/null +++ b/backend/Makefile @@ -0,0 +1,15 @@ +.PHONY: test +test: + ./node_modules/.bin/ava + +.PHONY: install +install: + npm install --quiet --no-spin + $(MAKE) compile-frontent + +# I'm not sure this is the best idea, let's see how this works out for us +# and then go with something better once we find pain points +.PHONY: compile-frontent +compile-frontent: + $(MAKE) -C ../frontend compile + cp -r ../frontend/static/* ./static diff --git a/backend/README.md b/backend/README.md new file mode 100644 index 00000000..eb9815d7 --- /dev/null +++ b/backend/README.md @@ -0,0 +1,13 @@ +# Joyent Dashboard Backend + +## start + +``` +npm run start +``` + +## test + +``` +npm run test +``` diff --git a/backend/etc/containerpilot.json b/backend/etc/containerpilot.json new file mode 100644 index 00000000..f61da1d0 --- /dev/null +++ b/backend/etc/containerpilot.json @@ -0,0 +1,14 @@ +{ + "consul": "{{ .CONSUL }}:8500", + "services": [ + { + "name": "joyent-dashboard-backend", + "port": 8000, + "health": "/usr/bin/curl -o /dev/null --fail -s http://localhost:8000/", + "poll": 3, + "ttl": 10 + } + ], + "backends": [ + ] +} diff --git a/backend/package.json b/backend/package.json new file mode 100644 index 00000000..0439a379 --- /dev/null +++ b/backend/package.json @@ -0,0 +1,24 @@ +{ + "name": "joyent-dashboard-backend", + "version": "1.0.0", + "private": true, + "license": "private", + "main": "src/index.js", + "scripts": { + "start": "node .", + "lint": "eslint .", + "open": "nyc report --reporter=html & open coverage/index.html", + "coverage": "nyc check-coverage --statements 100 --functions 100 --lines 100 --branches 100" + }, + "dependencies": { + "express": "^4.14.0", + "st": "^1.2.0" + }, + "devDependencies": { + "eslint": "^3.8.1", + "eslint-config-semistandard": "^7.0.0", + "eslint-config-standard": "^6.2.0", + "eslint-plugin-promise": "^3.3.0", + "eslint-plugin-standard": "^2.0.1" + } +} diff --git a/backend/src/index.js b/backend/src/index.js new file mode 100644 index 00000000..d4f73e28 --- /dev/null +++ b/backend/src/index.js @@ -0,0 +1,31 @@ +const path = require('path'); +const express = require('express'); +const st = require('st'); + +const app = express(); + +var mount = st({ + path: path.join(__dirname, '../static'), + url: 'static/', + index: 'index.html', + dot: false, + passthrough: false, + gzip: true, + cors: false +}); + +app.use(mount); + +app.get('/*', (req, res, next) => { + mount(Object.assign(req, { + sturl: '/static/index.html' + }), res, next); +}); + +app.listen(8000, (err, address) => { + if (err) { + throw err; + } + + console.log('Server running at: http://localhost:8000'); +}); diff --git a/docker-compose.yml b/docker-compose.yml index 2ccd71f1..fe6b2a0e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -31,3 +31,16 @@ cloudapi: - PORT=3000 ports: - 3000:3000 +############################################################################# +# Frontend +############################################################################# +cloudapi: + build: ./backend + mem_limit: 128m + labels: + - triton.cns.services=backend + env_file: .env + environment: + - PORT=8000 + ports: + - 8000:8000 diff --git a/frontend/Makefile b/frontend/Makefile index 00a4df7a..35fc320a 100644 --- a/frontend/Makefile +++ b/frontend/Makefile @@ -5,3 +5,7 @@ test: .PHONY: install install: npm install --quiet --no-spin + +.PHONY: compile +compile: install + NODE_ENV=production webpack --config webpack/index.js diff --git a/frontend/package.json b/frontend/package.json index 32903e47..1182e4b2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,5 +1,5 @@ { - "name": "joyent-dashboard", + "name": "joyent-dashboard-frontend", "version": "1.0.0", "private": true, "license": "private", diff --git a/local-compose.yml b/local-compose.yml index cd34a095..284e7af9 100644 --- a/local-compose.yml +++ b/local-compose.yml @@ -14,3 +14,13 @@ cloudapi: - PORT=3000 - ROOT_URL=http://localhost:3000 - CONSUL=consul +backend: + extends: + file: docker-compose.yml + service: backend + links: + - consul:consul + environment: + - PORT=8000 + - ROOT_URL=http://localhost:8000 + - CONSUL=consul