Compare commits

..

No commits in common. "master" and "v4.0.8" have entirely different histories.

18 changed files with 397 additions and 8860 deletions

View File

@ -1,8 +0,0 @@
self-hosted-runner:
# Labels of self-hosted runner in array of strings.
labels:
- "distro:jammy"
# Configuration variables in array of strings defined in your repository or
# organization. `null` means disabling configuration variables check.
# Empty array means no configuration variable is allowed.
config-variables: null

27
.github/renovate.json vendored
View File

@ -1,27 +0,0 @@
{
"extends": ["github>balena-io/renovate-config"],
"ignorePaths": [
"**/node_modules/**",
"**/bower_components/**",
"**/vendor/**",
"**/examples/**",
"**/__tests__/**",
"**/test/**",
"**/tests/suites/**",
"**/__fixtures__/**",
"**/Dockerfile.template"
],
"customManagers": [
{
"customType": "regex",
"fileMatch": [
".*"
],
"matchStrings": [
".*amiFilter=(?<packageName>.*?)\n(.*currentImageName=(?<currentDigest>.*?)\n)?(.*\n)?.*?(?<depName>[a-zA-Z0-9-_:]*)[ ]*?[:|=][ ]*?[\"|']?(?<currentValue>ami-[a-z0-9]{17})[\"|']?.*"
],
"datasourceTemplate": "aws-machine-image",
"versioningTemplate": "aws-machine-image"
}
]
}

View File

@ -8,11 +8,6 @@ on:
types: [opened, synchronize, closed] types: [opened, synchronize, closed]
branches: [main, master] branches: [main, master]
permissions:
contents: read
id-token: "write" # AWS GitHub OIDC required: write
packages: read
jobs: jobs:
flowzone: flowzone:
name: Flowzone name: Flowzone
@ -30,6 +25,15 @@ jobs:
with: with:
jobs_timeout_minutes: 60 jobs_timeout_minutes: 60
cloudflare_website: open-balena cloudflare_website: open-balena
custom_runs_on: |
[
[
"self-hosted",
"Linux",
"X64"
]
]
balena_slugs: | balena_slugs: |
balena/open-balena balena/open-balena
@ -46,3 +50,8 @@ jobs:
github.event_name == 'pull_request_target' github.event_name == 'pull_request_target'
)) && github.event.action != 'closed' )) && github.event.action != 'closed'
secrets: inherit secrets: inherit
with:
environment: balena-cloud.com
fleet: balena/open-balena
# https://dash.cloudflare.com/001b3ed2352612aaa068aca1b0022736/balena-devices.com/dns
dns_tld: balena-devices.com

View File

