Browse Source

Merge pull request #21 from getumbrel/umbrelbox-compose-checks

Add in checks for docker-compose
master v0.1.0
Mayank Chhabra 4 years ago
committed by GitHub
parent
commit
3ba40624ba
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      .github/workflows/on-tag.yml
  2. 1
      .gitignore
  3. 2
      Dockerfile
  4. 33
      Dockerfile.armhf
  5. 19
      build-docker.sh
  6. 88
      buildspec.yml
  7. 27
      middlewares/auth.js
  8. 3
      package.json
  9. 4
      routes/v1/bitcoind/info.js
  10. 4
      routes/v1/lnd/info.js
  11. 4
      utils/const.js
  12. 2
      utils/logger.js
  13. 40
      wait-for-node-manager.sh

4
.github/workflows/on-tag.yml

@ -41,14 +41,14 @@ jobs:
- name: Run Docker build X (against tag)
run: |
docker buildx build \
--platform linux/amd64,linux/386,linux/arm/v7,linux/arm64 \
--platform linux/amd64,linux/arm/v7,linux/arm64 \
-t getumbrel/middleware:$TAG \
--output "type=registry" \
.
- name: Run Docker build X (against latest)
run: |
docker buildx build \
--platform linux/amd64,linux/386,linux/arm/v7,linux/arm64 \
--platform linux/amd64,linux/arm/v7,linux/arm64 \
-t getumbrel/middleware:latest \
--output "type=registry" \
.

1
.gitignore

@ -10,3 +10,4 @@ package-lock.json
lb_settings.json
.nyc_output
coverage
.todo

2
Dockerfile

@ -24,5 +24,5 @@ COPY . .
RUN mkdir -p /root/.lnd
EXPOSE 3005
EXPOSE 3006
CMD [ "npm", "start" ]

33
Dockerfile.armhf

