Add Ingress Support (#1)

* Add ingress support

* Development framework

* Add ARCH arg for correct s6 version

* Support new ARCH arg for correct s6 overlay version

* Add PR trigger to workflow

* Add image again

Co-authored-by: Matt White <matt.white@microsoft.com>
This commit is contained in:
Thomas Moore
2021-01-08 14:24:13 +00:00
committed by GitHub
co-authored by Matt White
parent 0a82b9eba8
commit d544873055
15 changed files with 319 additions and 25 deletions
+45
View File
@@ -0,0 +1,45 @@
FROM ubuntu:20.04
WORKDIR /workspaces
# Default ENV
ENV LANG C.UTF-8
ENV DEBIAN_FRONTEND noninteractive
# Set shell
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
# Use the mirror protocol for a fast mirror
RUN sed -i -e 's/http:\/\/archive\.ubuntu\.com\/ubuntu\//mirror:\/\/mirrors\.ubuntu\.com\/mirrors\.txt/' /etc/apt/sources.list
# Install docker, jq, socat
# https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/
RUN apt-get update && apt-get install -y --no-install-recommends \
apt-transport-https \
ca-certificates \
curl \
dbus \
software-properties-common \
gpg-agent \
git \
jq \
socat \
sudo \
&& curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - \
&& add-apt-repository "deb https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \
&& apt-get update && apt-get install -y --no-install-recommends \
docker-ce \
docker-ce-cli \
containerd.io
# This is a development container. Don't bother to clean up apt cache, this way we have it handy later
COPY .devcontainer/start_ha.sh /usr/local/bin/start_ha.sh
# Install dependencies for the add-on development below. For example, if you're running Node.js,
# you may want something like the following...
# RUN apt-get install -y --no-install-recommends nodejs npm
# Generate a machine-id for this container
RUN rm /etc/machine-id && dbus-uuidgen --ensure=/etc/machine-id
ENV DEBIAN_FRONTEND=dialog
+29
View File
@@ -0,0 +1,29 @@
// For format details, see https://aka.ms/vscode-remote/devcontainer.json
// TODO: When https://github.com/microsoft/vscode-remote-release/issues/2129 is fixed, move to ${localWorkspaceFolderBasename}\
{
"name": "Home Assistant Add-On",
"context": "..",
"dockerFile": "Dockerfile",
"appPort": 8123,
"runArgs": [
"-e",
"GIT_EDITOR=code --wait",
"--privileged"
],
"settings": {
"terminal.integrated.shell.linux": "/bin/bash"
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/test_hassio/addons/local/myaddon,type=bind,consistency=delegated",
"workspaceFolder": "/workspaces/test_hassio/addons/local/myaddon",
"mounts": [
// Cache docker images between devcontainer rebuilds (and share between devcontainers)
"source=vsc-hassio-docker,target=/var/lib/docker,type=volume"
]
// Post-create command to initialize the workspace. For example, for a node.js add-on you may want:
// "postCreateCommand": "cd /workspaces/test_hassio/addons/local/myaddon && npm install",
// "extensions": [
// "dbaeumer.vscode-eslint",
// "maty.vscode-mocha-sidebar"
// ]
}
+103
View File
@@ -0,0 +1,103 @@
#!/bin/bash
set -eE
DOCKER_TIMEOUT=30
DOCKER_PID=0
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 install() {
docker pull homeassistant/amd64-hassio-supervisor:dev
docker pull homeassistant/amd64-hassio-cli:dev
}
function cleanup_hass_data() {
rm -rf /workspaces/test_hassio/{apparmor,backup,config.json,dns,dns.json,homeassistant,homeassistant.json,ingress.json,share,ssl,tmp,updater.json}
rm -rf /workspaces/test_hassio/addons/{core,data,git}
}
function cleanup_docker() {
echo "Cleaning up stopped containers..."
docker rm $(docker ps -a -q)
}
function run_supervisor() {
docker run --rm --privileged \
--name hassio_supervisor \
--security-opt seccomp=unconfined \
--security-opt apparmor:unconfined \
-v /run/docker.sock:/run/docker.sock \
-v /run/dbus:/run/dbus \
-v "/workspaces/test_hassio":/data \
-v /etc/machine-id:/etc/machine-id:ro \
-e SUPERVISOR_SHARE="/workspaces/test_hassio" \
-e SUPERVISOR_NAME=hassio_supervisor \
-e SUPERVISOR_DEV=1 \
-e HOMEASSISTANT_REPOSITORY="homeassistant/qemux86-64-homeassistant" \
homeassistant/amd64-hassio-supervisor:dev
}
case "$1" in
"--cleanup")
echo "Cleaning up old environment"
cleanup_docker || true
cleanup_hass_data || true
exit 0;;
*)
echo "Creating development Home Assistant environment"
start_docker
trap "stop_docker" ERR
install
cleanup_docker || true
run_supervisor
stop_docker;;
esac
+20 -6
View File
@@ -7,6 +7,12 @@ on:
paths: paths:
- '**' - '**'
- '!**.md' - '!**.md'
pull_request:
branches:
- main
paths:
- '**'
- '!**.md'
env: env:
DOCKER_USERNAME: mattffffff DOCKER_USERNAME: mattffffff
@@ -45,15 +51,21 @@ jobs:
run: | run: |
case "${{ matrix.arch }}" in case "${{ matrix.arch }}" in
"amd64" ) "amd64" )
echo "PLATFORM=linux/amd64" >> $GITHUB_ENV ;; echo "PLATFORM=linux/amd64" >> $GITHUB_ENV
"i386" ) echo "ARCH=amd64" >> $GITHUB_ENV
echo "PLATFORM=linux/386" >> $GITHUB_ENV ;; ;;
"aarch64" ) "aarch64" )
echo "PLATFORM=linux/arm64" >> $GITHUB_ENV ;; echo "PLATFORM=linux/arm64" >> $GITHUB_ENV
echo "ARCH=aarch64" >> $GITHUB_ENV
;;
"armhf" ) "armhf" )
echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV ;; echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV
echo "ARCH=armhf" >> $GITHUB_ENV
;;
"armv7" ) "armv7" )
echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV ;; echo "PLATFORM=linux/arm/v7" >> $GITHUB_ENV
echo "ARCH=arm" >> $GITHUB_ENV
;;
esac esac
- name: Set environment variables from config.json - name: Set environment variables from config.json
run: | run: |
@@ -68,6 +80,7 @@ jobs:
--pull \ --pull \
--platform=$PLATFORM \ --platform=$PLATFORM \
--build-arg TESLAMATE_TAG=$TESLAMATE_TAG \ --build-arg TESLAMATE_TAG=$TESLAMATE_TAG \
--build-arg ARCH=$ARCH \
--label io.hass.type="addon" \ --label io.hass.type="addon" \
--label io.hass.name="$ADDON_NAME" \ --label io.hass.name="$ADDON_NAME" \
--label io.hass.description="$ADDON_DESCRIPTION" \ --label io.hass.description="$ADDON_DESCRIPTION" \
@@ -84,6 +97,7 @@ jobs:
--push \ --push \
--platform=$PLATFORM \ --platform=$PLATFORM \
--build-arg TESLAMATE_TAG=$TESLAMATE_TAG \ --build-arg TESLAMATE_TAG=$TESLAMATE_TAG \
--build-arg ARCH=$ARCH \
--label io.hass.type="addon" \ --label io.hass.type="addon" \
--label io.hass.name="$ADDON_NAME" \ --label io.hass.name="$ADDON_NAME" \
--label io.hass.description="$ADDON_DESCRIPTION" \ --label io.hass.description="$ADDON_DESCRIPTION" \
+41
View File
@@ -0,0 +1,41 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "Start Home Assistant",
"type": "shell",
"command": "/usr/local/bin/start_ha.sh",
"group": {
"kind": "test",
"isDefault": true,
},
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},{
"label": "Cleanup stale Home Assistant environment",
"type": "shell",
"command": "/usr/local/bin/start_ha.sh --cleanup",
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
},{
"label": "Run Home Assistant CLI",
"type": "shell",
"command": "docker run --rm -ti -v /etc/machine-id:/etc/machine-id --network=hassio --add-host hassio:172.30.32.2 homeassistant/amd64-hassio-cli:dev",
"group": "test",
"presentation": {
"reveal": "always",
"panel": "new"
},
"problemMatcher": []
}
]
}
+12 -3
View File
@@ -6,6 +6,7 @@ FROM teslamate/grafana:${TESLAMATE_TAG} as grafana
FROM teslamate/teslamate:${TESLAMATE_TAG} FROM teslamate/teslamate:${TESLAMATE_TAG}
ARG ARCH
ARG BASHIO_VERSION=0.9.0 ARG BASHIO_VERSION=0.9.0
ARG S6_OVERLAY_VERSION=1.22.1.0 ARG S6_OVERLAY_VERSION=1.22.1.0
@@ -19,8 +20,9 @@ RUN apk add --no-cache \
ca-certificates \ ca-certificates \
curl \ curl \
bind-tools \ bind-tools \
nginx \
\ \
&& curl -L -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-amd64.tar.gz" \ && curl -L -s "https://github.com/just-containers/s6-overlay/releases/download/v${S6_OVERLAY_VERSION}/s6-overlay-${ARCH}.tar.gz" \
| tar zxvf - -C / \ | tar zxvf - -C / \
&& mkdir -p /etc/fix-attrs.d \ && mkdir -p /etc/fix-attrs.d \
&& mkdir -p /etc/services.d \ && mkdir -p /etc/services.d \
@@ -34,10 +36,17 @@ RUN apk add --no-cache \
COPY --chown=root scripts/*.sh / COPY --chown=root scripts/*.sh /
RUN chmod a+x /*.sh RUN chmod a+x /*.sh
COPY --chown=root services/teslamate/run services/teslamate/finish /etc/services.d/teslamate/
RUN chmod a+x /etc/services.d/teslamate/*
COPY --chown=root services/nginx/run services/nginx/finish /etc/services.d/nginx/
RUN chmod a+x /etc/services.d/nginx/*
COPY --chown=root services/nginx/teslamate.conf /etc/nginx/conf.d/
COPY --from=grafana --chown=root /dashboards /dashboards COPY --from=grafana --chown=root /dashboards /dashboards
COPY --from=grafana --chown=root /dashboards_internal /dashboards COPY --from=grafana --chown=root /dashboards_internal /dashboards
# USER nobody # USER nobody
ENTRYPOINT ["/ha-bootstrap.sh"] ENTRYPOINT ["/init"]
CMD ["bin/teslamate", "start"]
-8
View File
@@ -6,14 +6,6 @@ This addon builds on the excellent work of [Adrian Kumpf](https://github.com/adr
If using the Postgres addon from this repo, the database host is ```29b65938-postgres``` If using the Postgres addon from this repo, the database host is ```29b65938-postgres```
## No Ingress Support
TeslaMate does not currently support a base path, so it expects all requests to be generated from the URL root ```/```.
See https://github.com/adriankumpf/teslamate/issues/494.
This means we cannot implement Ingress and must expose TeslaMate to the network.
I recommend you only do this to configure TeslaMate and you then remove the external port mapping.
## Grafana Configuration ## Grafana Configuration
> I recommend you use the existing Grafana addon from the community addons > I recommend you use the existing Grafana addon from the community addons
+5
View File
@@ -0,0 +1,5 @@
{
"args": {
"TESLAMATE_TAG": "1.20.1"
}
}
+3 -7
View File
@@ -6,12 +6,10 @@
"arch": ["armhf", "armv7", "aarch64", "amd64"], "arch": ["armhf", "armv7", "aarch64", "amd64"],
"startup": "application", "startup": "application",
"boot": "auto", "boot": "auto",
"ingress": false, "ingress": true,
"ports": { "ports": {
"4000/tcp": null
}, },
"ports_description": { "ports_description": {
"4000/tcp": "Insecure web interface - disable when not in use"
}, },
"options": { "options": {
"database_user": "user", "database_user": "user",
@@ -33,8 +31,7 @@
"mqtt_tls": true, "mqtt_tls": true,
"mqtt_tls_accept_invalid_certs": false, "mqtt_tls_accept_invalid_certs": false,
"mqtt_namespace": "account_0", "mqtt_namespace": "account_0",
"timezone": "Europe/London", "timezone": "Europe/London"
"port": 4000
}, },
"schema": { "schema": {
"database_user": "str", "database_user": "str",
@@ -56,8 +53,7 @@
"mqtt_tls": "bool", "mqtt_tls": "bool",
"mqtt_tls_accept_invalid_certs": "bool", "mqtt_tls_accept_invalid_certs": "bool",
"mqtt_namespace": "str", "mqtt_namespace": "str",
"timezone": "str", "timezone": "str"
"port": "int"
}, },
"url": "https://github.com/matt-FFFFFF/hassio-addon-repository/blob/master/teslamate/README.md", "url": "https://github.com/matt-FFFFFF/hassio-addon-repository/blob/master/teslamate/README.md",
"image": "mattffffff/teslamate-{arch}" "image": "mattffffff/teslamate-{arch}"
+1 -1
View File
@@ -18,7 +18,7 @@ export MQTT_NAMESPACE=export MQTT_TLS=$(bashio::config 'mqtt_namespace')
# Other things # Other things
export TZ=$(bashio::config 'timezone') export TZ=$(bashio::config 'timezone')
export PORT=$(bashio::config 'port') export PORT=4000
# Import dashboards # Import dashboards
if [ $(bashio::config 'grafana_import_dashboards') == 'true' ]; then if [ $(bashio::config 'grafana_import_dashboards') == 'true' ]; then
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
s6-svscanctl -t /var/run/s6/services
+3
View File
@@ -0,0 +1,3 @@
#!/usr/bin/with-contenv sh
mkdir /run/nginx
exec nginx -g 'daemon off;'
+42
View File
@@ -0,0 +1,42 @@
# Enable gzipping of responses.
gzip on;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
server_name _;
listen 8099 default_server;
location / {
proxy_pass http://localhost:4000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Referer $http_referer;
# Disable encoding to allow the sub_filter to work
proxy_set_header Accept-Encoding "";
# Enable sub-filtering
sub_filter_types text/css text/xml application/javascript;
sub_filter_once off;
# Home URLs in the HTML
sub_filter 'href="/"' 'href="$http_x_ingress_path/"';
# Fonts in the CSS
sub_filter 'url(/' 'url($http_x_ingress_path/';
# Update fixed paths in the .js files
sub_filter '"/live"' '"$http_x_ingress_path/live"';
sub_filter '"/js/"' '"$http_x_ingress_path/js/"';
}
}
+2
View File
@@ -0,0 +1,2 @@
#!/bin/sh
s6-svscanctl -t /var/run/s6/services
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/with-contenv sh
ingress_entry=$(curl -X GET \
-H "Authorization: Bearer ${SUPERVISOR_TOKEN}" \
-H "Content-Type: application/json" \
-s http://supervisor/addons/self/info | \
jq -r '.data.ingress_entry')
sed -i "s^url: \[^url: \[path: \"${ingress_entry}\", ^" /opt/app/releases/*/releases.exs
cd /opt/app
exec /ha-bootstrap.sh bin/teslamate start