diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 0000000..f696222 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,34 @@ +FROM mcr.microsoft.com/vscode/devcontainers/base:debian + +WORKDIR /workspaces + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +# Set Docker daemon config +RUN \ + mkdir -p /etc/docker \ + && echo '{"storage-driver": "vfs"}' > /etc/docker/daemon.json + +# Installa aditional tools +RUN \ + apt-get update \ + && apt-get install -y --no-install-recommends \ + dbus \ + network-manager \ + libpulse0 \ + xz-utils + +# Install docker +RUN curl -fsSL https://get.docker.com | sh - + +# Install shellcheck +RUN \ + curl -fLs \ + "https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.x86_64.tar.xz" \ + | tar -xJ \ + \ + && mv -f "./shellcheck-stable/shellcheck" "/usr/bin/shellcheck" \ + && rm -rf "./shellcheck-stable" + +# Generate a machine-id for this container +RUN rm /etc/machine-id && dbus-uuidgen --ensure=/etc/machine-id diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 0000000..22b768f --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,14 @@ +{ + "name": "Home Assistant Add-Ons", + "context": "..", + "dockerFile": "Dockerfile", + "appPort": ["7123:8123", "7357:4357"], + "postStartCommand": "service docker start", + "runArgs": ["-e", "GIT_EDITOR=code --wait", "--privileged"], + "extensions": ["timonwong.shellcheck", "esbenp.prettier-vscode"], + "settings": { + "terminal.integrated.shell.linux": "/bin/bash" + }, + "workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/addons,type=bind,consistency=delegated", + "workspaceFolder": "/workspaces/addons" +} diff --git a/.devcontainer/supervisor.sh b/.devcontainer/supervisor.sh new file mode 100755 index 0000000..7c2ffe5 --- /dev/null +++ b/.devcontainer/supervisor.sh @@ -0,0 +1,141 @@ +#!/bin/bash +set -eE + +DOCKER_TIMEOUT=30 +DOCKER_PID=0 + +SUPERVISOR_VERSON="$(curl -s https://version.home-assistant.io/dev.json | jq -e -r '.supervisor')" + + +function start_docker() { + local starttime + local endtime + + echo "Starting docker." + dockerd 2> /dev/null & + DOCKER_PID=$! + + echo "Waiting for docker to initialize..." + starttime="$(date +%s)" + endtime="$(date +%s)" + until docker info >/dev/null 2>&1; do + if [ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]; then + sleep 1 + endtime=$(date +%s) + else + echo "Timeout while waiting for docker to come up" + exit 1 + fi + done + echo "Docker was initialized" +} + + +function stop_docker() { + local starttime + local endtime + + echo "Stopping in container docker..." + if [ "$DOCKER_PID" -gt 0 ] && kill -0 "$DOCKER_PID" 2> /dev/null; then + starttime="$(date +%s)" + endtime="$(date +%s)" + + # Now wait for it to die + kill "$DOCKER_PID" + while kill -0 "$DOCKER_PID" 2> /dev/null; do + if [ $((endtime - starttime)) -le $DOCKER_TIMEOUT ]; then + sleep 1 + endtime=$(date +%s) + else + echo "Timeout while waiting for container docker to die" + exit 1 + fi + done + else + echo "Your host might have been left with unreleased resources" + fi +} + + +function cleanup_lastboot() { + if [[ -f /tmp/supervisor_data/config.json ]]; then + echo "Cleaning up last boot" + cp /tmp/supervisor_data/config.json /tmp/config.json + jq -rM 'del(.last_boot)' /tmp/config.json > /tmp/supervisor_data/config.json + rm /tmp/config.json + fi +} + + +function cleanup_docker() { + echo "Cleaning up stopped containers..." + docker rm "$(docker ps -a -q)" || true +} + +function run_supervisor() { + mkdir -p /tmp/supervisor_data + docker run --rm --privileged \ + --name hassio_supervisor \ + --security-opt seccomp=unconfined \ + --security-opt apparmor:unconfined \ + -v /run/docker.sock:/run/docker.sock:rw \ + -v /run/dbus:/run/dbus:ro \ + -v /run/udev:/run/udev:ro \ + -v /tmp/supervisor_data:/data:rw \ + -v "/workspaces/addons":/data/addons/local:rw \ + -v /etc/machine-id:/etc/machine-id:ro \ + -e SUPERVISOR_SHARE="/tmp/supervisor_data" \ + -e SUPERVISOR_NAME=hassio_supervisor \ + -e SUPERVISOR_DEV=1 \ + -e SUPERVISOR_MACHINE="qemux86-64" \ + "homeassistant/amd64-hassio-supervisor:${SUPERVISOR_VERSON}" +} + +function init_dbus() { + if pgrep dbus-daemon; then + echo "Dbus is running" + return 0 + fi + + echo "Startup dbus" + mkdir -p /var/lib/dbus + cp -f /etc/machine-id /var/lib/dbus/machine-id + + # cleanups + mkdir -p /run/dbus + rm -f /run/dbus/pid + + # run + dbus-daemon --system --print-address +} + +function init_udev() { + if pgrep systemd-udevd; then + echo "udev is running" + return 0 + fi + + echo "Startup udev" + + # cleanups + mkdir -p /run/udev + + # run + /lib/systemd/systemd-udevd --daemon + sleep 3 + udevadm trigger && udevadm settle +} + +echo "Start Test-Env" + +start_docker +trap "stop_docker" ERR + +docker system prune -f + +cleanup_lastboot +cleanup_docker +init_dbus +init_udev +run_supervisor +stop_docker diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..69b089b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,30 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "Start Home Assistant", + "type": "shell", + "command": "./.devcontainer/supervisor.sh", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "new" + }, + "problemMatcher": [] + }, + { + "label": "Run Home Assistant CLI", + "type": "shell", + "command": "docker exec -ti hassio_cli /usr/bin/cli.sh", + "group": "test", + "presentation": { + "reveal": "always", + "panel": "new" + }, + "problemMatcher": [] + } + ] +}