Auto-merge for PR #470 via VersionBot

Refactor build process and switch to CircleCI
This commit is contained in:
resin-io-versionbot[bot] 2017-07-25 00:45:06 +00:00 committed by GitHub
commit 654e6ce929
26 changed files with 1070 additions and 580 deletions

View File

@ -1,13 +1,7 @@
.dockerignore
.git
node_modules
Dockerfile
Dockerfile.*
Makefile
.editorconfig
coffeelint.json
automation
tools
dindctl
README.md
retry_docker_push.sh
base-image

4
.gitignore vendored
View File

@ -1,4 +1,6 @@
/node_modules/
/automation/node_modules/
/automation/meta-resin/
*.swp
data
bin/gosuper
@ -19,3 +21,5 @@ Dockerfile.runtime.*
!Dockerfile.runtime.template
/build/
/dist/
tools/dind/config/services/docker.service.d/proxy.conf
tools/dind/supervisor-image.tar

View File

@ -4,6 +4,19 @@ All notable changes to this project will be documented in this file
automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY!
This project adheres to [Semantic Versioning](http://semver.org/).
## v6.0.2 - 2017-07-24
* Disable armel builds [Pablo Carranza Velez]
* Disable pushing to registry.resinstaging.io, and use build environment to login to dockerhub [Pablo Carranza Velez]
* Move dindctl to the base of the repository [Pablo Carranza Velez]
* Add a script to automate the creation of meta-resin PRs [Pablo Carranza Velez]
* Add a deploy-to-resin.js and automatically deploy to the Resin API on master builds [Pablo Carranza Velez]
* Use a local supervisor image for the dind supervisor [Pablo Carranza Velez]
* Replace the Jenkins build with a CircleCI build that uses the new multi-stage build [Pablo Carranza Velez]
* Make dindctl an easier to use tool that takes options instead of using env vars [Pablo Carranza Velez]
* Refactor the makefile to make it easier to use and make use of the multi-stage build [Pablo Carranza Velez]
* Add a single Dockerfile to build the supervisor as a multi-stage build [Pablo Carranza Velez]
## v6.0.1 - 2017-07-12
* Use webpack to join all modules [Pablo Carranza Velez]

207
Dockerfile Normal file
View File

@ -0,0 +1,207 @@
ARG ARCH=amd64
FROM debian:jessie as base
ARG ARCH
# Install the following utilities (required by openembedded)
# http://www.openembedded.org/wiki/Getting_started#Ubuntu_.2F_Debian
RUN apt-get -qq update \
&& apt-get -qq install -y \
build-essential \
chrpath \
cpio \
curl \
diffstat \
file \
gawk \
git-core \
libsdl1.2-dev \
locales \
python3 \
texinfo \
unzip \
wget \
xterm \
sudo \
&& rm -rf /var/lib/apt/lists/*
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV SOURCE_DIR /source
ENV DEST_DIR /dest
ENV SHARED_DOWNLOADS /yocto/shared-downloads
ENV SHARED_SSTATE /yocto/shared-sstate
ARG BUILDER_UID=1000
ARG BUILDER_GID=1000
COPY base-image /source
RUN cd /source && bash -ex build.sh
##############################################################################
# Build golang supervisor
FROM debian:jessie as gosuper
ARG ARCH
RUN apt-get update \
&& apt-get install -y \
build-essential \
curl \
rsync \
&& rm -rf /var/lib/apt/lists/
ENV GOLANG_VERSION 1.8.3
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772
COPY gosuper/go-${GOLANG_VERSION}-patches /go-${GOLANG_VERSION}-patches
RUN mkdir /usr/src/go \
&& cd /usr/src/go \
&& curl -L -o go.tar.gz $GOLANG_DOWNLOAD_URL \
&& echo "${GOLANG_DOWNLOAD_SHA256} go.tar.gz" | sha256sum -c - \
&& tar xzf go.tar.gz -C /usr/local \
&& cd /usr/src \
&& rm -rf go \
&& export GOROOT_BOOTSTRAP=/usr/local/go-bootstrap \
&& cp -r /usr/local/go /usr/local/go-bootstrap \
&& cd /usr/local/go/src \
&& patch -p2 -i /go-${GOLANG_VERSION}-patches/0001-dont-fail-when-no-mmx.patch \
&& patch -p2 -i /go-${GOLANG_VERSION}-patches/0002-implement-atomic-quadword-ops-with-FILD-FISTP.patch \
&& ./make.bash \
&& rm -rf /usr/local/go-bootstrap
ENV UPX_VERSION 3.94
# UPX doesn't provide fingerprints so I checked this one manually
ENV UPX_SHA256 e1fc0d55c88865ef758c7e4fabbc439e4b5693b9328d219e0b9b3604186abe20
RUN mkdir /usr/src/upx \
&& cd /usr/src/upx \
&& curl -L -o upx.tar.xz https://github.com/upx/upx/releases/download/v$UPX_VERSION/upx-$UPX_VERSION-amd64_linux.tar.xz \
&& echo "${UPX_SHA256} upx.tar.xz" | sha256sum -c - \
&& tar xf upx.tar.xz --strip-components=1 \
&& cp ./upx /usr/bin/ \
&& cd /usr/src \
&& rm -rf upx
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
COPY ./gosuper /go/src/resin-supervisor/gosuper
WORKDIR /go/src/resin-supervisor/gosuper
ENV GOOS linux
ENV GO386=387
RUN bash ./build.sh
RUN rsync -a --delete /go/bin/gosuper /build/
##############################################################################
# The node version here should match the version of the runtime image which is
# specified in the base-image subdirectory in the project
FROM resin/rpi-node:6.5-slim as rpi-node-base
FROM resin/armv7hf-node:6.5-slim as armv7hf-node-base
FROM resin/armel-node:6.5-slim as armel-node-base
FROM resin/aarch64-node:6.5-slim as aarch64-node-base
FROM resin/amd64-node:6.5-slim as amd64-node-base
RUN echo '#!/bin/sh\nexit 0' > /usr/bin/cross-build-start && chmod +x /usr/bin/cross-build-start \
&& echo '#!/bin/sh\nexit 0' > /usr/bin/cross-build-end && chmod +x /usr/bin/cross-build-end
FROM resin/i386-node:6.5-slim as i386-node-base
RUN echo '#!/bin/sh\nexit 0' > /usr/bin/cross-build-start && chmod +x /usr/bin/cross-build-start \
&& echo '#!/bin/sh\nexit 0' > /usr/bin/cross-build-end && chmod +x /usr/bin/cross-build-end
# Build nodejs dependencies
FROM $ARCH-node-base as node
ARG ARCH
RUN [ "cross-build-start" ]
WORKDIR /usr/src/app
RUN apt-get update \
&& apt-get install -y \
g++ \
libsqlite3-dev \
make \
python \
rsync \
wget \
&& rm -rf /var/lib/apt/lists/
RUN mkdir -p rootfs-overlay && \
ln -s /lib rootfs-overlay/lib64
COPY package.json /usr/src/app/
# Install only the production modules that have C extensions
RUN JOBS=MAX npm install --production --no-optional --unsafe-perm \
&& npm dedupe
COPY webpack.config.js remove-hashbang-loader.js /usr/src/app/
COPY src /usr/src/app/src
# Install devDependencies, build the coffeescript and then prune the deps
RUN cp -R node_modules node_modules_prod \
&& npm install --no-optional --unsafe-perm \
&& npm run lint \
&& npm run build \
&& rm -rf node_modules \
&& mv node_modules_prod node_modules
# Remove various uneeded filetypes in order to reduce space
RUN find . -path '*/coverage/*' -o -path '*/test/*' -o -path '*/.nyc_output/*' \
-o -name '*.tar.*' -o -name '*.in' -o -name '*.cc' \
-o -name '*.c' -o -name '*.coffee' -o -name '*.eslintrc' \
-o -name '*.h' -o -name '*.html' -o -name '*.markdown' \
-o -name '*.md' -o -name '*.patch' -o -name '*.png' \
-o -name '*.yml' \
-delete \
&& find . -type f -path '*/node_modules/sqlite3/deps*' -delete \
&& find . -type f -path '*/node_modules/knex/build*' -delete
# Create /var/run/resin for the gosuper to place its socket in
RUN mkdir -p rootfs-overlay/var/run/resin
COPY entry.sh run.sh package.json rootfs-overlay/usr/src/app/
COPY inittab rootfs-overlay/etc/inittab
RUN rsync -a --delete node_modules dist rootfs-overlay /build
RUN [ "cross-build-end" ]
##############################################################################
# Minimal runtime image
FROM scratch
ARG ARCH
ARG VERSION=master
ARG DEFAULT_PUBNUB_PUBLISH_KEY=pub-c-bananas
ARG DEFAULT_PUBNUB_SUBSCRIBE_KEY=sub-c-bananas
ARG DEFAULT_MIXPANEL_TOKEN=bananasbananas
COPY --from=base /dest/ /
WORKDIR /usr/src/app
COPY --from=node /build/dist ./dist
COPY --from=node /build/node_modules ./node_modules
COPY --from=gosuper /build/gosuper ./gosuper
COPY --from=node /build/rootfs-overlay/ /
VOLUME /data
ENV CONFIG_MOUNT_POINT=/boot/config.json \
LED_FILE=/dev/null \
SUPERVISOR_IMAGE=resin/$ARCH-supervisor \
VERSION=$VERSION \
DEFAULT_PUBNUB_PUBLISH_KEY=$DEFAULT_PUBNUB_PUBLISH_KEY \
DEFAULT_PUBNUB_SUBSCRIBE_KEY=$DEFAULT_PUBNUB_SUBSCRIBE_KEY \
DEFAULT_MIXPANEL_TOKEN=$DEFAULT_MIXPANEL_TOKEN
CMD [ "/sbin/init" ]

View File

@ -1,60 +0,0 @@
# Build nodejs dependencies
# The node version here should match the version of the runtime image which is
# specified in the base-image subdirectory in the project
FROM resin/%%ARCH%%-node:6.5-slim
WORKDIR /usr/src/app
RUN apt-get update \
&& apt-get install -y \
g++ \
libsqlite3-dev \
make \
python \
rsync \
wget \
&& rm -rf /var/lib/apt/lists/
RUN mkdir -p rootfs-overlay && \
ln -s /lib rootfs-overlay/lib64
COPY package.json /usr/src/app/
# Install only the production modules that have C extensions
RUN JOBS=MAX npm install --production --no-optional --unsafe-perm \
&& npm dedupe
COPY webpack.config.js remove-hashbang-loader.js /usr/src/app/
COPY src /usr/src/app/src
# Install devDependencies, build the coffeescript and then prune the deps
RUN cp -R node_modules node_modules_prod \
&& npm install --no-optional --unsafe-perm \
&& npm run lint \
&& npm run build \
&& rm -rf node_modules \
&& mv node_modules_prod node_modules
# Remove various uneeded filetypes in order to reduce space
RUN find . -path '*/coverage/*' -o -path '*/test/*' -o -path '*/.nyc_output/*' \
-o -name '*.tar.*' -o -name '*.in' -o -name '*.cc' \
-o -name '*.c' -o -name '*.coffee' -o -name '*.eslintrc' \
-o -name '*.h' -o -name '*.html' -o -name '*.markdown' \
-o -name '*.md' -o -name '*.patch' -o -name '*.png' \
-o -name '*.yml' \
-delete \
&& find . -type f -path '*/node_modules/sqlite3/deps*' -delete \
&& find . -type f -path '*/node_modules/knex/build*' -delete
# Create /var/run/resin for the gosuper to place its socket in
RUN mkdir -p rootfs-overlay/var/run/resin
COPY entry.sh run.sh package.json rootfs-overlay/usr/src/app/
COPY inittab rootfs-overlay/etc/inittab
CMD rsync -a --delete node_modules dist rootfs-overlay /build
# -*- mode: dockerfile -*-
# vi: set ft=dockerfile :

View File

@ -1,20 +0,0 @@
# Minimal runtime image
FROM %%BASE_IMAGE_TAG%%
WORKDIR /usr/src/app
COPY ./build/%%ARCH%%/dist ./dist
COPY ./build/%%ARCH%%/node_modules ./node_modules
COPY ./build/%%ARCH%%/gosuper ./gosuper
COPY ./build/%%ARCH%%/rootfs-overlay/ /
VOLUME /data
ENV CONFIG_MOUNT_POINT=/boot/config.json \
LED_FILE=/dev/null \
SUPERVISOR_IMAGE=resin/%%ARCH%%-supervisor
CMD [ "/sbin/init" ]
# -*- mode: dockerfile -*-
# vi: set ft=dockerfile :

204
Makefile
View File

@ -1,5 +1,44 @@
# resin-supervisor Makefile
#
# If you're looking for an easy way to develop on the supervisor, check ./tools/dev/dindctl, which provides a simplified interface
# to this makefile.
#
# Build targets (require Docker 17.05 or greater):
# * supervisor (default) - builds a resin-supervisor image
# * deploy - pushes a resin-supervisor image to the registry, retrying up to 3 times
# * base - builds the "base" component (a yocto builder with the output rootfs at /dest)
# * gosuper - builds the "gosuper" component (a golang image with the Go supervisor component at /go/bin/gosuper and /build/gosuper)
# * nodesuper - builds the node component, with the node_modules and src at /usr/src/app and /build (also includes a rootfs-overlay there)
# * supervisor-dind: build the development docker-in-docker supervisor that run-supervisor uses (requires a SUPERVISOR_IMAGE to be available locally)
#
# Variables for build targets:
# * ARCH: amd64/rpi/i386/armv7hf/armel/aarch64 architecture for which to build the supervisor - default: amd64
# * IMAGE: image to build or deploy - default: resin/$(ARCH)-supervisor:latest
# * MIXPANEL_TOKEN, PUBNUB_SUBSCRIBE_KEY, PUBNUB_PUBLISH_KEY: (optional) default pubnub and mixpanel keys to embed in the supervisor image
# * DISABLE_CACHE: if set to true, run build with no cache - default: false
# * DOCKER_BUILD_OPTIONS: Additional options for docker build, like --cache-from parameters
#
# Test/development targets:
# * run-supervisor, stop-supervisor - build and start or stop a docker-in-docker resin-supervisor (requires aufs, ability to run privileged containers, and a SUPERVISOR_IMAGE to be available locally)
# * format-gosuper, test-gosuper - build a gosuper image and run formatting or unit tests
# * test-integration - run an integration test (see gosuper/supertest). Requires a docker-in-docker supervisor to be running
#
# Variables for test/dev targets:
# * IMAGE: image to build and run (either for run-supervisor or test-gosuper/integration)
# * SUPERVISOR_IMAGE: In run-supervisor and supervisor-dind, the supervisor image to run inside the docker-in-docker image
# * PRELOADED_IMAGE: If true, will preload user app image from tools/dev/apps.json and bind mount apps.json into the docker-in-docker supervisor
# * SUPERVISOR_EXTRA_MOUNTS: Additional bind mount flags for the docker-in-docker supervisor
# * PASSWORDLESS_DROPBEAR: For run-supervisor - start a passwordless ssh daemon in the docker-in-docker supervisor
#
THIS_FILE := $(lastword $(MAKEFILE_LIST))
help:
@cat $(THIS_FILE) | awk '{if(/^#/)print;else exit}' | sed 's/\#//'
OS := $(shell uname)
# If we're behind a proxy, use it during build
ifdef http_proxy
DOCKER_HTTP_PROXY=--build-arg http_proxy=$(http_proxy)
endif
@ -18,74 +57,48 @@ ifdef use_proxy_at_runtime
rt_no_proxy=$(no_proxy)
endif
DISABLE_CACHE = 'false'
ARCH = rpi# rpi/amd64/i386/armv7hf/armel/aarch64
DEPLOY_REGISTRY =
SUPERVISOR_VERSION = master
BASE_IMAGE_VERSION = $(shell find base-image -print0 | LC_ALL=C sort -z | tar --null -cf - --no-recursion --mtime=@0 --owner=root --group=root --numeric-owner -T - | md5sum | awk -F " " '{print $$1}')
ESCAPED_BASE_IMAGE_TAG = resin\/$(ARCH)-supervisor-base:$(BASE_IMAGE_VERSION)
DISABLE_CACHE ?= 'false'
DOCKER_VERSION:=$(shell docker version --format '{{.Server.Version}}')
DOCKER_MAJOR_VERSION:=$(word 1, $(subst ., ,$(DOCKER_VERSION)))
DOCKER_MINOR_VERSION:=$(word 2, $(subst ., ,$(DOCKER_VERSION)))
DOCKER_GE_1_12 := $(shell [ $(DOCKER_MAJOR_VERSION) -gt 1 -o \( $(DOCKER_MAJOR_VERSION) -eq 1 -a $(DOCKER_MINOR_VERSION) -ge 12 \) ] && echo true)
DOCKER_GE_17_05 := $(shell [ $(DOCKER_MAJOR_VERSION) -gt 17 -o \( $(DOCKER_MAJOR_VERSION) -eq 17 -a $(DOCKER_MINOR_VERSION) -ge 5 \) ] && echo true)
# In docker 1.12 tag --force has been removed.
ifeq ($(DOCKER_GE_1_12),true)
DOCKER_TAG_FORCE=
else
DOCKER_TAG_FORCE=-f
endif
# Default values for Pubnub and Mixpanel keys
PUBNUB_SUBSCRIBE_KEY ?= sub-c-bananas
PUBNUB_PUBLISH_KEY ?= pub-c-bananas
MIXPANEL_TOKEN ?= bananasbananas
all: supervisor
# Default architecture and output image
ARCH ?= amd64
IMAGE ?= resin/$(ARCH)-supervisor:master
PUBNUB_SUBSCRIBE_KEY = sub-c-bananas
PUBNUB_PUBLISH_KEY = pub-c-bananas
MIXPANEL_TOKEN = bananasbananas
# Default values for run-supervisor
SUPERVISOR_IMAGE ?= resin/$(ARCH)-supervisor:master
PASSWORDLESS_DROPBEAR ?= false
PASSWORDLESS_DROPBEAR = false
IMAGE = "resin/$(ARCH)-supervisor:$(SUPERVISOR_VERSION)"
DOCKERFILE = $(ARCH)
SUPERVISOR_IMAGE=$(DEPLOY_REGISTRY)$(IMAGE)
ifeq ($(ARCH),rpi)
GOARCH = arm
GOARM = 6
endif
ifeq ($(ARCH),armv7hf)
GOARCH = arm
GOARM = 7
endif
ifeq ($(ARCH),armel)
GOARCH = arm
GOARM = 5
endif
ifeq ($(ARCH),i386)
GOARCH = 386
endif
ifeq ($(ARCH),amd64)
GOARCH = amd64
endif
ifeq ($(ARCH),aarch64)
GOARCH = arm64
endif
# Bind mounts and variables for the run-supervisor target
SUPERVISOR_DIND_MOUNTS := -v $$(pwd)/../../:/resin-supervisor -v $$(pwd)/config.json:/mnt/conf/config.json -v $$(pwd)/config/env:/usr/src/app/config/env -v $$(pwd)/config/localenv:/usr/src/app/config/localenv
ifeq ($(OS), Linux)
SUPERVISOR_DIND_MOUNTS := ${SUPERVISOR_DIND_MOUNTS} -v /sys/fs/cgroup:/sys/fs/cgroup:ro -v /bin/kmod:/bin/kmod
endif
ifdef PRELOADED_IMAGE
ifeq ($(PRELOADED_IMAGE),true)
SUPERVISOR_DIND_MOUNTS := ${SUPERVISOR_DIND_MOUNTS} -v $$(pwd)/apps.json:/usr/src/app/config/apps.json
else
PRELOADED_IMAGE=
endif
SUPERVISOR_EXTRA_MOUNTS ?=
SUPERVISOR_EXTRA_MOUNTS =
ifdef TARGET_COMPONENT
DOCKER_TARGET_COMPONENT := "--target=${TARGET_COMPONENT}"
else
DOCKER_TARGET_COMPONENT :=
endif
# Default target is to build the supervisor image
all: supervisor
# Settings to make the run-supervisor target work behind a proxy
DOCKERD_PROXY=tools/dind/config/services/docker.service.d/proxy.conf
${DOCKERD_PROXY}:
rm -f ${DOCKERD_PROXY}
@ -107,15 +120,19 @@ ${DOCKERD_PROXY}:
touch ${DOCKERD_PROXY}; \
fi
supervisor-dind: ${DOCKERD_PROXY}
supervisor-tar:
docker save --output tools/dind/supervisor-image.tar $(SUPERVISOR_IMAGE)
supervisor-dind: ${DOCKERD_PROXY} supervisor-tar
cd tools/dind \
&& docker build \
$(DOCKER_HTTP_PROXY) \
$(DOCKER_HTTPS_PROXY) \
$(DOCKER_NO_PROXY) \
${DOCKER_BUILD_OPTIONS} \
--no-cache=$(DISABLE_CACHE) \
--build-arg PASSWORDLESS_DROPBEAR=$(PASSWORDLESS_DROPBEAR) \
-t resin/resin-supervisor-dind:$(SUPERVISOR_VERSION) .
-t $(IMAGE) .
run-supervisor: stop-supervisor supervisor-dind
cd tools/dind \
@ -133,7 +150,7 @@ run-supervisor: stop-supervisor supervisor-dind
if [ -n "$(rt_no_proxy)" ]; then \
echo "no_proxy=$(rt_no_proxy)" >> config/localenv; \
fi \
&& docker run -d --name resin_supervisor_1 --privileged ${SUPERVISOR_DIND_MOUNTS} resin/resin-supervisor-dind:$(SUPERVISOR_VERSION)
&& docker run -d --name resin_supervisor_1 --privileged ${SUPERVISOR_DIND_MOUNTS} $(IMAGE)
stop-supervisor:
# Stop docker and remove volumes to prevent us from running out of loopback devices,
@ -142,81 +159,53 @@ stop-supervisor:
-docker stop resin_supervisor_1 > /dev/null || true
-docker rm -f --volumes resin_supervisor_1 > /dev/null || true
refresh-supervisor-src:
echo " * Compiling CoffeeScript.." \
&& coffee -c ./src \
&& echo " * Restarting supervisor container.." \
&& docker exec -ti resin_supervisor_1 docker restart resin_supervisor
supervisor: nodesuper gosuper
sed 's/%%ARCH%%/$(ARCH)/g' Dockerfile.runtime.template | sed 's/%%BASE_IMAGE_TAG%%/$(ESCAPED_BASE_IMAGE_TAG)/g' > Dockerfile.runtime.$(ARCH)
echo "ENV VERSION=$(shell jq -r .version package.json) \\" >> Dockerfile.runtime.$(ARCH)
echo " DEFAULT_PUBNUB_PUBLISH_KEY=$(PUBNUB_PUBLISH_KEY) \\" >> Dockerfile.runtime.$(ARCH)
echo " DEFAULT_PUBNUB_SUBSCRIBE_KEY=$(PUBNUB_SUBSCRIBE_KEY) \\" >> Dockerfile.runtime.$(ARCH)
echo " DEFAULT_MIXPANEL_TOKEN=$(MIXPANEL_TOKEN)" >> Dockerfile.runtime.$(ARCH)
ifdef rt_https_proxy
echo "ENV HTTPS_PROXY=$(rt_https_proxy) \\" >> Dockerfile.runtime.$(ARCH)
echo " https_proxy=$(rt_https_proxy)" >> Dockerfile.runtime.$(ARCH)
endif
ifdef rt_http_proxy
echo "ENV HTTP_PROXY=$(rt_http_proxy) \\" >> Dockerfile.runtime.$(ARCH)
echo " http_proxy=$(rt_http_proxy)" >> Dockerfile.runtime.$(ARCH)
endif
ifdef rt_no_proxy
echo "ENV no_proxy=$(rt_no_proxy)" >> Dockerfile.runtime.$(ARCH)
supervisor-image:
ifneq ($(DOCKER_GE_17_05),true)
@echo "Docker >= 17.05 is needed to build the supervisor"
@exit 1
endif
docker build \
$(DOCKER_HTTP_PROXY) \
$(DOCKER_HTTPS_PROXY) \
$(DOCKER_NO_PROXY) \
-f Dockerfile.runtime.$(ARCH) \
--pull \
$(DOCKER_TARGET_COMPONENT) \
$(DOCKER_BUILD_OPTIONS) \
--no-cache=$(DISABLE_CACHE) \
--build-arg ARCH=$(ARCH) \
--build-arg VERSION=$(shell jq -r .version package.json) \
--build-arg DEFAULT_PUBNUB_PUBLISH_KEY=$(PUBNUB_PUBLISH_KEY) \
--build-arg DEFAULT_PUBNUB_SUBSCRIBE_KEY=$(PUBNUB_SUBSCRIBE_KEY) \
--build-arg DEFAULT_MIXPANEL_TOKEN=$(MIXPANEL_TOKEN) \
-t $(IMAGE) .
lint:
docker run --rm resin/node-supervisor-$(ARCH):$(SUPERVISOR_VERSION) bash -c 'npm install resin-lint && npm run lint'
supervisor:
@$(MAKE) -f $(THIS_FILE) IMAGE=$(IMAGE) ARCH=$(ARCH) supervisor-image
deploy: supervisor
docker tag $(DOCKER_TAG_FORCE) $(IMAGE) $(SUPERVISOR_IMAGE)
bash retry_docker_push.sh $(SUPERVISOR_IMAGE)
deploy:
@bash retry_docker_push.sh $(IMAGE)
base:
$(MAKE) -f $(THIS_FILE) TARGET_COMPONENT=base IMAGE=$(IMAGE) ARCH=$(ARCH) supervisor-image
nodesuper:
sed 's/%%ARCH%%/$(ARCH)/g' Dockerfile.build.template > Dockerfile.build.$(ARCH)
docker build --pull \
$(DOCKER_HTTP_PROXY) \
$(DOCKER_HTTPS_PROXY) \
$(DOCKER_NO_PROXY) \
-f Dockerfile.build.$(ARCH) \
-t resin/node-supervisor-$(ARCH):$(SUPERVISOR_VERSION) .
docker run --rm \
-v `pwd`/build/$(ARCH):/build \
resin/node-supervisor-$(ARCH):$(SUPERVISOR_VERSION)
$(MAKE) -f $(THIS_FILE) TARGET_COMPONENT=node IMAGE=$(IMAGE) ARCH=$(ARCH) supervisor-image
gosuper:
cd gosuper && docker build --pull \
$(DOCKER_HTTP_PROXY) \
$(DOCKER_HTTPS_PROXY) \
$(DOCKER_NO_PROXY) \
--build-arg GOARCH=$(GOARCH) \
--build-arg GOARM=$(GOARM) \
-t resin/go-supervisor-$(ARCH):$(SUPERVISOR_VERSION) .
docker run --rm \
-v `pwd`/build/$(ARCH):/build \
resin/go-supervisor-$(ARCH):$(SUPERVISOR_VERSION)
$(MAKE) -f $(THIS_FILE) TARGET_COMPONENT=gosuper IMAGE=$(IMAGE) ARCH=$(ARCH) supervisor-image
test-gosuper: gosuper
docker run \
--rm \
-v /var/run/dbus:/mnt/root/run/dbus \
-e DBUS_SYSTEM_BUS_ADDRESS="/mnt/root/run/dbus/system_bus_socket" \
resin/go-supervisor-$(ARCH):$(SUPERVISOR_VERSION) bash -c \
$(IMAGE) bash -c \
'./test_formatting.sh && go test -v ./gosuper'
format-gosuper: gosuper
docker run \
--rm \
-v $(shell pwd)/gosuper:/go/src/resin-supervisor/gosuper \
resin/go-supervisor-$(ARCH):$(SUPERVISOR_VERSION) \
$(IMAGE) \
go fmt ./...
test-integration: gosuper
@ -227,10 +216,7 @@ test-integration: gosuper
--volumes-from resin_supervisor_1 \
-v /var/run/dbus:/mnt/root/run/dbus \
-e DBUS_SYSTEM_BUS_ADDRESS="/mnt/root/run/dbus/system_bus_socket" \
resin/go-supervisor-$(ARCH):$(SUPERVISOR_VERSION) \
$(IMAGE) \
go test -v ./supertest
base-image-version:
@echo $(BASE_IMAGE_VERSION)
.PHONY: supervisor deploy supervisor-dind run-supervisor gosuper nodesuper
.PHONY: supervisor deploy base nodesuper gosuper supervisor-dind run-supervisor

View File

@ -10,31 +10,26 @@ We are using [waffle.io](https://waffle.io) to manage our tickets / issues, so i
## Running supervisor locally
### Deploy your local version to a Docker registry
### Build a local supervisor image
We'll show how to use the DockerHub registry, but any other can be specified as part of the `SUPERVISOR_IMAGE` variable.
If you haven't done so yet, login to the registry:
Build the supervisor with a specific repo and tag, e.g.
```bash
docker login
./tools/dev/dindctl build --image username/resin-supervisor:master --arch amd64
```
Use your username and password as required.
Then deploy to a specific repo and tag, e.g.
```bash
make ARCH=amd64 SUPERVISOR_IMAGE=username/resin-supervisor:master deploy
```
This will build the Supervisor docker image if you haven't done it yet, and upload it to the registry.
As we pointed out before, a different registry can be specified with the DEPLOY_REGISTRY env var.
This will build the Supervisor docker image locally. If you then run `docker images` you should see the repo/tag you
set there.
### Set up config.json
Add `tools/dind/config.json` file from a staging device image.
Add a `tools/dind/config.json` file from a staging device image. It should be configured for an x86 or amd64 device type so that you can push apps to it and they run properly on your computer.
Note: don't use resinstaging for production devices. This is for development purposes only. A production (resin.io) config.json should work just as fine for this local supervisor, but we also don't recommend using this in production scenarios - ResinOS is way better suited for that.
A config.json file can be obtained in several ways, for instance:
* Download an Intel Edison image from staging, open `config.img` with an archive tool like [peazip](http://sourceforge.net/projects/peazip/files/)
* Download a Raspberry Pi 2 image, flash it to an SD card, then mount partition 5 (resin-conf).
* Install Resin CLI with `npm install -g resin-cli`, then login with `resin login` and finally run `resin config generate --app <appName> -o config.json` (choose the default settings whenever prompted). Check [this section](https://github.com/resin-io/resin-cli#how-do-i-point-the-resin-cli-to-staging) on how to point Resin CLI to a device on staging.
* Log in to the dashboard on resinstaging (https://dashboard.resinstaging.io), create or select an application, click "Download OS" and on the Advanced section select "Download configuration only".
* Install the Resin CLI with `npm install -g resin-cli`, then login with `resin login` and finally run `resin config generate --app <appName> -o config.json` (choose the default settings whenever prompted). Check [this section](https://github.com/resin-io/resin-cli#how-do-i-point-the-resin-cli-to-staging) on how to point Resin CLI to a device on staging.
The config.json file should look something like this:
@ -46,30 +41,45 @@ The config.json file should look something like this:
"userId": "141", /* User ID for the user who owns the app */
"username": "gh_pcarranzav", /* User name for the user who owns the app */
"deviceType": "intel-edison", /* The device type corresponding to the test application */
"files": { /* This field is used by the host OS on devices, so the supervisor doesn't care about it */
"network/settings": "[global]\nOfflineMode=false\n\n[WiFi]\nEnable=true\nTethering=false\n\n[Wired]\nEnable=true\nTethering=false\n\n[Bluetooth]\nEnable=true\nTethering=false",
"network/network.config": "[service_home_ethernet]\nType = ethernet\nNameservers = 8.8.8.8,8.8.4.4"
},
"apiEndpoint": "https://api.resinstaging.io", /* Endpoint for the Resin API */
"registryEndpoint": "registry.resinstaging.io", /* Endpoint for the Resin registry */
"deltaEndpoint": "https://delta.resinstaging.io", /* Endpoint for the delta server to download docker binary diffs */
"vpnEndpoint": "vpn.resinstaging.io", /* Endpoint for the Resin VPN server */
"pubnubSubscribeKey": "sub-c-aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", /* Subscribe key for Pubnub for logs */
"pubnubPublishKey": "pub-c-aaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", /* Publish key for Pubnub for logs */
"listenPort": 48484, /* Listen port for the supervisor API */
"mixpanelToken": "aaaaaaaaaaaaaaaaaaaaaaaaaa", /* Mixpanel token to report events */
"files": { /* This field is used by the host OS on devices, so the supervisor doesn't care about it */
"network/settings": "[global]\nOfflineMode=false\n\n[WiFi]\nEnable=true\nTethering=false\n\n[Wired]\nEnable=true\nTethering=false\n\n[Bluetooth]\nEnable=true\nTethering=false",
"network/network.config": "[service_home_ethernet]\nType = ethernet\nNameservers = 8.8.8.8,8.8.4.4"
},
"registryEndpoint": "registry.resinstaging.io", /* Endpoint for the Resin registry, not used by the latest supervisor versions */
}
```
Additionally, the `uuid`, `registered_at` and `deviceId` fields will be added by the supervisor upon registration with the resin API.
Additionally, the `uuid`, `registered_at` and `deviceId` fields will be added by the supervisor upon registration with the resin API. Other fields may be present (the format has evolved over time and will likely continue to do so).
### Start the supervisor instance
Ensure your kernel supports aufs (in Ubuntu, install `linux-image-extra-$(uname -r)`) and the `aufs` module is loaded (if necessary, run `sudo modprobe aufs`).
```bash
ARCH=amd64 SUPERVISOR_IMAGE=username/resin-supervisor:master ./tools/dev/dindctl run
./tools/dev/dindctl run --image username/resin-supervisor:master
```
This will setup a docker-in-docker instance with an image that runs the supervisor image.
This will setup a docker-in-docker instance with an image that runs the supervisor image. The image has to be available
locally, either because you built it as described above, or because you pulled it before running `dindctl run`.
If you want to develop and test your changes, you can run:
```bash
./tools/dev/dindctl run --image username/resin-supervisor:master --mount-dist
```
This will mount the ./dist folder into the supervisor container, so that any changes you make can be added to the running supervisor with:
```bash
./tools/dev/dindctl refresh
```
### Testing with preloaded apps
To test preloaded apps, add a `tools/dind/apps.json` file according to the preloaded apps spec.
@ -93,8 +103,7 @@ Make sure the config.json file doesn't have uuid, registered_at or deviceId popu
Then run the supervisor like this:
```bash
make ARCH=amd64 PRELOADED_IMAGE=true \
SUPERVISOR_IMAGE=username/resin-supervisor:master run-supervisor
./tools/dev/dindctl run --image username/resin-supervisor:master --preload
```
This will make the docker-in-docker instance pull the image specified in apps.json before running the supervisor.
@ -123,34 +132,26 @@ docker exec -it resin_supervisor_1 journalctl -f
This will stop the container and remove it, also removing its volumes.
## Working with the Go supervisor
The Dockerfile used to build the Go supervisor is Dockerfile.gosuper, and the code for the Go supervisor lives in the `gosuper` directory.
To build it, run:
The code for the Go supervisor lives in the `gosuper` directory.
To build it, run (with the ARCH and IMAGE you want):
```bash
make ARCH=amd64 gosuper
make ARCH=amd64 IMAGE=username/gosuper:master gosuper
```
This will build and run the docker image that builds the Go supervisor and outputs the executable at `gosuper/bin`.
This will build a docker image that builds the Go supervisor and has the executable at /go/bin/gosuper inside the image.
### Adding Go dependencies
This project uses [Godep](https://github.com/tools/godep) to manage its Go dependencies. In order for it to work, this repo needs to be withing the `src` directory in a valid Go workspace. This can easily be achieved by having the repo as a child of a directory named `src` and setting the `GOPATH` environment variable to such directory's parent.
This project uses [glide](https://github.com/Masterminds/glide) to manage its Go dependencies. Refer to its repository for instructions on adding packages.
If these conditions are met, a new dependency can be added with:
```bash
go get github.com/path/to/dependency
```
Then we add the corresponding import statement in our code (e.g. main.go):
```go
import "github.com/path/to/dependency"
```
And we save it to Godeps.json with:
```bash
cd gosuper
godep save -r ./...
```
(The -r switch will modify the import statement to use Godep's `_workspace`)
In order for go utilities to work, this repo needs to be within the `src` directory in a valid Go workspace. This can easily be achieved by having the repo as a child of a directory named `src` and setting the `GOPATH` environment variable to such directory's parent.
## Testing
We're working on adding more tests to this repo, but here's what you can run in the meantime:
### Gosuper
The Go supervisor can be tested by running:
```bash
make ARCH=amd64 test-gosuper
@ -164,6 +165,7 @@ Once it's running, you can run the test with:
```bash
make ARCH=amd64 test-integration
```
The tests will fail if the supervisor API is down - bear in mind that the supervisor image takes a while to start the actual supervisor program, so you might have to wait a few minutes between running the supervisor and testing it.
The test expects the supervisor to be already running the application (so that the app is already on the SQLite database), so check the dashboard to see if the app has already downloaded.

147
automation/build.sh Executable file
View File

@ -0,0 +1,147 @@
#!/bin/bash
#
# resin-supervisor automated build
#
# Required variables:
# * ARCH
# * TAG
#
# Optional variables:
# * PUSH_IMAGES
# * CLEANUP
# * ENABLE_TESTS
# * PUBNUB_SUBSCRIBE_KEY, PUBNUB_PUBLISH_KEY, MIXPANEL_TOKEN: default keys to inject in the supervisor image
# * EXTRA_TAG: when PUSH_IMAGES is true, additional tag to push to the registries
#
# Builds the supervisor for the architecture defined by $ARCH.
# Will produce and push an image tagged as resin/$ARCH-supervisor:$TAG
#
# It pulls intermediate images for caching, if available:
# resin/$ARCH-supervisor-base:$TAG
# resin/$ARCH-supervisor-node:$TAG
# resin/$ARCH-supervisor-go:$TAG
#
# In all of these cases it will use "master" if $TAG is not found.
#
# If PUSH_IMAGES is "true", it will also push the supervisor and intermediate images (must be logged in to dockerhub)
# to the docker registry.
# If CLEANUP is "true", all images will be removed after pushing - including any relevant images
# that may have been on the host from before the build, so be careful!
# If ENABLE_TESTS is "true", tests will be run.
#
# Requires docker >= 17.05, and make.
#
# If you just cloned the repo, run this to populate the yocto dependencies before running this script:
# git submodule update --init --recursive
# git clean -fxd base-image
# git submodule foreach --recursive git clean -fxd
#
set -e
THIS_FILE=$0
if [ -z "$ARCH" ] || [ -z "$TAG" ]; then
cat $THIS_FILE | awk '{if(/^#/)print;else exit}' | tail -n +2 | sed 's/\#//'
exit 1
fi
function tryRemove() {
docker rmi $1 || true
}
# This is the supervisor image we will produce
TARGET_IMAGE=resin/$ARCH-supervisor:$TAG
# Intermediate images and cache
BASE_IMAGE=resin/$ARCH-supervisor-base:$TAG
NODE_IMAGE=resin/$ARCH-supervisor-node:$TAG
GO_IMAGE=resin/$ARCH-supervisor-go:$TAG
TARGET_CACHE=$TARGET_IMAGE
BASE_CACHE=$BASE_IMAGE
GO_CACHE=$GO_IMAGE
NODE_CACHE=$NODE_IMAGE
CACHE_FROM=""
# Attempt to pull images for cache
# Only if the pull succeeds we add a --cache-from option
docker pull $TARGET_CACHE || {
TARGET_CACHE=resin/$ARCH-supervisor:master
docker pull $TARGET_CACHE
} && {
CACHE_FROM="$CACHE_FROM --cache-from $TARGET_CACHE"
} || true
docker pull $BASE_CACHE || {
BASE_CACHE=resin/$ARCH-supervisor-base:master
docker pull $BASE_CACHE
} && {
CACHE_FROM="$CACHE_FROM --cache-from $BASE_CACHE"
} || true
docker pull $NODE_CACHE || {
NODE_CACHE=resin/$ARCH-supervisor-node:master
docker pull $NODE_CACHE
} && {
CACHE_FROM="$CACHE_FROM --cache-from $NODE_CACHE"
} || true
docker pull $GO_CACHE || {
GO_CACHE=resin/$ARCH-supervisor-go:master
docker pull $GO_CACHE
} && {
CACHE_FROM="$CACHE_FROM --cache-from $GO_CACHE"
} || true
if [ "$ENABLE_TESTS" = "true" ]; then
make ARCH=$ARCH IMAGE=$GO_IMAGE test-gosuper
fi
export DOCKER_BUILD_OPTIONS=${CACHE_FROM}
export ARCH
export PUBNUB_PUBLISH_KEY
export PUBNUB_SUBSCRIBE_KEY
export MIXPANEL_TOKEN
make IMAGE=$BASE_IMAGE base
if [ "$PUSH_IMAGES" = "true" ]; then
make IMAGE=$BASE_IMAGE deploy || true
fi
export DOCKER_BUILD_OPTIONS="${DOCKER_BUILD_OPTIONS} --cache-from ${BASE_IMAGE}"
make IMAGE=$GO_IMAGE gosuper
if [ "$PUSH_IMAGES" = "true" ]; then
make IMAGE=$GO_IMAGE deploy || true
fi
export DOCKER_BUILD_OPTIONS="${DOCKER_BUILD_OPTIONS} --cache-from ${GO_IMAGE}"
make IMAGE=$NODE_IMAGE nodesuper
if [ "$PUSH_IMAGES" = "true" ]; then
make IMAGE=$NODE_IMAGE deploy || true
fi
export DOCKER_BUILD_OPTIONS="${DOCKER_BUILD_OPTIONS} --cache-from ${NODE_IMAGE}"
# This is the step that actually builds the supervisor
make IMAGE=$TARGET_IMAGE supervisor
if [ "$PUSH_IMAGES" = "true" ]; then
make IMAGE=$TARGET_IMAGE deploy
if [ -n "$EXTRA_TAG" ]; then
docker tag $TARGET_IMAGE resin/$ARCH-supervisor:$EXTRA_TAG
make IMAGE=resin/$ARCH-supervisor:$EXTRA_TAG deploy
fi
fi
if [ "$CLEANUP" = "true" ]; then
tryRemove $TARGET_IMAGE
tryRemove $BASE_IMAGE
tryRemove $GO_IMAGE
tryRemove $NODE_IMAGE
tryRemove $TARGET_CACHE
tryRemove $BASE_CACHE
tryRemove $GO_CACHE
tryRemove $NODE_CACHE
fi

View File

@ -0,0 +1,91 @@
// Deploy a supervisor image as a supervisor_release in the Resin API
//
// Environment variables:
// This program deploys only for device types where the architecture matches $ARCH.
// It deploys to the API specified by $API_ENDPOINT and using a provided $API_TOKEN or $API_KEY
// (if both are set, API_TOKEN is preferred).
// The tag to deploy must be passed as $TAG.
//
const PineJsClient = require('pinejs-client');
const Promise = require('bluebird');
const _ = require('lodash');
const url = require('url');
const apiEndpoint = process.env.API_ENDPOINT;
const apikey = process.env.API_KEY;
const arch = process.env.ARCH;
const tag = process.env.TAG;
const apiToken = process.env.API_TOKEN;
if (_.isEmpty(apikey) && _.isEmpty(apiToken)) {
console.error('Skipping deploy due to empty API_KEY and API_TOKEN');
process.exit(0);
}
if (_.isEmpty(apiEndpoint)) {
console.error('Please set a valid $API_ENDPOINT');
process.exit(1);
}
if (_.isEmpty(tag)) {
console.error('Please set a $TAG to deploy');
process.exit(1);
}
const supportedArchitectures = [ 'amd64', 'rpi', 'aarch64', 'armel', 'i386', 'armv7hf' ];
if (_.isEmpty(arch) || !_.includes(supportedArchitectures, arch)) {
console.error('Invalid architecture ' + arch);
process.exit(1);
}
const requestOpts = {
gzip: true,
timeout: 30000
};
if (!_.isEmpty(apiToken)) {
requestOpts.headers = {
Authorization: 'Bearer ' + apiToken
};
}
const apiEndpointWithPrefix = url.resolve(apiEndpoint, '/v2/')
const resinApi = new PineJsClient({
apiPrefix: apiEndpointWithPrefix,
passthrough: requestOpts
});
resinApi._request(_.extend({
url: apiEndpoint + '/config/device-types',
method: 'GET'
}, resinApi.passthrough))
.then( (deviceTypes) => {
// This is a critical step so we better do it serially
return Promise.mapSeries(deviceTypes, (deviceType) => {
if (deviceType.arch === arch) {
const customOptions = {};
if (_.isEmpty(apiToken)) {
customOptions.apikey = apikey;
}
console.log(`Deploying ${supervisor_version} for ${device_type}`);
return resinApi.post({
resource: 'supervisor_release',
body: {
image_name: `resin/${arch}-supervisor`,
supervisor_version: tag,
device_type: deviceType.slug,
is_public: true
},
customOptions
});
}
});
})
.then( () => {
process.exit(0);
})
.catch( (err) => {
console.error(`Error when deploying the supervisor to ${apiEndpoint}`, err, err.stack);
process.exit(1);
});

View File

@ -1,62 +0,0 @@
#!/bin/bash
set -e
# Jenkins build steps
export ESCAPED_BRANCH_NAME=$(echo $sourceBranch | sed 's/[^a-z0-9A-Z_.-]/-/g')
git submodule update --init --recursive
git clean -fxd base-image
git submodule foreach --recursive git clean -fxd
BASE_IMAGE_VERSION=$(make base-image-version)
export BASE_IMAGE_REPO=resin/$ARCH-supervisor-base
export BASE_IMAGE_TAG=resin/$ARCH-supervisor-base:$BASE_IMAGE_VERSION
# Try to pull the base image according to the contents of the base-image folder, otherwise build it
docker pull $BASE_IMAGE_TAG || (cd base-image && bash -ex automation/jenkins-build.sh)
# Try pulling the old build first for caching purposes.
docker pull resin/${ARCH}-supervisor:${ESCAPED_BRANCH_NAME} || docker pull resin/${ARCH}-supervisor:master || true
# Also pull the intermediate images, if possible, to improve caching
NODE_SUPERVISOR_REPO=registry.resinstaging.io/resin/node-supervisor-${ARCH}
GO_SUPERVISOR_REPO=registry.resinstaging.io/resin/go-supervisor-${ARCH}
docker pull ${NODE_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || docker pull ${NODE_SUPERVISOR_REPO}:master || true
docker pull ${GO_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || docker pull ${GO_SUPERVISOR_REPO}:master || true
# Test the gosuper
make SUPERVISOR_VERSION=${ESCAPED_BRANCH_NAME} JOB_NAME=${JOB_NAME} test-gosuper
MAKE_ARGS="ARCH=${ARCH} \
ESCAPED_BASE_IMAGE_TAG=$(echo $BASE_IMAGE_TAG | sed -e 's/\//\\\//g; s/\./\\\./g') \
PUBNUB_SUBSCRIBE_KEY=${PUBNUB_SUBSCRIBE_KEY} \
PUBNUB_PUBLISH_KEY=${PUBNUB_PUBLISH_KEY} \
MIXPANEL_TOKEN=${MIXPANEL_TOKEN} \
SUPERVISOR_VERSION=${ESCAPED_BRANCH_NAME}"
make ${MAKE_ARGS} \
DEPLOY_REGISTRY= \
deploy
# Try to push the intermediate images to improve caching in future builds
docker tag resin/node-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} ${NODE_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} \
|| docker tag -f resin/node-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} ${NODE_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} \
|| true
docker tag -f resin/go-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} ${GO_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} \
|| docker tag -f resin/go-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} ${GO_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} \
|| true
docker push ${NODE_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || true
docker push ${GO_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || true
make ${MAKE_ARGS} \
DEPLOY_REGISTRY=registry.resinstaging.io/ \
deploy
docker rmi registry.resinstaging.io/resin/${ARCH}-supervisor:${ESCAPED_BRANCH_NAME} || true
docker rmi resin/${ARCH}-supervisor:${ESCAPED_BRANCH_NAME} || true
docker rmi resin/${ARCH}-supervisor:master || true
docker rmi ${NODE_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || true
docker rmi ${NODE_SUPERVISOR_REPO}:master || true
docker rmi resin/node-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} || true
docker rmi ${GO_SUPERVISOR_REPO}:${ESCAPED_BRANCH_NAME} || true
docker rmi ${GO_SUPERVISOR_REPO}:master || true
docker rmi resin/go-supervisor-${ARCH}:${ESCAPED_BRANCH_NAME} || true
docker rmi ${BASE_IMAGE_TAG} || true
docker rmi ${BASE_IMAGE_REPO}:${ESCAPED_BRANCH_NAME} || true

16
automation/package.json Normal file
View File

@ -0,0 +1,16 @@
{
"name": "resin-supervisor-automation",
"version": "1.0.0",
"description": "Tools to build/deploy resin-supervisor",
"main": "deploy-to-resin.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "Resin Inc.",
"license": "Apache-2.0",
"dependencies": {
"bluebird": "^3.5.0",
"lodash": "^4.17.4",
"pinejs-client": "^4.0.0"
}
}

85
automation/pr-to-meta-resin.sh Executable file
View File

@ -0,0 +1,85 @@
#!/bin/bash
# PR a supervisor release to meta-resin
#
# It clones meta-resin and opens a PR changing the supervisor version to $TAG.
# If a meta-resin folder exists, it assumes it has a meta-resin git repo.
#
# If $PR_1X is "true", an additional PR for 1.X will be created.
#
# Requires $GITHUB_USERNAME and $GITHUB_PASSWORD to push and create the pull-request.
# Requires $TAG to be set to the supervisor version to use.
#
set -e
THIS_FILE=$0
if [ -z "$TAG" ]; then
cat $THIS_FILE | awk '{if(/^#/)print;else exit}' | tail -n +2 | sed 's/\#//'
exit 1
fi
if [[ -z "$GITHUB_PASSWORD" || -z "$GITHUB_USERNAME" ]]; then
echo "GITHUB_USERNAME and GITHUB_PASSWORD are required"
exit 1
fi
USER=${USER:-$(whoami)}
function prepareBranches() {
BASE=$1
HEAD=$2
git checkout $BASE
git reset HEAD
git checkout .
git fetch
git merge origin/${BASE}
git checkout -b ${HEAD}
}
function setSupervisorTag() {
sed -i "s/SUPERVISOR_TAG ?= \".*\"/SUPERVISOR_TAG ?= \"${TAG}\"/" meta-resin-common/recipes-containers/docker-disk/docker-resin-supervisor-disk.bb
}
function commitAndPR() {
BASE=$1
HEAD=$2
git commit -as -m "
docker-resin-supervisor-disk: Update to ${TAG}
Changelog-Entry: Update supervisor to ${TAG}
Change-Type: patch
" <<EOF
${GITHUB_USERNAME}
${GITHUB_PASSWORD}
EOF
git push origin $HEAD
hub pull-request -b ${BASE} -m "${BASE}: Update supervisor to ${TAG}
Change-Type: patch
" <<EOF
${GITHUB_USERNAME}
${GITHUB_PASSWORD}
EOF
}
if [ ! -d "./meta-resin" ]; then
echo "Cloning meta-resin..."
git clone https://github.com/resin-os/meta-resin.git
else
echo "Using available meta-resin repo"
fi
cd meta-resin
echo "Creating pull request to add supervisor ${TAG} on master"
prepareBranches master supervisor-${TAG}
setSupervisorTag
commitAndPR master supervisor-${TAG}
if [ "$PR_1X" = "true" ]; then
echo "Creating pull request to add supervisor ${TAG} on 1.X"
prepareBranches 1.X 1.X-supervisor-${TAG}
setSupervisorTag
commitAndPR 1.X 1.X-supervisor-${TAG}
fi

View File

@ -1,4 +0,0 @@
build
oe-core
meta-nodejs
bitbake

View File

@ -1,34 +0,0 @@
FROM ubuntu:15.04
# Install the following utilities (required by openembedded)
# http://www.openembedded.org/wiki/Getting_started#Ubuntu_.2F_Debian
RUN apt-get update \
&& apt-get install -y \
build-essential \
chrpath \
cpio \
curl \
diffstat \
file \
gawk \
git-core \
libsdl1.2-dev \
python3 \
texinfo \
unzip \
wget \
xterm \
sudo \
&& rm -rf /var/lib/apt/lists/*
RUN locale-gen en_US.UTF-8
ENV LANG en_US.UTF-8
ENV LC_ALL en_US.UTF-8
ENV SOURCE_DIR /source
ENV DEST_DIR /dest
ENV SHARED_DOWNLOADS /yocto/shared-downloads
ENV SHARED_SSTATE /yocto/shared-sstate
COPY build.sh /
CMD bash -ex build.sh

View File

@ -1,63 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
# ARCH, ESCAPED_BRANCH_NAME, BASE_IMAGE_REPO and BASE_IMAGE_TAG should be set before calling this script.
# This script purposefully doesn't clean up the BASE_IMAGE_TAG docker image after building it.
JENKINS_PERSISTENT_WORKDIR=${1:-/var/lib/yocto}
DL_DIR="$JENKINS_PERSISTENT_WORKDIR/shared-downloads"
mkdir dest
BUILDER_REPO=registry.resinstaging.io/resin/${ARCH}-supervisor-base-builder
BUILDER_IMAGE=${BUILDER_REPO}:${ESCAPED_BRANCH_NAME}
docker pull ${BUILDER_IMAGE} || docker pull ${BUILDER_REPO}:master || true
docker build -t ${BUILDER_IMAGE} .
docker push ${BUILDER_IMAGE} || true
case "$ARCH" in
'amd64')
machine='generic-x86-64'
;;
'i386')
machine='generic-x86'
;;
'rpi')
machine='generic-armv6'
;;
'armv7hf')
machine='generic-armv7hf'
;;
'armel')
machine='generic-armv5'
;;
'aarch64')
machine='generic-armv8'
;;
esac
SSTATE_DIR="$JENKINS_PERSISTENT_WORKDIR/$machine/sstate"
# Make sure shared directories are in place
mkdir -p $DL_DIR
mkdir -p $SSTATE_DIR
docker run --rm \
-e TARGET_MACHINE=$machine \
-e BUILDER_UID=$(id -u) \
-e BUILDER_GID=$(id -g) \
-v `pwd`:/source \
-v $DL_DIR:/yocto/shared-downloads \
-v $SSTATE_DIR:/yocto/shared-sstate \
-v `pwd`/dest:/dest \
${BUILDER_IMAGE}
docker rmi ${BUILDER_IMAGE} || true
docker rmi ${BUILDER_REPO}:master || true
if [ -f dest/rootfs.tar.gz ]; then
docker import dest/rootfs.tar.gz ${BASE_IMAGE_TAG}
docker tag ${BASE_IMAGE_TAG} ${BASE_IMAGE_REPO}:${ESCAPED_BRANCH_NAME} || docker tag -f ${BASE_IMAGE_TAG} ${BASE_IMAGE_REPO}:${ESCAPED_BRANCH_NAME}
docker push ${BASE_IMAGE_TAG}
else
echo "rootfs is missing!"
exit 1
fi

View File

@ -3,11 +3,49 @@
set -o errexit
BUILD_DIR='/home/builder/tmp'
case "$ARCH" in
'amd64')
export TARGET_MACHINE='generic-x86-64'
;;
'i386')
export TARGET_MACHINE='generic-x86'
;;
'rpi')
export TARGET_MACHINE='generic-armv6'
;;
'armv7hf')
export TARGET_MACHINE='generic-armv7hf'
;;
'armel')
export TARGET_MACHINE='generic-armv5'
;;
'aarch64')
export TARGET_MACHINE='generic-armv8'
;;
esac
export SOURCE_DIR=/source
export DEST_DIR=/dest
export SHARED_DOWNLOADS=/yocto/shared-downloads
export SHARED_SSTATE=/yocto/shared-sstate
# Make sure shared directories are in place
mkdir -p $SHARED_DOWNLOADS
mkdir -p $SHARED_SSTATE
mkdir -p $DEST_DIR
groupadd -g $BUILDER_GID builder
useradd -m -u $BUILDER_UID -g $BUILDER_GID builder
sudo -H -u builder /bin/bash -c "mkdir -p $BUILD_DIR \
sudo -H -u builder \
/bin/bash -c "mkdir -p $BUILD_DIR \
&& cp -r $SOURCE_DIR/* $BUILD_DIR/ \
&& cd $BUILD_DIR \
&& source oe-core/oe-init-build-env build bitbake \
&& DL_DIR=$SHARED_DOWNLOADS SSTATE_DIR=$SHARED_SSTATE MACHINE=$TARGET_MACHINE $BUILD_DIR/bitbake/bin/bitbake core-image-minimal"
cp --dereference $BUILD_DIR/build/tmp-glibc/deploy/images/$TARGET_MACHINE/core-image-minimal-$TARGET_MACHINE.tar.gz $DEST_DIR/rootfs.tar.gz
&& DL_DIR=$SHARED_DOWNLOADS SSTATE_DIR=$SHARED_SSTATE MACHINE=$TARGET_MACHINE $BUILD_DIR/bitbake/bin/bitbake core-image-minimal > /dev/null"
tar xzf $BUILD_DIR/build/tmp-glibc/deploy/images/$TARGET_MACHINE/core-image-minimal-$TARGET_MACHINE.tar.gz -C $DEST_DIR
# Delete the sstate and downloads directory so that the resulting image isn't huge
# If https://github.com/moby/moby/issues/32507 gets implemented we can start using
# a bind mounted cached directory instead
rm -rf $SHARED_DOWNLOADS
rm -rf $SHARED_SSTATE
rm -rf $BUILD_DIR

116
circle.yml Normal file
View File

@ -0,0 +1,116 @@
---
defaults: &defaults
docker:
- image: library/docker:17.06.0-ce
working_directory: /tmp/build
steps:
- setup_remote_docker:
version: 17.06.0-ce
reusable: true
- run:
name: Check docker is running and install git
command: |
docker info
apk update && apk upgrade && apk add --nocache \
make \
jq \
git \
bash \
nodejs \
nodejs-npm \
openssh-client
- checkout
- run:
name: Install npm dependencies
working_directory: /tmp/build/automation
command: |
JOBS=max npm install \
&& npm cache clean
- run:
name: Initialize the submodules (yocto layers)
command: |
git submodule update --init --recursive
git clean -fxd base-image
git submodule foreach --recursive git clean -fxd
- run:
name: Build $ARCH-supervisor
no_output_timeout: 10800
command: |
VERSION_TAG=v$(jq .version package.json | sed 's/"//g')
if [ "${CIRCLE_BRANCH}" = "master" ]; then
export EXTRA_TAG=$VERSION_TAG
fi
echo "Starting build.sh"
docker login --username $DOCKER_USERNAME --password $DOCKER_PASSWORD
# start the build for this architecture
export TAG=${CIRCLE_BRANCH}
export ARCH=${ARCH}
export PUSH_IMAGES=${PUSH_IMAGES}
bash automation/build.sh
if [ "${CIRCLE_BRANCH}" = "master" ] && [ "${DEPLOY_TO_RESIN}" = "true" ]; then
echo "Deploying to Resin API (staging)"
ARCH=${ARCH} TAG=$VERSION_TAG API_KEY=$STAGING_API_KEY API_ENDPOINT=$STAGING_API_ENDPOINT node automation/deploy-to-resin.js
echo "Deploying to Resin API (production)"
ARCH=${ARCH} TAG=$VERSION_TAG API_KEY=$PRODUCTION_API_KEY API_ENDPOINT=$PRODUCTION_API_ENDPOINT node automation/deploy-to-resin.js
fi
version: 2
jobs:
amd64:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: amd64
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
i386:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: i386
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
armel:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: armel
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
armv7hf:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: armv7hf
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
aarch64:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: aarch64
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
rpi:
<<: *defaults
environment:
DOCKER_USERNAME: travisciresin
ARCH: rpi
PUSH_IMAGES: "true"
STAGING_API_ENDPOINT: https://api.resinstaging.io
PRODUCTION_API_ENDPOINT: https://api.resin.io
workflows:
version: 2
build_and_maybe_deploy:
jobs:
- amd64
- i386
- rpi
- armv7hf
- aarch64

163
dindctl Executable file
View File

@ -0,0 +1,163 @@
#!/bin/bash
#
# This script can be used to facilitate supervisor development. Its core feature is allowing
# faster development iterations by bind-mounting the local './dist' directly into the running
# supervisor container.
#
# Setting the '--mount-nm' flag in either 'run' or 'buildrun' action will bind-mount
# './node_modules/' into the running supervisor. In this case, it's up to the developer
# to make sure that the correct dependencies are installed.
#
# Usage: dindctl action [options]
#
# Actions:
# build build local supervisor image - you can override image name with --image.
# run [options] build dind host container, run it (with name resin_supervisor_1), which will include the specified supervisor image and run it.
# buildrun [options] run 'build' and then immediately 'run' the built container.
# refresh recompile sources in './src' and restart supervisor container on dind host - requires --mount-dist in order to work properly.
# logs [-f] print out supervisor log files - use '-f' to follow instead, or any other arguments you'd send to journalctl.
# stop stop dind supervisor host container.
# Options:
# --arch | -a [arch] architecture of the supervisor to build (default: amd64 )
# --image | -i [image] image name for supervisor image to build/use ( default: resin/$ARCH-supervisor:master )
# --dind-image [image] image name for the dind host container
# --mount-dist bind-mount './dist/' (where webpack stores the built js) from local development environment into supervisor container.
# --mount-nm bind-mount './node_modules/' from local development environment into supervisor container.
# --preload | -p use tools/dev/apps.json to preload an application image into the dind host.
# --ssh enable a passwordless dropbear ssh server on the dind host
#
# See README.md for examples.
#
# The script requires make and docker.
#
THIS_FILE=$0
set -o errexit
set -o pipefail
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
SUPERVISOR_BASE_DIR="${DIR}"
ARCH="amd64"
SUPERVISOR_IMAGE="resin/${ARCH}-supervisor:master"
PASSWORDLESS_DROPBEAR="false"
SUPERVISOR_EXTRA_MOUNTS=""
DIST_MOUNTED="false"
DIND_IMAGE="resin-supervisor-dind"
PRELOADED_IMAGE=""
function showHelp {
cat $THIS_FILE | awk '{if(/^#/)print;else exit}' | tail -n +2 | sed 's/\#//' | sed 's|dindctl|'$THIS_FILE'|'
}
function parseOptions {
while [[ $# -gt 1 ]]
do
case $1 in
--mount-dist)
DIST_MOUNTED="true"
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS -v /resin-supervisor/dist:/usr/src/app/dist"
;;
--mount-nm)
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS -v /resin-supervisor/node_modules:/usr/src/app/node_modules"
;;
-p|--preload)
PRELOADED_IMAGE="true"
;;
--ssh)
PASSWORDLESS_DROPBEAR="true"
;;
-i|--image)
SUPERVISOR_IMAGE="$2"
shift || { echo "--image provided not specified" && exit 1; }
;;
--dind-image)
DIND_IMAGE="$2"
shift || { echo "--dind-image provided not specified" && exit 1; }
;;
-a|--arch)
ARCH="$2"
shift || { echo "--arch provided not specified" && exit 1; }
;;
*)
echo "Warning: unknown argument: $arg"
;;
esac
shift
done
}
function buildSupervisor {
echo "Building and deploying for architecture $ARCH and tagging as $IMAGE"
make -C "$SUPERVISOR_BASE_DIR" \
ARCH="$ARCH" \
IMAGE="$SUPERVISOR_IMAGE" \
supervisor
}
function buildSupervisorSrc {
echo "Rebuilding supervisor source"
( cd "$SUPERVISOR_BASE_DIR" && npm run build )
}
function refreshSupervisorSrc {
buildSupervisorSrc
echo "Restarting the supervisor container"
docker exec -ti resin_supervisor_1 docker restart resin_supervisor
}
function runDind {
if [ "$DIST_MOUNTED" = "true" ]; then
buildSupervisorSrc
echo "Running with mounted dist folder"
fi
if [ "$PRELOADED_IMAGE" = "true" ]; then
echo "Running with preloaded apps"
fi
echo "Starting dind supervisor"
make -C "$SUPERVISOR_BASE_DIR" \
ARCH="$ARCH" \
SUPERVISOR_IMAGE="$SUPERVISOR_IMAGE" \
PASSWORDLESS_DROPBEAR="$PASSWORDLESS_DROPBEAR" \
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS" \
IMAGE="$DIND_IMAGE" \
run-supervisor
}
function stopDind {
echo "Stopping dind supervisor"
make -C "$SUPERVISOR_BASE_DIR" stop-supervisor
}
function logs {
docker exec -ti resin_supervisor_1 journalctl $@
}
action="$1"
shift || true
if [ "$action" = "logs" ]; then
logs "$@"
else
parseOptions "$@"
case $action in
build)
buildSupervisor
;;
run)
runDind
;;
buildrun)
buildSupervisor && runDind
;;
refresh)
refreshSupervisorSrc
;;
stop)
stopDind
;;
*)
showHelp
esac
fi

View File

@ -1,63 +0,0 @@
# Build golang supervisor
FROM debian:jessie
RUN apt-get update \
&& apt-get install -y \
build-essential \
curl \
rsync \
&& rm -rf /var/lib/apt/lists/
ENV GOLANG_VERSION 1.8.3
ENV GOLANG_DOWNLOAD_URL https://golang.org/dl/go$GOLANG_VERSION.linux-amd64.tar.gz
ENV GOLANG_DOWNLOAD_SHA256 1862f4c3d3907e59b04a757cfda0ea7aa9ef39274af99a784f5be843c80c6772
COPY go-${GOLANG_VERSION}-patches /go-${GOLANG_VERSION}-patches
RUN mkdir /usr/src/go \
&& cd /usr/src/go \
&& curl -L -o go.tar.gz $GOLANG_DOWNLOAD_URL \
&& echo "${GOLANG_DOWNLOAD_SHA256} go.tar.gz" | sha256sum -c - \
&& tar xzf go.tar.gz -C /usr/local \
&& cd /usr/src \
&& rm -rf go \
&& export GOROOT_BOOTSTRAP=/usr/local/go-bootstrap \
&& cp -r /usr/local/go /usr/local/go-bootstrap \
&& cd /usr/local/go/src \
&& patch -p2 -i /go-${GOLANG_VERSION}-patches/0001-dont-fail-when-no-mmx.patch \
&& patch -p2 -i /go-${GOLANG_VERSION}-patches/0002-implement-atomic-quadword-ops-with-FILD-FISTP.patch \
&& ./make.bash \
&& rm -rf /usr/local/go-bootstrap
ENV UPX_VERSION 3.94
# UPX doesn't provide fingerprints so I checked this one manually
ENV UPX_SHA256 e1fc0d55c88865ef758c7e4fabbc439e4b5693b9328d219e0b9b3604186abe20
RUN mkdir /usr/src/upx \
&& cd /usr/src/upx \
&& curl -L -o upx.tar.xz https://github.com/upx/upx/releases/download/v$UPX_VERSION/upx-$UPX_VERSION-amd64_linux.tar.xz \
&& echo "${UPX_SHA256} upx.tar.xz" | sha256sum -c - \
&& tar xf upx.tar.xz --strip-components=1 \
&& cp ./upx /usr/bin/ \
&& cd /usr/src \
&& rm -rf upx
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
COPY . /go/src/resin-supervisor/gosuper
WORKDIR /go/src/resin-supervisor/gosuper
ENV GOOS linux
ENV GO386=387
ARG GOARCH=amd64
ARG GOARM=''
RUN go install -a -v ./gosuper \
&& cd /go/bin \
&& find -type f -name gosuper -exec mv {} /go/bin/gosuper \; \
&& upx --best /go/bin/gosuper
CMD rsync -a --delete /go/bin/gosuper /build

35
gosuper/build.sh Normal file
View File

@ -0,0 +1,35 @@
#!/bin/bash
set -o errexit
./test_formatting.sh
go test -v ./gosuper
case "$ARCH" in
'amd64')
export GOARCH=amd64
;;
'i386')
export GOARCH=386
;;
'rpi')
export GOARCH=arm
export GOARM=6
;;
'armv7hf')
export GOARCH=arm
export GOARM=7
;;
'armel')
export GOARCH=arm
export GOARM=5
;;
'aarch64')
export GOARCH=arm64
;;
esac
go install -a -v ./gosuper \
&& cd /go/bin \
&& find -type f -name gosuper -exec mv {} /go/bin/gosuper \; \
&& upx --best /go/bin/gosuper

View File

@ -1,7 +1,7 @@
{
"name": "resin-supervisor",
"description": "This is resin.io's Supervisor, a program that runs on IoT devices and has the task of running user Apps (which are Docker containers), and updating them as Resin's API informs it to.",
"version": "6.0.1",
"version": "6.0.2",
"license": "Apache-2.0",
"repository": {
"type": "git",

View File

@ -1,107 +0,0 @@
#!/bin/bash
set -o errexit
set -o pipefail
DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
SUPERVISOR_BASE_DIR="${DIR}/../.."
ARCH=${ARCH:-"amd64"}
SUPERVISOR_IMAGE=${SUPERVISOR_IMAGE:-"registry.resindev.io/resin/${ARCH}-supervisor:master"}
PASSWORDLESS_DROPBEAR=${PASSWORDLESS_DROPBEAR:-"false"}
SUPERVISOR_EXTRA_MOUNTS=
function showHelp {
echo
echo " This script can be used to facilitate supervisor development. Its core feature is allowing"
echo " faster development iterations by bind-mounting the local './src' directly into the running"
echo " supervisor container."
echo
echo " Setting the '--mount-nm' flag in either 'run' or 'deployrun' action will bind-mount"
echo " './node_modules/' into the running supervisor. In this case, it's up to the developer"
echo " to make sure that the correct dependencies are installed."
echo
echo " Usage: [environment] $0 action [options]"
echo
echo " Environment Variables:"
echo " ARCH [=amd64]"
echo " SUPERVISOR_IMAGE [=registry.resindev.io/resin/<ARCH>-supervisor:master]"
echo " PASSWORDLESS_DROPBEAR [=false]"
echo " Actions:"
echo " deploy build and deploy local supervisor image - you can override registry/image name with 'SUPERVISOR_IMAGE'"
echo " run [options] build dind host container, run it, then pull the configured 'SUPERVISOR_IMAGE' into the dind host and run it"
echo " deployrun [options] run 'deploy' and then immediately 'run' the deployed container"
echo " refresh recompile sources in './src' with 'coffee -c' and restart supervisor container on dind host"
echo " logs [-f] print out supervisor log files - use '-f' to follow instead"
echo " stop stop dind supervisor host container"
echo " Options:"
echo " --mount-src bind-mount './src/' from local development environment into supervisor container"
echo " --mount-nm bind-mount './node_modules/' from local development environment into supervisor container"
echo
}
function deploySupervisor {
make -C "$SUPERVISOR_BASE_DIR" \
ARCH="$ARCH" \
SUPERVISOR_IMAGE="$SUPERVISOR_IMAGE" \
PASSWORDLESS_DROPBEAR="$PASSWORDLESS_DROPBEAR" \
deploy
}
function runDind {
for arg in "$@"
do
case $arg in
--mount-src)
coffee -c "$SUPERVISOR_BASE_DIR/src"
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS -v /resin-supervisor/src:/usr/src/app/src"
shift
;;
--mount-nm)
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS -v /resin-supervisor/node_modules:/usr/src/app/node_modules"
shift
;;
*)
echo "Warning: unknown argument: $arg"
;;
esac
done
make -C "$SUPERVISOR_BASE_DIR" \
ARCH="$ARCH" \
SUPERVISOR_IMAGE="$SUPERVISOR_IMAGE" \
PASSWORDLESS_DROPBEAR="$PASSWORDLESS_DROPBEAR" \
SUPERVISOR_EXTRA_MOUNTS="$SUPERVISOR_EXTRA_MOUNTS" \
run-supervisor
}
function logs {
docker exec -ti resin_supervisor_1 journalctl $@
}
action="$1"
shift || true
case $action in
deploy)
deploySupervisor
;;
run)
runDind "$@"
;;
deployrun)
deploySupervisor && runDind "$@"
;;
refresh)
make -C "$SUPERVISOR_BASE_DIR" refresh-supervisor-src
;;
logs)
logs "$@"
;;
stop)
make -C "$SUPERVISOR_BASE_DIR" stop-supervisor
;;
*)
showHelp
esac

View File

@ -26,6 +26,10 @@ RUN apt-key adv --keyserver hkp://pgp.mit.edu:80 --recv-keys 58118E89F3A912897C0
&& apt-get --force-yes install docker-engine=${DOCKER_VERSION}-0~${RELEASE_NAME} \
&& rm -rf /var/lib/apt/lists/*
ENV DIND_COMMIT 3b5fac462d21ca164b3778647420016315289034
RUN curl -sL https://raw.githubusercontent.com/docker/docker/${DIND_COMMIT}/hack/dind > /usr/bin/dind \
&& chmod +x /usr/bin/dind
RUN passwd -d root
# Change os release to a resin-sync compatible one
@ -40,3 +44,5 @@ COPY resin-vars vpn-init /usr/src/app/
RUN if [ "$PASSWORDLESS_DROPBEAR" = "true" ]; then sed -i 's/\(DROPBEAR_EXTRA_ARGS=\).*/\1"-B"/' /etc/default/dropbear; fi
RUN systemctl enable resin-supervisor-dind
COPY supervisor-image.tar /usr/src/

View File

@ -1,3 +1,3 @@
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon --storage-driver aufs --host=fd://
ExecStart=/usr/bin/dind /usr/bin/docker daemon --storage-driver aufs --host=fd://

View File

@ -9,7 +9,7 @@ WorkingDirectory=/usr/src/app
EnvironmentFile=/usr/src/app/config/env
EnvironmentFile=/usr/src/app/config/localenv
ExecStartPre=/bin/bash -c 'if [ "${PRELOADED_IMAGE}" == "true" ]; then /usr/bin/docker pull $(jq ".[0].imageId" ${APPS_PATH}); fi'
ExecStartPre=/usr/bin/docker pull ${SUPERVISOR_IMAGE}
ExecStartPre=/usr/bin/docker load --input /usr/src/supervisor-image.tar
ExecStartPre=-/usr/bin/docker kill resin_supervisor
ExecStartPre=-/usr/bin/docker rm resin_supervisor
ExecStartPre=-/bin/touch /etc/resolv.conf