@ -1,33 +0,0 @@
# specify the node base image with your desired version
FROM balenalib/armv7hf-node:8-stretch-run
# need qemu to emulate arm architecture
# can be downloaded here, $ docker run -v /usr/bin/qemu-arm-static:/usr/bin/qemu-arm-static --rm -ti arm32v7/debian:stretch-slim
COPY ./qemu-arm-static /usr/bin/qemu-arm-static
# install tools
RUN apt-get update --no-install-recommends \
&& apt-get install -y --no-install-recommends curl \
&& apt-get install -y --no-install-recommends rsync \
&& apt-get install -y --no-install-recommends vim \
&& rm -rf /var/lib/apt/lists/*
# Create app directory
WORKDIR /usr/src/app
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY package*.json ./
RUN npm install
# If you are building your code for production
# RUN npm install --only=production
# Bundle app source
COPY . .
RUN mkdir -p /root/.lnd
EXPOSE 3005
CMD [ "npm", "start" ]

19
build-docker.sh

@ -1,19 +0,0 @@
#!/usr/bin/env bash
if [[ "$ARCH" != "arm" && "$ARCH" != "x86" ]] ; then
echo 'Please set an ARCH to x86 or arm.'
return
fi
if [[ -z "$ENV" ]] ; then
echo 'Please set an ENV variable.'
return
fi
DOCKERFILE="Dockerfile"
if [ "$ARCH" = "arm" ]; then
DOCKERFILE="Dockerfile.armhf"
fi
docker build . -f $DOCKERFILE -t casanodeinternal/lnapi:$ARCH-$ENV
docker push casanodeinternal/lnapi:$ARCH-$ENV

88
buildspec.yml

@ -1,88 +0,0 @@
version: 0.2
env:
parameter-store:
DOCKER_HUB_USER: "/Casanode/DockerHub/User"
DOCKER_HUB_PASS: "/Casanode/DockerHub/Pass"
GITHUB_USER: "/Casanode/Git/User"
GITHUB_PASS: "/Casanode/Git/Pass"
phases:
pre_build:
commands:
- echo Installing source NPM dependencies...
- npm install
install:
commands:
# CodePipeline creates artifacts using zip format, which does not preserve the permissions/modes.
# we must reset permissions here
- chmod 755 pre-commit qemu-arm-static
build:
commands:
- echo Running tests
- if [ -z $CODECOV_TOKEN ]; then npm run test; else npm run coverage; fi
- echo Building the Docker image ...
# building
# Remove qemu-static if non-arm, or register
- |
if [ $ARCH != arm ]; then
rm qemu-arm-static
else
docker run --rm --privileged multiarch/qemu-user-static:register --reset
fi
- docker build . -f $DOCKERFILE -t $ORGANIZATION/$REPOSITORY:$ARCH
- docker tag $ORGANIZATION/$REPOSITORY:$ARCH $ORGANIZATION/$REPOSITORY:$ARCH
# Hacky way to determine what branch we are in. $CODEBUILD_SOURCE_VERSION is the git commit we are currently
# building. We search all local branches to get a list of branches that include that git commit. We return all
# alpha characters from the branch we are looking for.
#
# Ex.
# master => master
# release/1.0.0 => release
- masterBranchText=$(git branch --contains $CODEBUILD_SOURCE_VERSION | grep master | sed 's/[^a-zA-Z]//g')
- releaseBranchText=$(git branch --contains $CODEBUILD_SOURCE_VERSION | grep release | sed 's/[^a-zA-Z]//g')
- developBranchText=$(git branch --contains $CODEBUILD_SOURCE_VERSION | grep develop | sed 's/[^a-zA-Z]//g')
# push image to docker
- docker login --username=$DOCKER_HUB_USER --password=$DOCKER_HUB_PASS
# Since a git commit can be in multiple branches, we will start with master and work our way down. If a git commit
# exists in master, release, and develop, it really means we want to deploy master. Likewise, if a git commit exists
# in release and develop, we release want to deploy release.
#
# Public vs Private
# Casa Inc releases code publicly for various reasons. We also develop features in private before the public
# release. Historically we have used the private casacomputer organization on docker hub. We have since migrated
# to casanode for our public releases. We will support legacy nodes running on casacomputer until March 2020.
- |
if [ "$masterBranchText" = "master" ] && [ "$PUBLIC" = "false" ]; then
echo "pushing master branch to docker hub"
docker tag $ORGANIZATION/$REPOSITORY:$ARCH $ORGANIZATION/$REPOSITORY:$ARCH
docker push $ORGANIZATION/$REPOSITORY:$ARCH
elif [ "$masterBranchText" = "master" ] && [ "$PUBLIC" = "true" ]; then
echo "pushing master branch to docker hub"
docker tag $ORGANIZATION/$REPOSITORY:$ARCH $ORGANIZATION/$REPOSITORY:$ARCH
docker push $ORGANIZATION/$REPOSITORY:$ARCH
echo "pushing master branch to legacy docker hub"
docker tag casacomputer/$REPOSITORY:$ARCH casacomputer/$REPOSITORY:$ARCH
docker push casacomputer/$REPOSITORY:$ARCH
elif [ "$releaseBranchText" = "release" ] && [ "$PUBLIC" = "false" ]; then
echo "pushing release branch to docker hub"
docker tag $ORGANIZATION/$REPOSITORY:$ARCH $ORGANIZATION/$REPOSITORY:$ARCH-stage
docker push $ORGANIZATION/$REPOSITORY:$ARCH-stage
elif [ "$developBranchText" = "develop" ] && [ "$PUBLIC" = "false" ]; then
echo "pushing develop branch to docker hub"
docker tag $ORGANIZATION/$REPOSITORY:$ARCH $ORGANIZATION/$REPOSITORY:$ARCH-develop
docker push $ORGANIZATION/$REPOSITORY:$ARCH-develop
else
echo "docker image has been built, but not pushed to docker hub"
fi
post_build:
commands:
- echo Build completed on `date`
cache:
paths:
- 'node_modules/**/*'

27
middlewares/auth.js

