mirror of
https://github.com/balena-io/open-balena.git
synced 2025-04-24 13:05:57 +00:00
Compare commits
No commits in common. "master" and "v4.0.25" have entirely different histories.
8
.github/actionlint.yaml
vendored
8
.github/actionlint.yaml
vendored
@ -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
27
.github/renovate.json
vendored
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
19
.github/workflows/flowzone.yml
vendored
19
.github/workflows/flowzone.yml
vendored
@ -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
|
||||||
|
15
.github/workflows/renovate.json
vendored
15
.github/workflows/renovate.json
vendored
@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
816
.github/workflows/tests.yml
vendored
816
.github/workflows/tests.yml
vendored
File diff suppressed because it is too large
Load Diff
@ -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
2117
CHANGELOG.md
2117
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
56
Makefile
56
Makefile
@ -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
|
||||||
|
|
||||||
|
19
README.md
19
README.md
@ -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
|
||||||
|
@ -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.25
|
||||||
|
@ -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:v24.1.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.57
|
||||||
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.44
|
||||||
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
|
||||||
|
|
||||||
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
FROM ubuntu:24.04
|
FROM ubuntu:24.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 \
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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/
|
||||||
|
@ -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:5.12
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
minicom \
|
minicom \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user