@ -1,15 +0,0 @@
{
"customManagers": [
{
"customType": "regex",
"fileMatch": [
".*"
],
"matchStrings": [
".*amiFilter=(?<packageName>.*?)\n(.*currentImageName=(?<currentDigest>.*?)\n)?(.*\n)?.*?(?<depName>[a-zA-Z0-9-_:]*)[ ]*?[:|=][ ]*?[\"|']?(?<currentValue>ami-[a-z0-9]{17})[\"|']?.*"
],
"datasourceTemplate": "aws-machine-image",
"versioningTemplate": "aws-machine-image"
}
]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,17 +0,0 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
exclude: ^(.versionbot/|CHANGELOG.md|VERSION|README.md)
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v5.0.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-yaml
args: [--allow-multiple-documents]
- id: check-added-large-files
- repo: https://github.com/shellcheck-py/shellcheck-py
rev: v0.10.0.1
hooks:
- id: shellcheck

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3,17 +3,15 @@ SHELL := bash
# export all variables to child processes by default # export all variables to child processes by default
export export
# include the .env file if it exists # Include the .env file
-include .env include .env
BALENARC_NO_ANALYTICS ?= 1
DNS_TLD ?= $(error DNS_TLD not set) DNS_TLD ?= $(error DNS_TLD not set)
ORG_UNIT ?= openBalena
PRODUCTION_MODE ?= true
STAGING_PKI ?= /usr/local/share/ca-certificates
SUPERUSER_EMAIL ?= admin@$(DNS_TLD)
TMPKI := $(shell mktemp) TMPKI := $(shell mktemp)
VERBOSE ?= false STAGING_PKI ?= /usr/local/share/ca-certificates
PRODUCTION_MODE ?= true
ORG_UNIT ?= openBalena
SUPERUSER_EMAIL ?= admin@$(DNS_TLD)
.NOTPARALLEL: $(DOCKERCOMPOSE) .NOTPARALLEL: $(DOCKERCOMPOSE)
@ -41,45 +39,23 @@ ifneq ($(GANDI_API_TOKEN),)
endif endif
endif endif
@rm -f .env @rm -f .env
@echo "BALENARC_NO_ANALYTICS=$(BALENARC_NO_ANALYTICS)" > .env
@echo "DNS_TLD=$(DNS_TLD)" >> .env @echo "DNS_TLD=$(DNS_TLD)" >> .env
@echo "ORG_UNIT=$(ORG_UNIT)" >> .env @echo "ORG_UNIT=$(ORG_UNIT)" >> .env
@echo "PRODUCTION_MODE=$(PRODUCTION_MODE)" >> .env
@echo "SUPERUSER_EMAIL=$(SUPERUSER_EMAIL)" >> .env @echo "SUPERUSER_EMAIL=$(SUPERUSER_EMAIL)" >> .env
@echo "VERBOSE=$(VERBOSE)" >> .env @echo "PRODUCTION_MODE=$(PRODUCTION_MODE)" >> .env
ifneq ($(ACME_EMAIL),)
@echo "ACME_EMAIL=$(ACME_EMAIL)" >> .env
endif
ifneq ($(CLOUDFLARE_API_TOKEN),)
@echo "CLOUDFLARE_API_TOKEN=$(CLOUDFLARE_API_TOKEN)" >> .env
endif
ifneq ($(GANDI_API_TOKEN),)
@echo "GANDI_API_TOKEN=$(GANDI_API_TOKEN)" >> .env @echo "GANDI_API_TOKEN=$(GANDI_API_TOKEN)" >> .env
endif @echo "CLOUDFLARE_API_TOKEN=$(CLOUDFLARE_API_TOKEN)" >> .env
ifneq ($(HAPROXY_CRT),) @echo "ACME_EMAIL=$(ACME_EMAIL)" >> .env
@echo "HAPROXY_CRT=$(HAPROXY_CRT)" >> .env @echo "HAPROXY_CRT=$(HAPROXY_CRT)" >> .env
endif
ifneq ($(HAPROXY_KEY),)
@echo "HAPROXY_KEY=$(HAPROXY_KEY)" >> .env @echo "HAPROXY_KEY=$(HAPROXY_KEY)" >> .env
endif
ifneq ($(ROOT_CA),)
@echo "ROOT_CA=$(ROOT_CA)" >> .env @echo "ROOT_CA=$(ROOT_CA)" >> .env
endif
@$(MAKE) showenv @$(MAKE) showenv
.PHONY: wait
wait: ## Wait for service
@until [[ $$(docker compose ps $(SERVICE) --format json | jq -r '.Health') =~ ^healthy$$ ]]; do printf '.'; sleep 3; done
@printf '\n'
.PHONY: waitlog
waitlog: ## Wait for log line
@until docker compose logs $(SERVICE) | grep -Eq "$(LOG_STRING)"; do printf '.'; sleep 3; done
.PHONY: up .PHONY: up
up: config ## Start all services up: config ## Start all services
@docker compose up --build -d @docker compose up --build -d
@$(MAKE) wait SERVICE=api @until [[ $$(docker compose ps api --format json | jq -r '.Health') =~ healthy ]]; do printf '.'; sleep 3; done
@printf '\n'
@$(MAKE) showenv @$(MAKE) showenv
@$(MAKE) showpass @$(MAKE) showpass
@ -107,7 +83,6 @@ stop: down ## Alias for 'make down'
.PHONY: restart .PHONY: restart
restart: ## Restart all services restart: ## Restart all services
@docker compose restart @docker compose restart
@$(MAKE) wait SERVICE=api
.PHONY: update .PHONY: update
update: # Pull and deploy latest changes from git update: # Pull and deploy latest changes from git
@ -143,10 +118,11 @@ self-signed: ## Install self-signed CA certificates
auto-pki: config # Start all services using LetsEncrypt and ACME auto-pki: config # Start all services using LetsEncrypt and ACME
@docker compose exec cert-manager rm -f /certs/export/chain.pem @docker compose exec cert-manager rm -f /certs/export/chain.pem
@docker compose up -d @docker compose up -d
@$(MAKE) waitlog SERVICE=cert-manager LOG_STRING="/certs/export/chain.pem Certificate will not expire in [0-9] days" @until docker compose logs cert-manager | grep -Eq "/certs/export/chain.pem Certificate will not expire in [0-9] days"; do printf '.'; sleep 3; done
@$(MAKE) waitlog SERVICE=cert-manager LOG_STRING="subject=CN = ${DNS_TLD}" @until docker compose logs cert-manager | grep -q "subject=CN = ${DNS_TLD}"; do printf '.'; sleep 3; done
@$(MAKE) waitlog SERVICE=cert-manager LOG_STRING="issuer=C = US, O = Let's Encrypt, CN = .*" @until docker compose logs cert-manager | grep -q "issuer=C = US, O = Let's Encrypt, CN = R3"; do printf '.'; sleep 3; done
@$(MAKE) wait SERVICE=haproxy @until [[ $$(docker compose ps haproxy --format json | jq -r '.Health') =~ healthy ]]; do printf '.'; sleep 3; done
@printf '\n'
@$(MAKE) showenv @$(MAKE) showenv
@$(MAKE) showpass @$(MAKE) showpass

View File

@ -16,23 +16,6 @@ images to your devices.
To learn more about openBalena, visit [balena.io/open][open-balena-website]. To learn more about openBalena, visit [balena.io/open][open-balena-website].
- [Features](#features)
- [Getting Started](#getting-started)
- [Compatibility](#compatibility)
- [Documentation](#documentation)
- [Getting Help](#getting-help)
- [Contributing](#contributing)
- [Roadmap](#roadmap)
- [Differences between openBalena and balenaCloud](#differences-between-openbalena-and-balenacloud)
- [License](#license)
- [FAQ](#faq)
- [How do you ensure continuity of openBalena? Are there security patches on openBalena?](#how-do-you-ensure-continuity-of-openbalena-are-there-security-patches-on-openbalena)
- [How do you ensure the "Join" command actually works between openBalena and](#how-do-you-ensure-the-join-command-actually-works-between-openbalena-and)
- [Is it "production ready"?](#is-it-production-ready)
- [Can a new device type be added to openBalena?](#can-a-new-device-type-be-added-to-openbalena)
- [Are there open-source UI dashboards from the community for openBalena?](#are-there-open-source-ui-dashboards-from-the-community-for-openbalena)
## Features ## Features
@ -176,7 +159,7 @@ While we actually have some rather large fleets using openBalena, we consider it
perpetually in "beta". This means potentially introducing breaking changes between perpetually in "beta". This means potentially introducing breaking changes between
releases. releases.
### Can a new device type be added to openBalena? ### Can new device type be added to openBalena?
openBalena imports the following public [device-types] "out of the box". You can specify openBalena imports the following public [device-types] "out of the box". You can specify
your own contracts repository by overriding `CONTRACTS_PUBLIC_REPO_NAME`, your own contracts repository by overriding `CONTRACTS_PUBLIC_REPO_NAME`,
`CONTRACTS_PUBLIC_REPO_OWNER` and `IMAGE_STORAGE_BUCKET` environment variables on the API `CONTRACTS_PUBLIC_REPO_OWNER` and `IMAGE_STORAGE_BUCKET` environment variables on the API

View File

@ -1 +1 @@
4.1.390 4.0.8

View File

@ -23,4 +23,4 @@ data:
- generic-amd64 - generic-amd64
- genericx86-64-ext - genericx86-64-ext
- intel-nuc - intel-nuc
version: 4.1.390 version: 4.0.8

View File

@ -26,7 +26,7 @@ x-default-environment: &default-environment
DB_PASSWORD: docker DB_PASSWORD: docker
DB_USER: docker DB_USER: docker
LOG_LEVEL: DEBUG LOG_LEVEL: DEBUG
PRODUCTION_MODE: 'true' PRODUCTION_MODE: 'false'
x-default-healthcheck-trait: &with-default-healthcheck x-default-healthcheck-trait: &with-default-healthcheck
healthcheck: healthcheck:
@ -64,11 +64,11 @@ x-network-privileges-trait: &with-network-privileges
- SYS_RESOURCE - SYS_RESOURCE
x-base-service-definition: &base-service x-base-service-definition: &base-service
restart: 'unless-stopped' restart: unless-stopped
# for docker-compose only, no effect on balenaCloud # for docker-compose only, no effect on balenaCloud
env_file: env_file:
- .env - .env
tty: true # send syastemd logs from containers to stdout tty: 'true' # send syastemd logs from containers to stdout
services: services:
# https://github.com/balena-io/open-balena-api # https://github.com/balena-io/open-balena-api
@ -79,7 +79,7 @@ services:
*with-default-privileges, *with-default-privileges,
*with-default-volumes, *with-default-volumes,
] ]
image: balena/open-balena-api:35.0.0 image: balena/open-balena-api:v22.2.3
depends_on: depends_on:
- db - db
- redis - redis
@ -110,7 +110,7 @@ services:
TRUST_PROXY: 172.16.0.0/12 TRUST_PROXY: 172.16.0.0/12
VPN_PORT: 443 VPN_PORT: 443
WEBRESOURCES_S3_BUCKET: web-resources WEBRESOURCES_S3_BUCKET: web-resources
WEBRESOURCES_S3_REGION: 'us-east-1' # this is required for minio WEBRESOURCES_S3_REGION: "us-east-1" # this is required for minio
# https://github.com/balena-io/open-balena-registry # https://github.com/balena-io/open-balena-registry
registry: registry:
@ -119,7 +119,7 @@ services:
*with-default-healthcheck, *with-default-healthcheck,
*with-default-privileges, *with-default-privileges,
] ]
image: balena/open-balena-registry:2.41.25 image: balena/open-balena-registry:v2.39.56
volumes: volumes:
- certs-data:/certs - certs-data:/certs
- resin-data:/balena - resin-data:/balena
@ -146,7 +146,7 @@ services:
*with-network-privileges, *with-network-privileges,
*with-default-privileges, *with-default-privileges,
] ]
image: balena/open-balena-vpn:11.32.6 image: balena/open-balena-vpn:v11.30.22
depends_on: depends_on:
- api - api
environment: environment:
@ -156,13 +156,11 @@ services:
VPN_PORT: 443 VPN_PORT: 443
# ensure correct service instance IP is registered with the API # ensure correct service instance IP is registered with the API
VPN_SERVICE_REGISTER_INTERFACE: eth0 VPN_SERVICE_REGISTER_INTERFACE: eth0
devices:
- /dev/net/tun
# https://github.com/balena-io/open-balena-db # https://github.com/balena-io/open-balena-db
db: db:
<<: *base-service <<: *base-service
image: balena/open-balena-db:6.0.0 image: balena/open-balena-db:v5.2.2
volumes: volumes:
- db-data:/var/lib/postgresql/data - db-data:/var/lib/postgresql/data
environment: environment:
@ -177,7 +175,7 @@ services:
*with-default-healthcheck, *with-default-healthcheck,
*with-default-privileges, *with-default-privileges,
] ]
image: balena/open-balena-s3:2.28.68 image: balena/open-balena-s3:v2.28.43
volumes: volumes:
- s3-data:/export - s3-data:/export
- certs-data:/certs - certs-data:/certs
@ -191,7 +189,7 @@ services:
redis: redis:
<<: *base-service <<: *base-service
# https://redis.io/blog/what-redis-license-change-means-for-our-managed-service-providers/ # https://redis.io/blog/what-redis-license-change-means-for-our-managed-service-providers/
image: redis:7.4-alpine image: redis:7.2-alpine
volumes: volumes:
- redis-data:/data - redis-data:/data
healthcheck: healthcheck:
@ -214,11 +212,11 @@ services:
test: true | openssl s_client -connect localhost:443 test: true | openssl s_client -connect localhost:443
ports: ports:
# haproxy/http # haproxy/http
- '80:80/tcp' - "80:80/tcp"
# haproxy/tcp-router # haproxy/tcp-router
- '443:443/tcp' - "443:443/tcp"
# haproxy/stats # haproxy/stats
- '1936:1936/tcp' - "1936:1936/tcp"
environment: environment:
LOGLEVEL: info LOGLEVEL: info
@ -235,7 +233,7 @@ services:
ALIASES: api,ca,cloudlink,db,delta,logs,redis,registry2,s3,stats,tunnel ALIASES: api,ca,cloudlink,db,delta,logs,redis,registry2,s3,stats,tunnel
labels: labels:
io.balena.features.balena-socket: 1 io.balena.features.balena-socket: 1
io.balena.features.supervisor-api: 1 io.balena.features.supervisor-api : 1
# https://github.com/balena-io/cert-manager # https://github.com/balena-io/cert-manager
# https://certbot.eff.org/docs/using.html # https://certbot.eff.org/docs/using.html
@ -261,7 +259,7 @@ services:
# https://github.com/cloudflare/cfssl/blob/master/doc/api/intro.txt # https://github.com/cloudflare/cfssl/blob/master/doc/api/intro.txt
balena-ca: balena-ca:
<<: *base-service <<: *base-service
image: balena/ca-private:0.0.15 image: balena/ca-private:v0.0.14
volumes: volumes:
- pki-data:/pki - pki-data:/pki
- certs-data:/certs - certs-data:/certs
@ -283,7 +281,7 @@ services:
# only relevant when running in AWS/EC2 # only relevant when running in AWS/EC2
tag-sidecar: tag-sidecar:
build: src/tag-sidecar build: src/tag-sidecar
restart: 'no' restart: no
environment: environment:
ENABLED: 'true' ENABLED: 'true'
labels: labels:
@ -310,7 +308,7 @@ services:
labels: labels:
io.balena.features.balena-api: 1 io.balena.features.balena-api: 1
io.balena.features.supervisor-api: 1 io.balena.features.supervisor-api: 1
restart: 'no' restart: no
# virtual Device Under Test (DUT) # virtual Device Under Test (DUT)
dut: dut:
@ -335,7 +333,7 @@ services:
- resin-data:/balena - resin-data:/balena
devices: devices:
- /dev/net/tun - /dev/net/tun
restart: 'no' restart: no
# https://hub.docker.com/_/docker # https://hub.docker.com/_/docker
# pseudo(builder) service for balena-tests # pseudo(builder) service for balena-tests
@ -346,23 +344,11 @@ services:
*with-network-privileges, *with-network-privileges,
] ]
image: docker:dind image: docker:dind
entrypoint:
- /bin/sh
- -c
command:
- |
set -x
cp /certs/root-ca.pem /certs/server-ca.pem /usr/local/share/ca-certificates/ \
&& update-ca-certificates
exec /usr/local/bin/dockerd-entrypoint.sh
volumes: volumes:
- /sys:/sys - builder-data:/var/lib/docker
- builder-certs-ca:/docker-pki/ca - builder-certs-ca:/docker-pki/ca
- builder-certs-client:/docker-pki/client - builder-certs-client:/docker-pki/client
- builder-data:/var/lib/docker - /sys:/sys
- certs-data:/certs
environment: environment:
DOCKER_TLS_CERTDIR: /docker-pki DOCKER_TLS_CERTDIR: /docker-pki
healthcheck: healthcheck:

View File

@ -82,7 +82,7 @@ name and configure records.
```bash ```bash
sudo useradd -s /bin/bash -m -G docker,sudo balena sudo useradd -s /bin/bash -m -G docker,sudo balena
echo 'balena ALL=(ALL) NOPASSWD: ALL' | sudo tee /etc/sudoers.d/balena echo 'balena ALL=(ALL) NOPASSWD: ALL' | tee >/etc/sudoers.d/balena
``` ```
6. Switch user: 6. Switch user:

View File

@ -1,7 +1,7 @@
FROM ubuntu:24.04 FROM ubuntu:22.04
# renovate: datasource=github-releases depName=balena-io/balena-cli # renovate: datasource=github-releases depName=balena-io/balena-cli
ARG BALENA_CLI_VERSION=v21.1.0 ARG BALENA_CLI_VERSION=v18.2.2
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
bash \ bash \

View File

@ -1,24 +1,23 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# shellcheck disable=SC2034,SC1090 # shellcheck disable=SC2154,SC2034,SC1090
set -aeu set -ae
read -ra curl_opts <<<'--retry 3 --fail' curl_opts="--retry 3 --fail"
if [[ $VERBOSE =~ on|On|Yes|yes|true|True ]]; then if [[ $VERBOSE =~ on|On|Yes|yes|true|True ]]; then
set -x set -x
curl_opts+=('--verbose') curl_opts="${curl_opts} --verbose"
else else
curl_opts+=('--silent') curl_opts="${curl_opts} --silent"
fi fi
# shellcheck disable=SC1091
source /usr/sbin/functions source /usr/sbin/functions
function remove_test_assets() { function remove_test_assets() {
rm -rf /balena/config.json \ rm -rf /balena/config.json \
"${GUEST_IMAGE}" \ "${GUEST_IMAGE}" \
"${GUEST_IMAGE%.*}.ready" \ "${GUEST_IMAGE%.*}.ready" \
"${tmpbuild:-}" \ "${tmpbuild}" \
/tmp/*.img /tmp/*.img
} }
@ -40,20 +39,18 @@ function shutdown_dut() {
local balena_device_uuid local balena_device_uuid
balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)" balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)"
if [[ -n "${balena_device_uuid:-}" ]]; then if [[ -n $balena_device_uuid ]]; then
with_backoff balena device "${balena_device_uuid}" with_backoff balena device "${balena_device_uuid}"
if ! with_backoff balena device shutdown -f "${balena_device_uuid}"; then balena device shutdown -f "${balena_device_uuid}" || true
echo 'DUT failed to shutdown properly'
fi
fi fi
} }
function set_update_lock { function set_update_lock {
if [[ -n "${BALENA_SUPERVISOR_ADDRESS:-}" ]] && [[ -n "${BALENA_SUPERVISOR_API_KEY:-}" ]]; then if [[ -n "$BALENA_SUPERVISOR_ADDRESS" ]] && [[ -n "$BALENA_SUPERVISOR_API_KEY" ]]; then
while [[ $(curl "${curl_opts[@]}" "${BALENA_SUPERVISOR_ADDRESS}/v1/device?apikey=${BALENA_SUPERVISOR_API_KEY}" \ while [[ $(curl ${curl_opts} "${BALENA_SUPERVISOR_ADDRESS}/v1/device?apikey=${BALENA_SUPERVISOR_API_KEY}" \
-H "Content-Type: application/json" | jq -r '.update_pending') == 'true' ]]; do -H "Content-Type: application/json" | jq -r '.update_pending') == 'true' ]]; do
curl "${curl_opts[@]}" "${BALENA_SUPERVISOR_ADDRESS}/v1/device?apikey=${BALENA_SUPERVISOR_API_KEY}" \ curl ${curl_opts} "${BALENA_SUPERVISOR_ADDRESS}/v1/device?apikey=${BALENA_SUPERVISOR_API_KEY}" \
-H "Content-Type: application/json" | jq -r -H "Content-Type: application/json" | jq -r
sleep "$(( (RANDOM % 3) + 3 ))s" sleep "$(( (RANDOM % 3) + 3 ))s"
@ -90,8 +87,7 @@ function update_ca_certificates() {
} }
function wait_for_api() { function wait_for_api() {
while ! curl "${curl_opts[@]}" "https://api.${DNS_TLD}/ping"; do while ! curl ${curl_opts} "https://api.${DNS_TLD}/ping"; do
echo 'waiting for API...'
sleep "$(( (RANDOM % 5) + 5 ))s" sleep "$(( (RANDOM % 5) + 5 ))s"
done done
} }
@ -100,7 +96,6 @@ function open_balena_login() {
while ! balena login --credentials \ while ! balena login --credentials \
--email "${SUPERUSER_EMAIL}" \ --email "${SUPERUSER_EMAIL}" \
--password "${SUPERUSER_PASSWORD}"; do --password "${SUPERUSER_PASSWORD}"; do
echo 'waiting for auth...'
sleep "$(( (RANDOM % 5) + 5 ))s" sleep "$(( (RANDOM % 5) + 5 ))s"
done done
} }
@ -109,7 +104,6 @@ function create_fleet() {
if ! balena fleet "${TEST_FLEET}"; then if ! balena fleet "${TEST_FLEET}"; then
# wait for API to load DT contracts # wait for API to load DT contracts
while ! balena fleet create "${TEST_FLEET}" --type "${DEVICE_TYPE}"; do while ! balena fleet create "${TEST_FLEET}" --type "${DEVICE_TYPE}"; do
echo 'waiting for device types...'
sleep "$(( (RANDOM % 5) + 5 ))s" sleep "$(( (RANDOM % 5) + 5 ))s"
done done
@ -164,7 +158,7 @@ function check_device_status() {
balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)" balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)"
if [[ -n $balena_device_uuid ]]; then if [[ -n $balena_device_uuid ]]; then
is_online="$(balena device list --json --fleet "${TEST_FLEET}" \ is_online="$(balena devices --json --fleet "${TEST_FLEET}" \
| jq -r --arg uuid "${balena_device_uuid}" '.[] | select(.uuid==$uuid).is_online == true')" | jq -r --arg uuid "${balena_device_uuid}" '.[] | select(.uuid==$uuid).is_online == true')"
if [[ $is_online =~ true ]]; then if [[ $is_online =~ true ]]; then
@ -181,10 +175,9 @@ function wait_for_device() {
} }
function registry_auth() { function registry_auth() {
if [[ -n "${REGISTRY_USER:-}" ]] && [[ -n "${REGISTRY_PASS:-}" ]]; then if [[ -n $REGISTRY_USER ]] && [[ -n $REGISTRY_PASS ]]; then
with_backoff docker login -u "${REGISTRY_USER}" -p "${REGISTRY_PASS}" with_backoff docker login -u "${REGISTRY_USER}" -p "${REGISTRY_PASS}"
# shellcheck disable=SC2016
printf '{"https://index.docker.io/v1/": {"username":"%s", "password":"$s"}}' \ printf '{"https://index.docker.io/v1/": {"username":"%s", "password":"$s"}}' \
"${REGISTRY_USER}" "${REGISTRY_PASS}" | jq -r > ~/.balena/secrets.json "${REGISTRY_USER}" "${REGISTRY_PASS}" | jq -r > ~/.balena/secrets.json
fi fi
@ -208,29 +201,31 @@ function deploy_release() {
} }
function get_releases() { function get_releases() {
with_backoff balena release list --json "${TEST_FLEET}" with_backoff balena releases --json "${TEST_FLEET}"
} }
function get_release_commit() { function get_release_commit() {
get_releases | jq -re \ echo "$(get_releases)" | jq -re \
'[.[] | select((.status=="success") 'select((.[].status=="success")
and (.is_invalidated==false) and (.[].is_invalidated==false)
and (.is_final==true))][0].commit' and (.[].is_final==true)
and (.[].release_type=="final"))[0].commit'
} }
function get_release_id() { function get_release_id() {
get_releases | jq -re \ echo "$(get_releases)" | jq -re \
'[.[] | select((.status=="success") 'select((.[].status=="success")
and (.is_invalidated==false) and (.[].is_invalidated==false)
and (.is_final==true))][0].id' and (.[].is_final==true)
and (.[].release_type=="final"))[0].id'
} }
function supervisor_update_target_state() { function supervisor_update_target_state() {
local balena_device_uuid local balena_device_uuid
balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)" balena_device_uuid="$(cat </balena/config.json | jq -r .uuid)"
if [[ -n "${balena_device_uuid:-}" ]]; then if [[ -n $balena_device_uuid ]]; then
while ! curl "${curl_opts[@]}" "https://api.${DNS_TLD}/supervisor/v1/update" \ while ! curl ${curl_opts} "https://api.${DNS_TLD}/supervisor/v1/update" \
--header "Content-Type: application/json" \ --header "Content-Type: application/json" \
--header "Authorization: Bearer $(cat <~/.balena/token)" \ --header "Authorization: Bearer $(cat <~/.balena/token)" \
--data "{\"uuid\": \"${balena_device_uuid}\", \"data\": {\"force\": true}}"; do --data "{\"uuid\": \"${balena_device_uuid}\", \"data\": {\"force\": true}}"; do
@ -246,14 +241,14 @@ function check_running_release() {
local should_be_running_release local should_be_running_release
should_be_running_release="$(get_release_commit)" should_be_running_release="$(get_release_commit)"
[[ -z "$should_be_running_release" ]] && false [[ -z $should_be_running_release ]] && false
if [[ -n "${balena_device_uuid:-}" ]]; then if [[ -n $balena_device_uuid ]]; then
while ! [[ $(balena device "${balena_device_uuid}" | grep -E ^COMMIT | awk '{print $2}') =~ ${should_be_running_release} ]]; do while ! [[ $(balena device "${balena_device_uuid}" | grep -E ^COMMIT | awk '{print $2}') =~ ${should_be_running_release} ]]; do
running_release_id="$(balena device "${balena_device_uuid}" | grep -E ^COMMIT | awk '{print $2}')" running_release_id="$(balena device "${balena_device_uuid}" | grep -E ^COMMIT | awk '{print $2}')"
printf 'please wait, device %s should be running %s, but is still running %s...\n' \ printf 'please wait, device %s should be running %s, but is still running %s...\n' \
"${balena_device_uuid}" \ "${balena_device_uuid}" \
"${should_be_running_release}" \ "${1}" \
"${running_release_id}" "${running_release_id}"
sleep "$(( (RANDOM % 5) + 5 ))s" sleep "$(( (RANDOM % 5) + 5 ))s"
@ -263,7 +258,7 @@ function check_running_release() {
function get_os_version() { function get_os_version() {
local BALENARC_BALENA_URL local BALENARC_BALENA_URL
BALENARC_BALENA_URL="${BALENA_API_URL//https:\/\/api\./}" BALENARC_BALENA_URL="$(echo "${BALENA_API_URL}" | sed 's#https://api\.##g')"
local os_version local os_version
os_version=${OS_VERSION:-$(with_backoff balena os versions "${DEVICE_TYPE}" | head -n 1)} os_version=${OS_VERSION:-$(with_backoff balena os versions "${DEVICE_TYPE}" | head -n 1)}
@ -271,27 +266,27 @@ function get_os_version() {
} }
function upload_release_asset() { function upload_release_asset() {
if [[ "${RELEASE_ASSETS_T:-}" =~ true ]]; then if [[ "$RELEASE_ASSETS_TEST" =~ true ]]; then
local release_id local release_id
release_id=${1:-1} release_id=${1:-1}
release_asset="$(find / -type f -name '*.png' | head -n 1)" release_asset="$(find / -type f -name '*.png' | head -n 1)"
curl "${curl_opts[@]}" "https://api.${DNS_TLD}/resin/release_asset" \ curl ${curl_opts} "https://api.${DNS_TLD}/resin/release_asset" \
--header "Authorization: Bearer $(cat <~/.balena/token)" \ --header "Authorization: Bearer $(cat <~/.balena/token)" \
--form "asset=@${release_asset}" \ --form "asset=@${release_asset}" \
--form "release=${release_id}" \ --form "release=${release_id}" \
--form "asset_key=$((RANDOM))-$(basename "${release_asset}")" \ --form "asset_key=$((RANDOM))-$(basename ${release_asset})" \
| jq -re .asset.href \ | jq -re .asset.href \
| xargs curl "${curl_opts[@]}" -o "/tmp/$((RANDOM))-$(basename "${release_asset}")" | xargs curl ${curl_opts} -o "/tmp/$((RANDOM))-$(basename ${release_asset})"
fi fi
} }
# --- main # --- main
if [[ "${PRODUCTION_MODE:-}" =~ true ]]; then if [[ "$PRODUCTION_MODE" =~ true ]]; then
exit exit
fi fi
if [[ -n "${BALENA_DEVICE_UUID:-}" ]]; then if [[ -n "${BALENA_DEVICE_UUID}" ]]; then
# prepend the device UUID if running on balenaOS # prepend the device UUID if running on balenaOS
TLD="${BALENA_DEVICE_UUID}.${DNS_TLD}" TLD="${BALENA_DEVICE_UUID}.${DNS_TLD}"
else else
@ -308,19 +303,7 @@ GUEST_IMAGE=${GUEST_IMAGE:-/balena/balena.img}
OS_VERSION="$(get_os_version)" OS_VERSION="$(get_os_version)"
TEST_FLEET=${TEST_FLEET:-test-fleet} TEST_FLEET=${TEST_FLEET:-test-fleet}
# wait here until global config is ready [[ -f "$CONF" ]] && source "${CONF}"
until [[ -s "$CONF" ]]; do
echo 'waiting for config...'
sleep "$(( (RANDOM % 5) + 5 ))s"
done
source "${CONF}"
# wait her until we have valid login credentials
until [[ -n "${SUPERUSER_EMAIL:-}" ]] && [[ -n "${SUPERUSER_PASSWORD:-}" ]]; do
echo 'waiting for credentials...'
sleep "$(( (RANDOM % 5) + 5 ))s"
source "${CONF}"
done
update_ca_certificates # ensure self-signed root CA certificate(s) trust update_ca_certificates # ensure self-signed root CA certificate(s) trust

View File

@ -1,4 +1,4 @@
# https://github.com/balena-io/cert-manager # https://github.com/balena-io/cert-manager
FROM balena/cert-manager:0.3.2 FROM balena/cert-manager:v0.2.2
COPY *.json /opt/ COPY *.json /opt/

View File

@ -1,6 +1,6 @@
# https://hub.docker.com/r/qemux/qemu-docker # https://hub.docker.com/r/qemux/qemu-docker
# https://github.com/qemus/qemu-docker # https://github.com/qemus/qemu-docker
FROM qemux/qemu-docker:6.20 FROM qemux/qemu-docker:4.28
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
minicom \ minicom \