@ -2,6 +2,7 @@ const passport = require('passport');
const passportJWT = require('passport-jwt');
const constants = require('utils/const.js');
const NodeError = require('models/errors.js').NodeError;
const diskService = require('services/disk.js');
var JwtStrategy = passportJWT.Strategy;
var ExtractJwt = passportJWT.ExtractJwt;
@ -12,31 +13,41 @@ passport.serializeUser(function (user, done) {
return done(null, user.id);
});
const jwtOptions = {
async function createJwtOptions() {
const pubKey = await diskService.readFile(constants.JWT_PUBLIC_KEY_FILE);
return {
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme('jwt'),
secretOrKey: Buffer.from(constants.JWT_PUBLIC_KEY, 'hex'), // The `manager` will pass the public key as hex.
secretOrKey: pubKey,
algorithm: 'RS256'
};
}
createJwtOptions().then(function (data) {
const jwtOptions = data;
passport.use(JWT_AUTH, new JwtStrategy(jwtOptions, function (jwtPayload, done) {
return done(null, { id: jwtPayload.id });
}));
});
function jwt(req, res, next) {
passport.authenticate(JWT_AUTH, { session: false }, function (error, user) {
//if (error || user === false) {
//return next(new NodeError('Invalid JWT', 401)); // eslint-disable-line no-magic-numbers
//}
if (error || user === false) {
return next(new NodeError('Invalid JWT', 401)); // eslint-disable-line no-magic-numbers
}
req.logIn(user, function (err) {
//if (err) {
//return next(new NodeError('Unable to authenticate', 401)); // eslint-disable-line no-magic-numbers
//}
if (err) {
return next(new NodeError('Unable to authenticate', 401)); // eslint-disable-line no-magic-numbers
}
return next(null, user);
});
})(req, res, next);
}
module.exports = {
jwt,
};

3
package.json

@ -1,6 +1,6 @@
{
"name": "umbrel-middleware",
"version": "0.0.5",
"version": "0.1.0",
"description": "Middleware for Umbrel Node",
"author": "Umbrel",
"scripts": {
@ -11,6 +11,7 @@
"postcoverage": "codecov"
},
"dependencies": {
"axios": "^0.19.2",
"big.js": "^5.2.2",
"bitcoind-rpc": "^0.7.2",
"body-parser": "^1.18.2",

4
routes/v1/bitcoind/info.js

@ -25,7 +25,9 @@ router.get('/connections', auth.jwt, safeHandler((req, res) =>
.then(connections => res.json(connections))
));
router.get('/status', auth.jwt, safeHandler((req, res) =>
//requires no authentication as it is used to fetch loading status
//which could be fetched at login/signup page
router.get('/status', safeHandler((req, res) =>
bitcoind.getStatus()
.then(status => res.json(status))
));

4
routes/v1/lnd/info.js

@ -11,7 +11,9 @@ router.get('/uris', auth.jwt, safeHandler((req, res) =>
.then(uris => res.json(uris))
));
router.get('/status', auth.jwt, safeHandler((req, res) =>
//requires no authentication as it is used to fetch loading status
//which could be fetched at login/signup page
router.get('/status', safeHandler((req, res) =>
lightning.getStatus()
.then(status => res.json(status))
));

4
utils/const.js

@ -5,9 +5,9 @@ module.exports = {
UNAVAILABLE: 14,
UNKNOWN: 2,
},
JWT_PUBLIC_KEY: process.env.JWT_PUBLIC_KEY || 'UNKNOWN',
JWT_PUBLIC_KEY_FILE: process.env.JWT_PUBLIC_KEY_FILE || 'UNKNOWN',
MANAGED_CHANNELS_FILE: '/channel-data/managedChannels.json',
REQUEST_CORRELATION_NAMESPACE_KEY: 'lnapi-request',
REQUEST_CORRELATION_NAMESPACE_KEY: 'umbrel-middleware-request',
REQUEST_CORRELATION_ID_KEY: 'reqId',
STATUS_CODES: {
BAD_GATEWAY: 502,

2
utils/logger.js

@ -71,7 +71,7 @@ winston.loggers.add(LOCAL, {
const morganConfiguration = {
stream: {
write: function (message) {
info(message, 'lnapi');
info(message, 'umbrel-middleware');
}
}
};

40
wait-for-node-manager.sh

@ -0,0 +1,40 @@
#!/bin/bash
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
# Usage
# ./wait-for-node-manager.sh <hostname> <command>
# Other documentation: https://docs.docker.com/compose/startup-order/
set -e
host="$1"
shift
cmd="$@"
found=1
iterations=1
until [ $found = 2 ]; do
if node -e "const axios = require('axios').default; axios.get('http://$host:3006/ping').then((resp) => {console.log(resp.data); process.exit(0); }).catch((error) => {process.exit(1) } );" ; then
echo "Can connect, lets proceed with server starting"
found=2
else
echo "Can't connect, keep trying"
fi
if [ $iterations -gt 14 ]; then
echo "Cannot connect after 15 tries, giving up"
exit 1
fi
((iterations=iterations+1))
sleep 2
done
>&2 echo "Pre-condition found, Running service"
exec $cmd
Loading…
Cancel
Save