Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: implement bare-metal provider
Browse files Browse the repository at this point in the history
Add initial implementation of the bare-metal infra provider.

Related to siderolabs/omni#660.

Signed-off-by: Utku Ozdemir <utku.ozdemir@siderolabs.com>
utkuozdemir committed Nov 28, 2024
1 parent c3e892b commit 70acf82
Showing 76 changed files with 9,047 additions and 0 deletions.
18 changes: 18 additions & 0 deletions .codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-10-14T09:32:55Z by kres 34e72ac.

codecov:
require_ci_to_pass: false

coverage:
status:
project:
default:
target: 0%
threshold: 0.5%
base: auto
if_ci_failed: success
patch: off

comment: false
48 changes: 48 additions & 0 deletions .conform.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-10-14T09:32:55Z by kres 34e72ac.

policies:
- type: commit
spec:
dco: true
gpg:
required: true
identity:
gitHubOrganization: siderolabs
spellcheck:
locale: US
maximumOfOneCommit: true
header:
length: 89
imperative: true
case: lower
invalidLastCharacters: .
body:
required: true
conventional:
types:
- chore
- docs
- perf
- refactor
- style
- test
- release
scopes:
- .*
- type: license
spec:
root: .
skipPaths:
- .git/
- testdata/
includeSuffixes:
- .go
excludeSuffixes:
- .pb.go
- .pb.gw.go
header: |
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 changes: 13 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-10-14T09:34:03Z by kres 34e72ac.

*
!api
!cmd
!internal
!go.mod
!go.sum
!.golangci.yml
!README.md
!.markdownlint.json
169 changes: 169 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-28T09:31:42Z by kres 232fe63.

name: default
concurrency:
group: ${{ github.head_ref || github.run_id }}
cancel-in-progress: true
"on":
push:
branches:
- main
- release-*
tags:
- v*
pull_request:
branches:
- main
- release-*
jobs:
default:
permissions:
actions: read
contents: write
issues: read
packages: write
pull-requests: read
runs-on:
- self-hosted
- generic
if: (!startsWith(github.head_ref, 'renovate/') && !startsWith(github.head_ref, 'dependabot/'))
steps:
- name: gather-system-info
id: system-info
uses: kenchan0130/actions-system-info@v1.3.0
continue-on-error: true
- name: print-system-info
run: |
MEMORY_GB=$((${{ steps.system-info.outputs.totalmem }}/1024/1024/1024))
OUTPUTS=(
"CPU Core: ${{ steps.system-info.outputs.cpu-core }}"
"CPU Model: ${{ steps.system-info.outputs.cpu-model }}"
"Hostname: ${{ steps.system-info.outputs.hostname }}"
"NodeName: ${NODE_NAME}"
"Kernel release: ${{ steps.system-info.outputs.kernel-release }}"
"Kernel version: ${{ steps.system-info.outputs.kernel-version }}"
"Name: ${{ steps.system-info.outputs.name }}"
"Platform: ${{ steps.system-info.outputs.platform }}"
"Release: ${{ steps.system-info.outputs.release }}"
"Total memory: ${MEMORY_GB} GB"
)
for OUTPUT in "${OUTPUTS[@]}";do
echo "${OUTPUT}"
done
continue-on-error: true
- name: checkout
uses: actions/checkout@v4
- name: Unshallow
run: |
git fetch --prune --unshallow
- name: Set up Docker Buildx
id: setup-buildx
uses: docker/setup-buildx-action@v3
with:
driver: remote
endpoint: tcp://buildkit-amd64.ci.svc.cluster.local:1234
timeout-minutes: 10
- name: Mask secrets
run: |
echo "$(sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | "::add-mask::" + .value')"
- name: Set secrets for job
run: |
sops -d .secrets.yaml | yq -e '.secrets | to_entries[] | .key + "=" + .value' >> "$GITHUB_ENV"
- name: base
run: |
make base
- name: unit-tests
run: |
make unit-tests
- name: unit-tests-race
run: |
make unit-tests-race
- name: provider
run: |
make provider
- name: lint
run: |
make lint
- name: Login to registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io
username: ${{ github.repository_owner }}
- name: image-provider
run: |
make image-provider
- name: push-provider
if: github.event_name != 'pull_request'
env:
PLATFORM: linux/amd64,linux/arm64
PUSH: "true"
run: |
make image-provider
- name: qemu-up
run: |
make qemu-up
- name: Login to registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v3
with:
password: ${{ secrets.GITHUB_TOKEN }}
registry: ghcr.io
username: ${{ github.repository_owner }}
- name: image-qemu-up
run: |
make image-qemu-up
- name: push-qemu-up
if: github.event_name != 'pull_request'
env:
PLATFORM: linux/amd64,linux/arm64
PUSH: "true"
run: |
make image-qemu-up
- name: run-integration-test
run: |
sudo -E make run-integration-test
- name: Generate executable list
run: |
find _out -type f -executable > _out/executable-artifacts
- name: save-artifacts
uses: actions/upload-artifact@v4
with:
name: artifacts
path: |
_out
retention-days: "5"
- name: save-talos-logs-artifacts
if: always()
uses: actions/upload-artifact@v4
with:
name: talos-logs
path: |-
~/.talos/clusters/**/*.log
!~/.talos/clusters/**/swtpm.log
retention-days: "5"
- name: Generate Checksums
if: startsWith(github.ref, 'refs/tags/')
run: |
cd _out
sha256sum provider-* qemu-up-* > sha256sum.txt
sha512sum provider-* qemu-up-* > sha512sum.txt
- name: release-notes
if: startsWith(github.ref, 'refs/tags/')
run: |
make release-notes
- name: Release
if: startsWith(github.ref, 'refs/tags/')
uses: crazy-max/ghaction-github-release@v2
with:
body_path: _out/RELEASE_NOTES.md
draft: "true"
files: |-
_out/provider-*
_out/qemu-up-*
_out/sha*.txt
92 changes: 92 additions & 0 deletions .github/workflows/slack-notify.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-26T10:24:08Z by kres 232fe63.

name: slack-notify
"on":
workflow_run:
workflows:
- default
types:
- completed
jobs:
slack-notify:
runs-on:
- self-hosted
- generic
if: github.event.workflow_run.conclusion != 'skipped'
steps:
- name: Get PR number
id: get-pr-number
if: github.event.workflow_run.event == 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
run: |
echo pull_request_number=$(gh pr view -R ${{ github.repository }} ${{ github.event.workflow_run.head_repository.owner.login }}:${{ github.event.workflow_run.head_branch }} --json number --jq .number) >> $GITHUB_OUTPUT
- name: Slack Notify
uses: slackapi/slack-github-action@v2
with:
method: chat.postMessage
payload: |
{
"channel": "proj-talos-maintainers",
"attachments": [
{
"color": "${{ github.event.workflow_run.conclusion == 'success' && '#2EB886' || github.event.workflow_run.conclusion == 'failure' && '#A30002' || '#FFCC00' }}",
"fallback": "test",
"blocks": [
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "${{ github.event.workflow_run.event == 'pull_request' && format('*Pull Request:* {0} (`{1}`)\n<{2}/pull/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, steps.get-pr-number.outputs.pull_request_number, github.event.workflow_run.display_title) || format('*Build:* {0} (`{1}`)\n<{2}/commit/{3}|{4}>', github.repository, github.ref_name, github.event.repository.html_url, github.sha, github.event.workflow_run.display_title) }}"
},
{
"type": "mrkdwn",
"text": "*Status:*\n`${{ github.event.workflow_run.conclusion }}`"
}
]
},
{
"type": "section",
"fields": [
{
"type": "mrkdwn",
"text": "*Author:*\n`${{ github.actor }}`"
},
{
"type": "mrkdwn",
"text": "*Event:*\n`${{ github.event.workflow_run.event }}`"
}
]
},
{
"type": "divider"
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Logs"
},
"url": "${{ github.event.workflow_run.html_url }}"
},
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Commit"
},
"url": "${{ github.event.repository.html_url }}/commit/${{ github.sha }}"
}
]
}
]
}
]
}
token: ${{ secrets.SLACK_BOT_TOKEN }}
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-28T09:31:42Z by kres 232fe63.

_out
hack/compose/docker-compose.override.yml
149 changes: 149 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-18T15:38:35Z by kres 91b35db.

# options for analysis running
run:
timeout: 10m
issues-exit-code: 1
tests: true
build-tags: [ ]
modules-download-mode: readonly

# output configuration options
output:
formats:
- format: colored-line-number
path: stdout
print-issued-lines: true
print-linter-name: true
uniq-by-line: true
path-prefix: ""

# all available settings of specific linters
linters-settings:
dogsled:
max-blank-identifiers: 2
dupl:
threshold: 150
errcheck:
check-type-assertions: true
check-blank: true
exhaustive:
default-signifies-exhaustive: false
gci:
sections:
- standard # Standard section: captures all standard packages.
- default # Default section: contains all imports that could not be matched to another section type.
- localmodule # Imports from the same module.
gocognit:
min-complexity: 30
nestif:
min-complexity: 5
goconst:
min-len: 3
min-occurrences: 3
gocritic:
disabled-checks: [ ]
gocyclo:
min-complexity: 20
godot:
scope: declarations
gofmt:
simplify: true
gomodguard: { }
govet:
enable-all: true
lll:
line-length: 200
tab-width: 4
misspell:
locale: US
ignore-words: [ ]
nakedret:
max-func-lines: 30
prealloc:
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
nolintlint:
allow-unused: false
allow-no-explanation: [ ]
require-explanation: false
require-specific: true
rowserrcheck: { }
testpackage: { }
unparam:
check-exported: false
unused:
local-variables-are-used: false
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
wsl:
strict-append: true
allow-assign-and-call: true
allow-multiline-assign: true
allow-cuddle-declarations: false
allow-trailing-comment: false
force-case-trailing-whitespace: 0
force-err-cuddling: false
allow-separated-leading-comment: false
gofumpt:
extra-rules: false
cyclop:
# the maximal code complexity to report
max-complexity: 20
depguard:
rules:
prevent_unmaintained_packages:
list-mode: lax # allow unless explicitly denied
files:
- $all
deny:
- pkg: io/ioutil
desc: "replaced by io and os packages since Go 1.16: https://tip.golang.org/doc/go1.16#ioutil"

linters:
enable-all: true
disable-all: false
fast: false
disable:
- exhaustruct
- err113
- forbidigo
- funlen
- gochecknoglobals
- gochecknoinits
- godox
- gomoddirectives
- gosec
- inamedparam
- ireturn
- mnd
- nestif
- nonamedreturns
- paralleltest
- tagalign
- tagliatelle
- thelper
- varnamelen
- wrapcheck
- testifylint # complains about our assert recorder and has a number of false positives for assert.Greater(t, thing, 1)
- protogetter # complains about us using Value field on typed spec, instead of GetValue which has a different signature
- perfsprint # complains about us using fmt.Sprintf in non-performance critical code, updating just kres took too long
- goimports # same as gci
- musttag # seems to be broken - goes into imported libraries and reports issues there

issues:
exclude: [ ]
exclude-rules: [ ]
exclude-use-default: false
exclude-case-sensitive: false
max-issues-per-linter: 10
max-same-issues: 3
new: false

severity:
default-severity: error
case-sensitive: false
139 changes: 139 additions & 0 deletions .kres.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
kind: common.Build
spec:
ignoredPaths:
- hack/compose/docker-compose.override.yml
---
kind: common.Image
name: image-metal-agent
spec:
pushLatest: false
extraEnvironment:
PLATFORM: linux/amd64,linux/arm64
---
kind: common.Image
name: image-qemu-up
spec:
baseImage: ghcr.io/siderolabs/talosctl:v1.9.0-alpha.3
pushLatest: false
extraEnvironment:
PLATFORM: linux/amd64,linux/arm64
---
kind: custom.Step
name: ipxe
spec:
docker:
enabled: true
stages:
- name: ipxe-linux-amd64
from: ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4
platform: linux/amd64
- name: ipxe-linux-arm64
from: ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4
platform: linux/arm64
---
kind: auto.CustomSteps
spec:
steps:
- name: ipxe
toplevel: true
- name: run-integration-test
toplevel: true
---
kind: common.Image
name: image-provider
spec:
pushLatest: false
extraEnvironment:
PLATFORM: linux/amd64,linux/arm64
copyFrom:
- stage: ghcr.io/siderolabs/musl:v1.8.0-16-g71d23b4 # required by zbin
source: /
destination: /
- stage: ghcr.io/siderolabs/liblzma:v1.8.0-16-g71d23b4 # required by zbin
source: /
destination: /
- stage: ghcr.io/siderolabs/openssl:v1.8.0-16-g71d23b4 # required by ipmitool
source: /
destination: /
- stage: ghcr.io/siderolabs/ipmitool:v1.8.0-16-g71d23b4
source: /
destination: /
- stage: ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4
source: /usr/libexec/zbin
destination: /bin/zbin
- stage: ipxe-linux-amd64
source: /usr/libexec/
destination: /var/lib/ipxe/amd64
- stage: ipxe-linux-arm64
source: /usr/libexec/
destination: /var/lib/ipxe/arm64
-
stage: ghcr.io/siderolabs/talos-metal-agent-boot-assets:v1.9.0-alpha.3-agent-v0.1.0-alpha.2 # to be used with --use-local-boot-assets for local development
# stage: 127.0.0.1:5005/siderolabs/talos-metal-agent-boot-assets:v0.0.1-local # for local development, to be replaced with the line above and rekres-ed
source: /
destination: /assets
---
kind: golang.Build
spec:
outputs:
linux-amd64:
GOOS: linux
GOARCH: amd64
linux-arm64:
GOOS: linux
GOARCH: arm64
---
kind: golang.Generate
spec:
versionPackagePath: internal/version
baseSpecPath: /api
vtProtobufEnabled: true
specs:
- source: api/provider/provider.proto
subdirectory: provider
- source: api/specs/specs.proto
subdirectory: specs
---
kind: service.CodeCov
spec:
enabled: false
---
kind: custom.Step
name: run-integration-test
spec:
sudoInCI: true
makefile:
enabled: true
depends:
- provider
- qemu-up
script:
- >-
@hack/test/integration.sh
ghaction:
enabled: true
sops: true
artifacts:
enabled: true
additional:
- name: talos-logs
always: true
continueOnError: true
paths:
- "~/.talos/clusters/**/*.log"
- "!~/.talos/clusters/**/swtpm.log"
---
kind: common.SOPS
spec:
enabled: true
config: |-
creation_rules:
- age: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k
# order: Andrey, Noel, Artem, Utku, Dmitriy
pgp: >-
15D5721F5F5BAF121495363EFE042E3D4085A811,
CC51116A94490FA6FB3C18EB2401FCAE863A06CA,
4919F560F0D35F80CF382D76E084A2DF1143C14D,
11177A43C6E3752E682AC690DBD13117B0A14E93,
AA5213AF261C1977AF38B03A94B473337258BFD5
3 changes: 3 additions & 0 deletions .license-header.go.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 changes: 9 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-10-14T09:32:55Z by kres 34e72ac.

{
"MD013": false,
"MD033": false,
"default": true
}
82 changes: 82 additions & 0 deletions .secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
secrets:
AUTH0_TEST_USERNAME: ENC[AES256_GCM,data:lPddHbDVfWxaEW7ujLDnWdhIBMFj2hcp,iv:oG3Ebn8ym7g/Z7L3A3BTHRHIk+zzblZKvzMKYMPSfWI=,tag:wV7xJWbnLrj/UWj0fGGQCw==,type:str]
AUTH0_TEST_PASSWORD: ENC[AES256_GCM,data:3tgQjqv5ktdnnGUQw5Lpuw==,iv:F8zYxqk5P0tV1Pvt6QBlho8H0wuX+K91pgwLzF+4kC8=,tag:HJ4s14d/u2KyP780wFDk/w==,type:str]
AUTH0_CLIENT_ID: ENC[AES256_GCM,data:HevA8uFKCOPF8W/FRjSo/pyUFN66eXwvAxaqT5LdnT0=,iv:qpWNjsRSZ28lWQJGfMoGQvLY8KRKWv1dhR07vCgIvIU=,tag:x5BS26iacdBMv2ZkdCdr3A==,type:str]
AUTH0_DOMAIN: ENC[AES256_GCM,data:2vv9ay+hC1kN46MG8E0v1Z3G7Dm0hMmLx1/AWg==,iv:9thZflFQ1yhf0jH3u6Om7RV7Y/qYzrTf82hoYrDvyG0=,tag:BUNuHJobt/NoR5FFQBIbIQ==,type:str]
sops:
kms: []
gcp_kms: []
azure_kv: []
hc_vault: []
age:
- recipient: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k
enc: |
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRRC9PWFJkK2FJa3N0UHlv
WkJGQVZCVUl4NEhqRDdiUm03TC9NQTVmWm5vCmNFZGdCUE1OMzZiNnpoSnR0UVYx
UVF2Rzg4VEdSdGNZdUNXd2V5UGdrOTAKLS0tIEQvNjVjUlRPZFBuK2M4dS9KYTFR
a3QwZCtyZ0NBQXo4cmFRazVwWlZEWFkKIHUHaImxN+SgMVSd6pgMQyiAy+mTQAaQ
mGIKj1vrDXs1FLAl5lkV7IxFkf51qqTk6rOxjv1zCzFYLATAr3t4eg==
-----END AGE ENCRYPTED FILE-----
lastmodified: "2024-05-06T09:52:57Z"
mac: ENC[AES256_GCM,data:4qmhG/liKJdnEBxvvnxnpb9xJpS8GGjCAHGUVM4dGtYY5+TkfgnSQyvVdg88Ag16nMDTBEeRJO6VfOYD/Wx/PfIYnajhxRm3ZYuPPSJ5t0LGqRryUtR9vJTtHuTew5gjX8FCTvjiGJzqcfTiq11HhN3Xyu7VNwwan50QUvz5oKY=,iv:Rc0/1kH74ahBkNygwFrOZymWMnPj3VCQZ7wBi1d7Rzc=,tag:Cgdjhlc24S2gklSKYe5mPw==,type:str]
pgp:
- created_at: "2024-11-27T13:27:48Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4D/dYBJRlWfQISAQdAWb3gbi9Rm9Ery5O4vjcms/Inx26KJ8SODWRZ1t/k7nkw
I+u059duWr0e7O2ykSzDnGQA6Aj+HdhPoPcdnNlBWpy3raPwKzJ+X8kVIYp3qiba
0lwB4HMtkNBpz91ErblPNWiVVVe3+G8LLJpDTpaVuPNsj1d3OgnKnWnVFK0b8FAL
kQSmurQgKKbWZ7R6uhfWLINBR4ICZg51FViURfpWoUtlGvrL+nnbvmy9hQVGMQ==
=7teE
-----END PGP MESSAGE-----
fp: 15D5721F5F5BAF121495363EFE042E3D4085A811
- created_at: "2024-11-27T13:27:48Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4D+EORkHurkvgSAQdAkbVUYD2I5MOoPjRjTRI6EfMlA8oEGsMu+ovxmEyMLwkw
egHUl/oDTgovO+12mC/iRAhaKzV5fvCeZUTDbPB7BT+a2HsGyQEE2O4JYrSY/EMJ
0lwBe8TdlHF9HUqwzHbRTo8UDbap0gpJ/KngXJ51m90Az6u4+lmpPgcgWSyJAnBF
u/rjpjqobTmwR8Ea7NZpF3ZcoltlJLyd6w0O7JD5hd8nVWEhbN2KDHwKAnbneQ==
=aBI7
-----END PGP MESSAGE-----
fp: CC51116A94490FA6FB3C18EB2401FCAE863A06CA
- created_at: "2024-11-27T13:27:48Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DCsA/BhMt3V4SAQdAasIYIdDD+bb/JHfxT0yCMbxOu0JFB95rVSMTzLLw+BAw
K8XVL7U+2EbmjO2OkTEbI80SEu//L/c/ZjmvTU8dt18WWMWb/FDWYGrw40KBMbts
0lwBUk4UzZ38uDmnNPka1k6vBPWxvfIOHylbZYFoC4oLXEkghj70cPji6ZBUxpe1
d6Avs0cXx5PLbM2lL/Rh/+9dAhSkl+Uzc5kEXfYPW0IBNlHaH1By+wsoVTgsGQ==
=+zAf
-----END PGP MESSAGE-----
fp: 4919F560F0D35F80CF382D76E084A2DF1143C14D
- created_at: "2024-11-27T13:27:48Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DRbry8yWl6IgSAQdAJoHdZndKL5N3KuO+gNofIpZYKhihf0L5MP+tG5LPKD0w
Hhm5QOMjYNT7LjOTKtRb59ymKSP0oLiQMNvphw4q0IYsFz+l4UkanT6IO6K5tdvQ
1GYBCQIQrIdQeujzcbTI2z9Iwh8RnBxdEhhBYSZMyrzBS7B2V5p0qpjaFojbI3oa
A4uaNEpxnk59mfCuZeKHNURVHn0VT/jZdzalC7aQMk1h/7w6cjZLjJ/Skn5t1Obp
mQKG7tBZzLo=
=PH0s
-----END PGP MESSAGE-----
fp: 11177A43C6E3752E682AC690DBD13117B0A14E93
- created_at: "2024-11-27T13:27:48Z"
enc: |-
-----BEGIN PGP MESSAGE-----
hF4DzfZC0UNQ1VgSAQdAZ0yc24RcLD0R7Bs4UPQTAfbp5Y/DtanIv7kOSjVtlAEw
+F1qLNuwR0r1K9HLndgu0G5vi3L3ra8drb6YMKR7kXyN9RLXjDBt8gD3s386VGMa
1GYBCQIQx6GailOK4BBn2H8HQqDTEgrsLj0ZhG6jOCwKpdPD3VoC4OWDJ0yzt72Z
fwP3VgEH1IB+QF+XBJgdJsh54d79UDutBLxIYJAInQ3foxD3DOQ96D0onysA/qqh
ZV7CB+9hCYc=
=36ga
-----END PGP MESSAGE-----
fp: AA5213AF261C1977AF38B03A94B473337258BFD5
unencrypted_suffix: _unencrypted
version: 3.8.1
13 changes: 13 additions & 0 deletions .sops.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-28T09:26:49Z by kres 232fe63.

creation_rules:
- age: age1xrpa9ujxxcj2u2gzfrzv8mxak4rts94a6y60ypurv6rs5cpr4e4sg95f0k
# order: Andrey, Noel, Artem, Utku, Dmitriy
pgp: >-
15D5721F5F5BAF121495363EFE042E3D4085A811,
CC51116A94490FA6FB3C18EB2401FCAE863A06CA,
4919F560F0D35F80CF382D76E084A2DF1143C14D,
11177A43C6E3752E682AC690DBD13117B0A14E93,
AA5213AF261C1977AF38B03A94B473337258BFD5
241 changes: 241 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
# syntax = docker/dockerfile-upstream:1.11.1-labs

# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-27T11:13:27Z by kres 232fe63.

ARG TOOLCHAIN

FROM ghcr.io/siderolabs/talosctl:v1.9.0-alpha.3 AS base-image-qemu-up

FROM ghcr.io/siderolabs/ca-certificates:v1.8.0 AS image-ca-certificates

FROM ghcr.io/siderolabs/fhs:v1.8.0 AS image-fhs

FROM --platform=linux/amd64 ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4 AS ipxe-linux-amd64

FROM --platform=linux/arm64 ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4 AS ipxe-linux-arm64

# runs markdownlint
FROM docker.io/oven/bun:1.1.36-alpine AS lint-markdown
WORKDIR /src
RUN bun i markdownlint-cli@0.43.0 sentences-per-line@0.2.1
COPY .markdownlint.json .
COPY ./README.md ./README.md
RUN bunx markdownlint --ignore "CHANGELOG.md" --ignore "**/node_modules/**" --ignore '**/hack/chglog/**' --rules node_modules/sentences-per-line/index.js .

# collects proto specs
FROM scratch AS proto-specs
ADD api/provider/provider.proto /api/provider/
ADD api/specs/specs.proto /api/specs/

# base toolchain image
FROM --platform=${BUILDPLATFORM} ${TOOLCHAIN} AS toolchain
RUN apk --update --no-cache add bash curl build-base protoc protobuf-dev

# build tools
FROM --platform=${BUILDPLATFORM} toolchain AS tools
ENV GO111MODULE=on
ARG CGO_ENABLED
ENV CGO_ENABLED=${CGO_ENABLED}
ARG GOTOOLCHAIN
ENV GOTOOLCHAIN=${GOTOOLCHAIN}
ARG GOEXPERIMENT
ENV GOEXPERIMENT=${GOEXPERIMENT}
ENV GOPATH=/go
ARG GOIMPORTS_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/tools/cmd/goimports@v${GOIMPORTS_VERSION}
RUN mv /go/bin/goimports /bin
ARG PROTOBUF_GO_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install google.golang.org/protobuf/cmd/protoc-gen-go@v${PROTOBUF_GO_VERSION}
RUN mv /go/bin/protoc-gen-go /bin
ARG GRPC_GO_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v${GRPC_GO_VERSION}
RUN mv /go/bin/protoc-gen-go-grpc /bin
ARG GRPC_GATEWAY_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-grpc-gateway@v${GRPC_GATEWAY_VERSION}
RUN mv /go/bin/protoc-gen-grpc-gateway /bin
ARG VTPROTOBUF_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/planetscale/vtprotobuf/cmd/protoc-gen-go-vtproto@v${VTPROTOBUF_VERSION}
RUN mv /go/bin/protoc-gen-go-vtproto /bin
ARG DEEPCOPY_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/siderolabs/deep-copy@${DEEPCOPY_VERSION} \
&& mv /go/bin/deep-copy /bin/deep-copy
ARG GOLANGCILINT_VERSION
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCILINT_VERSION} \
&& mv /go/bin/golangci-lint /bin/golangci-lint
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg go install golang.org/x/vuln/cmd/govulncheck@latest \
&& mv /go/bin/govulncheck /bin/govulncheck
ARG GOFUMPT_VERSION
RUN go install mvdan.cc/gofumpt@${GOFUMPT_VERSION} \
&& mv /go/bin/gofumpt /bin/gofumpt

# tools and sources
FROM tools AS base
WORKDIR /src
COPY go.mod go.mod
COPY go.sum go.sum
RUN cd .
RUN --mount=type=cache,target=/go/pkg go mod download
RUN --mount=type=cache,target=/go/pkg go mod verify
COPY ./api ./api
COPY ./cmd ./cmd
COPY ./internal ./internal
RUN --mount=type=cache,target=/go/pkg go list -mod=readonly all >/dev/null

FROM tools AS embed-generate
ARG SHA
ARG TAG
WORKDIR /src
RUN mkdir -p internal/version/data && \
echo -n ${SHA} > internal/version/data/sha && \
echo -n ${TAG} > internal/version/data/tag

# runs protobuf compiler
FROM tools AS proto-compile
COPY --from=proto-specs / /
RUN protoc -I/api --go_out=paths=source_relative:/api --go-grpc_out=paths=source_relative:/api --go-vtproto_out=paths=source_relative:/api --go-vtproto_opt=features=marshal+unmarshal+size+equal+clone /api/provider/provider.proto /api/specs/specs.proto
RUN rm /api/provider/provider.proto
RUN rm /api/specs/specs.proto
RUN goimports -w -local github.com/siderolabs/omni-infra-provider-bare-metal /api
RUN gofumpt -w /api

# runs gofumpt
FROM base AS lint-gofumpt
RUN FILES="$(gofumpt -l .)" && test -z "${FILES}" || (echo -e "Source code is not formatted with 'gofumpt -w .':\n${FILES}"; exit 1)

# runs golangci-lint
FROM base AS lint-golangci-lint
WORKDIR /src
COPY .golangci.yml .
ENV GOGC=50
RUN golangci-lint config verify --config .golangci.yml
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/root/.cache/golangci-lint --mount=type=cache,target=/go/pkg golangci-lint run --config .golangci.yml

# runs govulncheck
FROM base AS lint-govulncheck
WORKDIR /src
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg govulncheck ./...

# runs unit-tests with race detector
FROM base AS unit-tests-race
WORKDIR /src
ARG TESTPKGS
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg --mount=type=cache,target=/tmp CGO_ENABLED=1 go test -v -race -count 1 ${TESTPKGS}

# runs unit-tests
FROM base AS unit-tests-run
WORKDIR /src
ARG TESTPKGS
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg --mount=type=cache,target=/tmp go test -v -covermode=atomic -coverprofile=coverage.txt -coverpkg=${TESTPKGS} -count 1 ${TESTPKGS}

FROM embed-generate AS embed-abbrev-generate
WORKDIR /src
ARG ABBREV_TAG
RUN echo -n 'undefined' > internal/version/data/sha && \
echo -n ${ABBREV_TAG} > internal/version/data/tag

FROM scratch AS unit-tests
COPY --from=unit-tests-run /src/coverage.txt /coverage-unit-tests.txt

# cleaned up specs and compiled versions
FROM scratch AS generate
COPY --from=proto-compile /api/ /api/
COPY --from=embed-abbrev-generate /src/internal/version internal/version

# builds provider-linux-amd64
FROM base AS provider-linux-amd64-build
COPY --from=generate / /
COPY --from=embed-generate / /
WORKDIR /src/cmd/provider
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
ARG VERSION_PKG="internal/version"
ARG SHA
ARG TAG
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg GOARCH=amd64 GOOS=linux go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X ${VERSION_PKG}.Name=provider -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /provider-linux-amd64

# builds provider-linux-arm64
FROM base AS provider-linux-arm64-build
COPY --from=generate / /
COPY --from=embed-generate / /
WORKDIR /src/cmd/provider
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
ARG VERSION_PKG="internal/version"
ARG SHA
ARG TAG
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg GOARCH=arm64 GOOS=linux go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X ${VERSION_PKG}.Name=provider -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /provider-linux-arm64

# builds qemu-up-linux-amd64
FROM base AS qemu-up-linux-amd64-build
COPY --from=generate / /
COPY --from=embed-generate / /
WORKDIR /src/cmd/qemu-up
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
ARG VERSION_PKG="internal/version"
ARG SHA
ARG TAG
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg GOARCH=amd64 GOOS=linux go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X ${VERSION_PKG}.Name=qemu-up -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /qemu-up-linux-amd64

# builds qemu-up-linux-arm64
FROM base AS qemu-up-linux-arm64-build
COPY --from=generate / /
COPY --from=embed-generate / /
WORKDIR /src/cmd/qemu-up
ARG GO_BUILDFLAGS
ARG GO_LDFLAGS
ARG VERSION_PKG="internal/version"
ARG SHA
ARG TAG
RUN --mount=type=cache,target=/root/.cache/go-build --mount=type=cache,target=/go/pkg GOARCH=arm64 GOOS=linux go build ${GO_BUILDFLAGS} -ldflags "${GO_LDFLAGS} -X ${VERSION_PKG}.Name=qemu-up -X ${VERSION_PKG}.SHA=${SHA} -X ${VERSION_PKG}.Tag=${TAG}" -o /qemu-up-linux-arm64

FROM scratch AS provider-linux-amd64
COPY --from=provider-linux-amd64-build /provider-linux-amd64 /provider-linux-amd64

FROM scratch AS provider-linux-arm64
COPY --from=provider-linux-arm64-build /provider-linux-arm64 /provider-linux-arm64

FROM scratch AS qemu-up-linux-amd64
COPY --from=qemu-up-linux-amd64-build /qemu-up-linux-amd64 /qemu-up-linux-amd64

FROM scratch AS qemu-up-linux-arm64
COPY --from=qemu-up-linux-arm64-build /qemu-up-linux-arm64 /qemu-up-linux-arm64

FROM provider-linux-${TARGETARCH} AS provider

FROM scratch AS provider-all
COPY --from=provider-linux-amd64 / /
COPY --from=provider-linux-arm64 / /

FROM qemu-up-linux-${TARGETARCH} AS qemu-up

FROM scratch AS qemu-up-all
COPY --from=qemu-up-linux-amd64 / /
COPY --from=qemu-up-linux-arm64 / /

FROM scratch AS image-provider
ARG TARGETARCH
COPY --from=provider provider-linux-${TARGETARCH} /provider
COPY --from=image-fhs / /
COPY --from=image-ca-certificates / /
COPY --from=ghcr.io/siderolabs/musl:v1.8.0-16-g71d23b4 / /
COPY --from=ghcr.io/siderolabs/liblzma:v1.8.0-16-g71d23b4 / /
COPY --from=ghcr.io/siderolabs/openssl:v1.8.0-16-g71d23b4 / /
COPY --from=ghcr.io/siderolabs/ipmitool:v1.8.0-16-g71d23b4 / /
COPY --from=ghcr.io/siderolabs/ipxe:v1.8.0-16-g71d23b4 /usr/libexec/zbin /bin/zbin
COPY --from=ipxe-linux-amd64 /usr/libexec/ /var/lib/ipxe/amd64
COPY --from=ipxe-linux-arm64 /usr/libexec/ /var/lib/ipxe/arm64
COPY --from=ghcr.io/siderolabs/talos-metal-agent-boot-assets:v1.9.0-alpha.3-agent-v0.1.0-alpha.2 / /assets
LABEL org.opencontainers.image.source=https://github.com/siderolabs/omni-infra-provider-bare-metal
ENTRYPOINT ["/provider"]

FROM base-image-qemu-up AS image-qemu-up
ARG TARGETARCH
COPY --from=qemu-up qemu-up-linux-${TARGETARCH} /qemu-up
COPY --from=image-fhs / /
COPY --from=image-ca-certificates / /
LABEL org.opencontainers.image.source=https://github.com/siderolabs/omni-infra-provider-bare-metal
ENTRYPOINT ["/qemu-up"]

373 changes: 373 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

262 changes: 262 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-11-28T09:31:42Z by kres 232fe63.

# common variables

SHA := $(shell git describe --match=none --always --abbrev=8 --dirty)
TAG := $(shell git describe --tag --always --dirty --match v[0-9]\*)
ABBREV_TAG := $(shell git describe --tags >/dev/null 2>/dev/null && git describe --tag --always --match v[0-9]\* --abbrev=0 || echo 'undefined')
BRANCH := $(shell git rev-parse --abbrev-ref HEAD)
ARTIFACTS := _out
IMAGE_TAG ?= $(TAG)
OPERATING_SYSTEM := $(shell uname -s | tr '[:upper:]' '[:lower:]')
GOARCH := $(shell uname -m | sed 's/x86_64/amd64/' | sed 's/aarch64/arm64/')
WITH_DEBUG ?= false
WITH_RACE ?= false
REGISTRY ?= ghcr.io
USERNAME ?= siderolabs
REGISTRY_AND_USERNAME ?= $(REGISTRY)/$(USERNAME)
PROTOBUF_GO_VERSION ?= 1.35.2
GRPC_GO_VERSION ?= 1.5.1
GRPC_GATEWAY_VERSION ?= 2.24.0
VTPROTOBUF_VERSION ?= 0.6.0
GOIMPORTS_VERSION ?= 0.27.0
DEEPCOPY_VERSION ?= v0.5.6
GOLANGCILINT_VERSION ?= v1.62.0
GOFUMPT_VERSION ?= v0.7.0
GO_VERSION ?= 1.23.3
GO_BUILDFLAGS ?=
GO_LDFLAGS ?=
CGO_ENABLED ?= 0
GOTOOLCHAIN ?= local
TESTPKGS ?= ./...
KRES_IMAGE ?= ghcr.io/siderolabs/kres:latest
CONFORMANCE_IMAGE ?= ghcr.io/siderolabs/conform:latest

# docker build settings

BUILD := docker buildx build
PLATFORM ?= linux/amd64
PROGRESS ?= auto
PUSH ?= false
CI_ARGS ?=
BUILDKIT_MULTI_PLATFORM ?= 1
COMMON_ARGS = --file=Dockerfile
COMMON_ARGS += --provenance=false
COMMON_ARGS += --progress=$(PROGRESS)
COMMON_ARGS += --platform=$(PLATFORM)
COMMON_ARGS += --push=$(PUSH)
COMMON_ARGS += --build-arg=BUILDKIT_MULTI_PLATFORM=$(BUILDKIT_MULTI_PLATFORM)
COMMON_ARGS += --build-arg=ARTIFACTS="$(ARTIFACTS)"
COMMON_ARGS += --build-arg=SHA="$(SHA)"
COMMON_ARGS += --build-arg=TAG="$(TAG)"
COMMON_ARGS += --build-arg=ABBREV_TAG="$(ABBREV_TAG)"
COMMON_ARGS += --build-arg=USERNAME="$(USERNAME)"
COMMON_ARGS += --build-arg=REGISTRY="$(REGISTRY)"
COMMON_ARGS += --build-arg=TOOLCHAIN="$(TOOLCHAIN)"
COMMON_ARGS += --build-arg=CGO_ENABLED="$(CGO_ENABLED)"
COMMON_ARGS += --build-arg=GO_BUILDFLAGS="$(GO_BUILDFLAGS)"
COMMON_ARGS += --build-arg=GO_LDFLAGS="$(GO_LDFLAGS)"
COMMON_ARGS += --build-arg=GOTOOLCHAIN="$(GOTOOLCHAIN)"
COMMON_ARGS += --build-arg=GOEXPERIMENT="$(GOEXPERIMENT)"
COMMON_ARGS += --build-arg=PROTOBUF_GO_VERSION="$(PROTOBUF_GO_VERSION)"
COMMON_ARGS += --build-arg=GRPC_GO_VERSION="$(GRPC_GO_VERSION)"
COMMON_ARGS += --build-arg=GRPC_GATEWAY_VERSION="$(GRPC_GATEWAY_VERSION)"
COMMON_ARGS += --build-arg=VTPROTOBUF_VERSION="$(VTPROTOBUF_VERSION)"
COMMON_ARGS += --build-arg=GOIMPORTS_VERSION="$(GOIMPORTS_VERSION)"
COMMON_ARGS += --build-arg=DEEPCOPY_VERSION="$(DEEPCOPY_VERSION)"
COMMON_ARGS += --build-arg=GOLANGCILINT_VERSION="$(GOLANGCILINT_VERSION)"
COMMON_ARGS += --build-arg=GOFUMPT_VERSION="$(GOFUMPT_VERSION)"
COMMON_ARGS += --build-arg=TESTPKGS="$(TESTPKGS)"
TOOLCHAIN ?= docker.io/golang:1.23-alpine

# help menu

export define HELP_MENU_HEADER
# Getting Started

To build this project, you must have the following installed:

- git
- make
- docker (19.03 or higher)

## Creating a Builder Instance

The build process makes use of experimental Docker features (buildx).
To enable experimental features, add 'experimental: "true"' to '/etc/docker/daemon.json' on
Linux or enable experimental features in Docker GUI for Windows or Mac.

To create a builder instance, run:

docker buildx create --name local --use

If running builds that needs to be cached aggresively create a builder instance with the following:

docker buildx create --name local --use --config=config.toml

config.toml contents:

[worker.oci]
gc = true
gckeepstorage = 50000

[[worker.oci.gcpolicy]]
keepBytes = 10737418240
keepDuration = 604800
filters = [ "type==source.local", "type==exec.cachemount", "type==source.git.checkout"]
[[worker.oci.gcpolicy]]
all = true
keepBytes = 53687091200

If you already have a compatible builder instance, you may use that instead.

## Artifacts

All artifacts will be output to ./$(ARTIFACTS). Images will be tagged with the
registry "$(REGISTRY)", username "$(USERNAME)", and a dynamic tag (e.g. $(IMAGE):$(IMAGE_TAG)).
The registry and username can be overridden by exporting REGISTRY, and USERNAME
respectively.

endef

ifneq (, $(filter $(WITH_RACE), t true TRUE y yes 1))
GO_BUILDFLAGS += -race
CGO_ENABLED := 1
GO_LDFLAGS += -linkmode=external -extldflags '-static'
endif

ifneq (, $(filter $(WITH_DEBUG), t true TRUE y yes 1))
GO_BUILDFLAGS += -tags sidero.debug
else
GO_LDFLAGS += -s
endif

all: unit-tests provider image-provider qemu-up image-qemu-up ipxe run-integration-test lint

$(ARTIFACTS): ## Creates artifacts directory.
@mkdir -p $(ARTIFACTS)

.PHONY: clean
clean: ## Cleans up all artifacts.
@rm -rf $(ARTIFACTS)

target-%: ## Builds the specified target defined in the Dockerfile. The build result will only remain in the build cache.
@$(BUILD) --target=$* $(COMMON_ARGS) $(TARGET_ARGS) $(CI_ARGS) .

local-%: ## Builds the specified target defined in the Dockerfile using the local output type. The build result will be output to the specified local destination.
@$(MAKE) target-$* TARGET_ARGS="--output=type=local,dest=$(DEST) $(TARGET_ARGS)"
@PLATFORM=$(PLATFORM) DEST=$(DEST) bash -c '\
for platform in $$(tr "," "\n" <<< "$$PLATFORM"); do \
echo $$platform; \
directory="$${platform//\//_}"; \
if [[ -d "$$DEST/$$directory" ]]; then \
mv "$$DEST/$$directory/"* $$DEST; \
rmdir "$$DEST/$$directory/"; \
fi; \
done'

generate: ## Generate .proto definitions.
@$(MAKE) local-$@ DEST=./ BUILDKIT_MULTI_PLATFORM=0

lint-golangci-lint: ## Runs golangci-lint linter.
@$(MAKE) target-$@

lint-gofumpt: ## Runs gofumpt linter.
@$(MAKE) target-$@

.PHONY: fmt
fmt: ## Formats the source code
@docker run --rm -it -v $(PWD):/src -w /src golang:$(GO_VERSION) \
bash -c "export GOTOOLCHAIN=local; \
export GO111MODULE=on; export GOPROXY=https://proxy.golang.org; \
go install mvdan.cc/gofumpt@$(GOFUMPT_VERSION) && \
gofumpt -w ."

lint-govulncheck: ## Runs govulncheck linter.
@$(MAKE) target-$@

.PHONY: base
base: ## Prepare base toolchain
@$(MAKE) target-$@

.PHONY: unit-tests
unit-tests: ## Performs unit tests
@$(MAKE) local-$@ DEST=$(ARTIFACTS)

.PHONY: unit-tests-race
unit-tests-race: ## Performs unit tests with race detection enabled.
@$(MAKE) target-$@

.PHONY: $(ARTIFACTS)/provider-linux-amd64
$(ARTIFACTS)/provider-linux-amd64:
@$(MAKE) local-provider-linux-amd64 DEST=$(ARTIFACTS)

.PHONY: provider-linux-amd64
provider-linux-amd64: $(ARTIFACTS)/provider-linux-amd64 ## Builds executable for provider-linux-amd64.

.PHONY: $(ARTIFACTS)/provider-linux-arm64
$(ARTIFACTS)/provider-linux-arm64:
@$(MAKE) local-provider-linux-arm64 DEST=$(ARTIFACTS)

.PHONY: provider-linux-arm64
provider-linux-arm64: $(ARTIFACTS)/provider-linux-arm64 ## Builds executable for provider-linux-arm64.

.PHONY: provider
provider: provider-linux-amd64 provider-linux-arm64 ## Builds executables for provider.

.PHONY: lint-markdown
lint-markdown: ## Runs markdownlint.
@$(MAKE) target-$@

.PHONY: lint
lint: lint-golangci-lint lint-gofumpt lint-govulncheck lint-markdown ## Run all linters for the project.

.PHONY: image-provider
image-provider: ## Builds image for provider.
@$(MAKE) target-$@ TARGET_ARGS="--tag=$(REGISTRY)/$(USERNAME)/provider:$(IMAGE_TAG)"

.PHONY: $(ARTIFACTS)/qemu-up-linux-amd64
$(ARTIFACTS)/qemu-up-linux-amd64:
@$(MAKE) local-qemu-up-linux-amd64 DEST=$(ARTIFACTS)

.PHONY: qemu-up-linux-amd64
qemu-up-linux-amd64: $(ARTIFACTS)/qemu-up-linux-amd64 ## Builds executable for qemu-up-linux-amd64.

.PHONY: $(ARTIFACTS)/qemu-up-linux-arm64
$(ARTIFACTS)/qemu-up-linux-arm64:
@$(MAKE) local-qemu-up-linux-arm64 DEST=$(ARTIFACTS)

.PHONY: qemu-up-linux-arm64
qemu-up-linux-arm64: $(ARTIFACTS)/qemu-up-linux-arm64 ## Builds executable for qemu-up-linux-arm64.

.PHONY: qemu-up
qemu-up: qemu-up-linux-amd64 qemu-up-linux-arm64 ## Builds executables for qemu-up.

.PHONY: image-qemu-up
image-qemu-up: ## Builds image for qemu-up.
@$(MAKE) target-$@ TARGET_ARGS="--tag=$(REGISTRY)/$(USERNAME)/qemu-up:$(IMAGE_TAG)"

run-integration-test: provider qemu-up
@hack/test/integration.sh

.PHONY: rekres
rekres:
@docker pull $(KRES_IMAGE)
@docker run --rm --net=host --user $(shell id -u):$(shell id -g) -v $(PWD):/src -w /src -e GITHUB_TOKEN $(KRES_IMAGE)

.PHONY: help
help: ## This help menu.
@echo "$$HELP_MENU_HEADER"
@grep -E '^[a-zA-Z%_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

.PHONY: release-notes
release-notes: $(ARTIFACTS)
@ARTIFACTS=$(ARTIFACTS) ./hack/release.sh $@ $(ARTIFACTS)/RELEASE_NOTES.md $(TAG)

.PHONY: conformance
conformance:
@docker pull $(CONFORMANCE_IMAGE)
@docker run --rm -it -v $(PWD):/src -w /src $(CONFORMANCE_IMAGE) enforce

105 changes: 105 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,106 @@
# omni-infra-provider-bare-metal

This repo contains the code for the Omni Bare Metal Infra Provider.

## Requirements

To run the provider, you need:

- A running Omni instance
- An Omni infra provider service account matching the ID you'll use with this provider (`bare-metal` by default).
To create it, run:

```bash
omnictl serviceaccount create --use-user-role=false --role=InfraProvider infra-provider:bare-metal
```

Replace `bare-metal` with your desired provider ID.
- A DHCP server: This provider runs a DHCP proxy to provide DHCP responses for iPXE boot, so a DHCP server must be running in the same network as the provider.
- Access to an [Image Factory](https://www.talos.dev/v1.8/learn-more/image-factory/).

## Development

For local development using Talos running on QEMU, follow these steps:

1. Set up a `buildx` builder instance with host network access, if you don't have one already:

```bash
docker buildx create --driver docker-container --driver-opt network=host --name local1 --buildkitd-flags '--allow-insecure-entitlement security.insecure' --use
```

2. Start a local image registry if you don't have one running:

```bash
docker run -d -p 5005:5000 --restart always --name local registry:2
```

3. Start Talos nodes on QEMU, set to PXE boot:

```bash
talosctl cluster create \
--provisioner=qemu \
--cidr=172.20.0.0/24 \
--controlplanes=3 \
--workers=0 \
--disable-dhcp-hostname=true \
--with-bootloader=true \
--with-apply-config=false \
--skip-injecting-config=true \
--wait=false \
--with-init-node=true \
--default-boot-order=nc \
--pxe-booted \
--memory=8192 \
--cpus=6 \
--with-uefi=false \
--with-uuid-hostnames
```

4. (Optional) If you have made local changes to the [Talos Metal agent](https://github.com/siderolabs/talos-metal-agent), follow these steps to use your local version:
1. Build and push Talos Metal Agent boot assets image following [these instructions](https://github.com/siderolabs/talos-metal-agent/blob/main/README.md).
2. Replace the `ghcr.io/siderolabs/talos-metal-agent-boot-assets` image reference in [.kres.yaml](.kres.yaml) with your built image,
e.g., `127.0.0.1:5005/siderolabs/talos-metal-agent-boot-assets:v1.9.0-alpha.2-agent-v0.1.0-alpha.0-1-gbf1282b-dirty`.
3. Re-kres the project to propagate this change into `Dockerfile`:

```bash
make rekres
```

5. Build a local provider image:

```bash
make image-provider PLATFORM=linux/amd64 REGISTRY=127.0.0.1:5005 PUSH=true TAG=local-dev
docker pull 127.0.0.1:5005/siderolabs/provider:local-dev
```

6. Start the provider with your Omni API address and service account credentials:

```bash
export OMNI_ENDPOINT=<your-omni-api-address>
export OMNI_SERVICE_ACCOUNT_KEY=<your-omni-service-account-key>
docker run --name=omni-bare-metal-provider --network host --rm -it \
-v "$HOME/.talos/clusters/talos-default:/api-power-mgmt-state:ro" \
-e OMNI_ENDPOINT -e OMNI_SERVICE_ACCOUNT_KEY \
127.0.0.1:5005/siderolabs/provider:local-dev \
--insecure-skip-tls-verify \
--api-advertise-address=<provider-ip-to-advertise> \
--use-local-boot-assets \
--agent-test-mode \
--api-power-mgmt-state-dir=/api-power-mgmt-state \
--dhcp-proxy-iface-or-ip=172.20.0.1 \
--debug
```

Important flags:
- `--use-local-boot-assets`: Makes the provider serve the boot assets image embedded in the provider image.
This is useful for testing local Talos Metal Agent boot assets.
Omit this flag to use the upstream agent version, which will forward agent mode PXE boot requests to the image factory.
- `--agent-test-mode`: Boots the agent in test mode when booting a Talos node in agent mode, enabling API-based power management instead of IPMI/RedFish.
This is necessary for QEMU development,
as it uses the power management API run by the `talosctl cluster create` command.
- The volume mount `-v "$HOME/.talos/clusters/talos-default:/api-power-mgmt-state:ro"`
mounts the directory containing API-based power management state information generated by `talosctl cluster create`.
- `--api-power-mgmt-state-dir`: Specifies where to read the API power management address of the nodes.
- `--dhcp-proxy-iface-or-ip`: Specifies the IP address or interface name for running the DHCP proxy
(e.g., the IP address of the QEMU bridge interface).
188 changes: 188 additions & 0 deletions api/provider/provider.pb.go
19 changes: 19 additions & 0 deletions api/provider/provider.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";

package baremetalprovider;

option go_package = "github.com/siderolabs/talos-metal-agent/internal/providerpb";

import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

message RebootMachineRequest {
string id = 1;
}

message RebootMachineResponse {}

service ProviderService {
rpc RebootMachine(RebootMachineRequest) returns (RebootMachineResponse);
}
122 changes: 122 additions & 0 deletions api/provider/provider_grpc.pb.go
321 changes: 321 additions & 0 deletions api/provider/provider_vtproto.pb.go
485 changes: 485 additions & 0 deletions api/specs/specs.pb.go

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions api/specs/specs.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
syntax = "proto3";

package baremetalproviderspecs;

option go_package = "github.com/siderolabs/omni-infra-provider-bare-metal/api/specs";

message PowerManagement {
message IPMI {
string address = 1;
uint32 port = 2;
string username = 3;
string password = 4;
}

message API {
string address = 1;
}

IPMI ipmi = 1;
API api = 2;
}

enum BootMode {
BOOT_MODE_UNKNOWN = 0;
BOOT_MODE_AGENT_PXE = 1;
BOOT_MODE_TALOS_PXE = 2;
BOOT_MODE_TALOS_DISK = 3;
}

enum PowerState {
POWER_STATE_UNKNOWN = 0;
POWER_STATE_OFF = 1;
POWER_STATE_ON = 2;
}

message MachineStatusSpec {
PowerManagement power_management = 1;

PowerState power_state = 2;

// LastBootMode is the last observed boot mode of the machine. It is updated by the PXE server each time it boots a server,
// and is also updated by the status of the agent connectivity.
BootMode boot_mode = 3;

// LastWipeId is the ID of the last wipe operation that was performed on the machine.
//
// It is used to track if the machine needs to be wiped for an allocation.
string last_wipe_id = 4;
}
1,016 changes: 1,016 additions & 0 deletions api/specs/specs_vtproto.pb.go

Large diffs are not rendered by default.

141 changes: 141 additions & 0 deletions cmd/provider/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package main implements the main entrypoint for the Omni bare metal infra provider.
package main

import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"

"github.com/siderolabs/talos-metal-agent/pkg/config"
"github.com/spf13/cobra"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"github.com/siderolabs/omni-infra-provider-bare-metal/internal/provider"
"github.com/siderolabs/omni-infra-provider-bare-metal/internal/provider/meta"
"github.com/siderolabs/omni-infra-provider-bare-metal/internal/version"
)

var (
providerOptions provider.Options
debug bool
)

// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{
Use: version.Name,
Short: "Run the Omni bare metal infra provider",
Version: version.Tag,
Args: cobra.NoArgs,
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
cmd.SilenceUsage = true // if the args are parsed fine, no need to show usage
},
RunE: func(cmd *cobra.Command, _ []string) error {
logger, err := initLogger()
if err != nil {
return fmt.Errorf("failed to create logger: %w", err)
}

defer logger.Sync() //nolint:errcheck

return run(cmd.Context(), logger)
},
}

func initLogger() (*zap.Logger, error) {
var loggerConfig zap.Config

if debug {
loggerConfig = zap.NewDevelopmentConfig()
loggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
loggerConfig.Level.SetLevel(zap.DebugLevel)
} else {
loggerConfig = zap.NewProductionConfig()
loggerConfig.Level.SetLevel(zap.InfoLevel)
}

return loggerConfig.Build(zap.AddStacktrace(zapcore.FatalLevel)) // only print stack traces for fatal errors)
}

func run(ctx context.Context, logger *zap.Logger) error {
prov := provider.New(providerOptions, logger)

if err := prov.Run(ctx); err != nil {
return fmt.Errorf("failed to run provider: %w", err)
}

return nil
}

func main() {
if err := runCmd(); err != nil {
log.Fatalf("failed to run: %v", err)
}
}

func runCmd() error {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
defer cancel()

return rootCmd.ExecuteContext(ctx)
}

func init() {
const (
apiPowerMgmtStateDirFlag = "api-power-mgmt-state-dir"
dhcpProxyIfaceOrIPFlag = "dhcp-proxy-iface-or-ip"
)

rootCmd.Flags().StringVar(&meta.ProviderID, "id", meta.ProviderID, "The id of the infra provider, it is used to match the resources with the infra provider label.")
rootCmd.Flags().BoolVar(&debug, "debug", false, "Enable debug mode & logs.")

rootCmd.Flags().StringVar(&providerOptions.APIListenAddress, "api-listen-address", provider.DefaultOptions.APIListenAddress,
"The IP address to listen on. If not specified, the server will listen on all interfaces.")
rootCmd.Flags().StringVar(&providerOptions.APIAdvertiseAddress, "api-advertise-address", provider.DefaultOptions.APIAdvertiseAddress,
"The IP address to advertise. Required if the server has more than a single routable IP address. If not specified, the single routable IP address will be used.")
rootCmd.Flags().IntVar(&providerOptions.APIPort, "api-port", provider.DefaultOptions.APIPort, "The port to run the api server on.")
rootCmd.Flags().StringVar(&providerOptions.OmniAPIEndpoint, "omni-api-endpoint", os.Getenv("OMNI_ENDPOINT"),
"The endpoint of the Omni API, if not set, defaults to OMNI_ENDPOINT env var.")
rootCmd.Flags().StringVar(&providerOptions.Name, "provider-name", provider.DefaultOptions.Name, "Provider name as it appears in Omni")
rootCmd.Flags().StringVar(&providerOptions.Description, "provider-description", provider.DefaultOptions.Description, "Provider description as it appears in Omni")
rootCmd.Flags().BoolVar(&providerOptions.UseLocalBootAssets, "use-local-boot-assets", provider.DefaultOptions.UseLocalBootAssets,
"Use local boot assets for iPXE booting. If set, the iPXE server will use the kernel and initramfs from the local assets "+
"instead of forwarding the request to the image factory to boot into agent mode.")
rootCmd.Flags().StringVar(&providerOptions.DHCPProxyIfaceOrIP, dhcpProxyIfaceOrIPFlag, provider.DefaultOptions.DHCPProxyIfaceOrIP,
"The interface name or the IP address on the interface to run the DHCP proxy server on. "+
"If it is an IP address, the DHCP proxy server will run on the interface that has the IP address.")
rootCmd.Flags().StringVar(&providerOptions.ImageFactoryBaseURL, "image-factory-base-url", provider.DefaultOptions.ImageFactoryBaseURL,
"The base URL of the image factory.")
rootCmd.Flags().StringVar(&providerOptions.ImageFactoryPXEBaseURL, "image-factory-pxe-base-url", provider.DefaultOptions.ImageFactoryPXEBaseURL,
"The base URL of the image factory PXE server.")
rootCmd.Flags().StringVar(&providerOptions.AgentModeTalosVersion, "agent-mode-talos-version", provider.DefaultOptions.AgentModeTalosVersion,
"The default Talos version to when forwarding iPXE requests to the image factory to boot into Talos agent.")
rootCmd.Flags().BoolVar(&providerOptions.AgentTestMode, "agent-test-mode", provider.DefaultOptions.AgentTestMode,
fmt.Sprintf("Enable agent test mode. In this mode, the Talos agent will be booted into the test mode via the kernel arg %q. "+
"In this mode, you probably want to set the --%s flag, as the test mode agents are probably QEMU machines whose power is managed over the HTTP API.",
config.TestModeKernelArg, apiPowerMgmtStateDirFlag))
rootCmd.Flags().StringVar(&providerOptions.APIPowerMgmtStateDir, apiPowerMgmtStateDirFlag, provider.DefaultOptions.APIPowerMgmtStateDir,
"The directory to read the power management API endpoints and ports, to be used to manage the power state of the machines which are managed via API "+
"(e.g., QEMU VMs created by 'talosctl cluster create') Mainly used for testing purposes.")
rootCmd.Flags().StringVar(&providerOptions.BootFromDiskMethod, "boot-from-disk-method", provider.DefaultOptions.BootFromDiskMethod,
"Default method to use to boot server from disk if it hits iPXE endpoint after install.")
rootCmd.Flags().StringSliceVar(&providerOptions.MachineLabels, "machine-labels", provider.DefaultOptions.MachineLabels,
"Comma separated list of key=value pairs to be set to the machine. Example: key1=value1,key2,key3=value3")
rootCmd.Flags().BoolVar(&providerOptions.InsecureSkipTLSVerify, "insecure-skip-tls-verify", provider.DefaultOptions.InsecureSkipTLSVerify,
"Skip TLS verification when connecting to the Omni API.")
rootCmd.Flags().BoolVar(&providerOptions.ClearState, "clear-state", provider.DefaultOptions.ClearState, "Clear the state of the provider on startup.")
rootCmd.Flags().BoolVar(&providerOptions.EnableResourceCache, "enable-resource-cache", provider.DefaultOptions.EnableResourceCache,
"Enable controller runtime resource cache.")
rootCmd.Flags().BoolVar(&providerOptions.WipeWithZeroes, "wipe-with-zeroes", provider.DefaultOptions.WipeWithZeroes,
"When wiping a machine, write zeroes to the whole disk instead doing a fast wipe.")

// mark the flags as required
rootCmd.MarkFlagRequired(dhcpProxyIfaceOrIPFlag) //nolint:errcheck
}
111 changes: 111 additions & 0 deletions cmd/qemu-up/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Package main implements the main entrypoint for the Omni bare metal infra provider.
package main

import (
"context"
"fmt"
"log"
"os"
"os/signal"
"syscall"

"github.com/spf13/cobra"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"

"github.com/siderolabs/omni-infra-provider-bare-metal/internal/qemu"
"github.com/siderolabs/omni-infra-provider-bare-metal/internal/version"
)

var (
qemuOptions qemu.Options
destroy bool
debug bool
)

// rootCmd represents the base command when called without any subcommands.
var rootCmd = &cobra.Command{
Use: version.Name,
Short: "Bring QMU Talos machines up with iPXE boot for development and testing",
Version: version.Tag,
Args: cobra.NoArgs,
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
cmd.SilenceUsage = true // if the args are parsed fine, no need to show usage
},
RunE: func(cmd *cobra.Command, _ []string) error {
logger, err := initLogger()
if err != nil {
return fmt.Errorf("failed to create logger: %w", err)
}

defer logger.Sync() //nolint:errcheck

return run(cmd.Context(), logger)
},
}

func initLogger() (*zap.Logger, error) {
var loggerConfig zap.Config

if debug {
loggerConfig = zap.NewDevelopmentConfig()
loggerConfig.EncoderConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
loggerConfig.Level.SetLevel(zap.DebugLevel)
} else {
loggerConfig = zap.NewProductionConfig()
loggerConfig.Level.SetLevel(zap.InfoLevel)
}

return loggerConfig.Build(zap.AddStacktrace(zapcore.FatalLevel)) // only print stack traces for fatal errors)
}

func run(ctx context.Context, logger *zap.Logger) error {
machines, err := qemu.New(qemuOptions, logger)
if err != nil {
return fmt.Errorf("failed to create QEMU machines: %w", err)
}

if destroy {
if err = machines.Destroy(ctx); err != nil {
return fmt.Errorf("failed to destroy machines: %w", err)
}

return nil
}

return machines.Run(ctx)
}

func main() {
if err := runCmd(); err != nil {
log.Fatalf("failed to run: %v", err)
}
}

func runCmd() error {
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGTERM, os.Interrupt)
defer cancel()

return rootCmd.ExecuteContext(ctx)
}

func init() {
rootCmd.Flags().BoolVar(&debug, "debug", false, "Enable debug mode & logs.")
rootCmd.Flags().BoolVar(&destroy, "destroy", false, "Destroy existing machines and exit.")

rootCmd.Flags().StringVar(&qemuOptions.Name, "name", qemu.DefaultOptions.Name, "Name of the cluster (the set of machines).")
rootCmd.Flags().StringVar(&qemuOptions.CIDR, "cidr", qemu.DefaultOptions.CIDR, "CIDR for the machines' network.")
rootCmd.Flags().StringVar(&qemuOptions.CNIBundleURL, "cni-bundle-url", qemu.DefaultOptions.CNIBundleURL, "URL to the CNI bundle.")
rootCmd.Flags().StringVar(&qemuOptions.TalosctlPath, "talosctl-path", qemu.DefaultOptions.TalosctlPath,
fmt.Sprintf("Path to the talosctl binary. If not specified, the binary %q will be looked up in the current working dir and in the PATH.", qemu.TalosctlBinary))
rootCmd.Flags().StringVar(&qemuOptions.CPUs, "cpus", qemu.DefaultOptions.CPUs, "Number of CPUs for each machine.")
rootCmd.Flags().IntVar(&qemuOptions.NumMachines, "num-machines", qemu.DefaultOptions.NumMachines, "Number of machines to bring up.")
rootCmd.Flags().IntVar(&qemuOptions.MTU, "mtu", qemu.DefaultOptions.MTU, "MTU for the machines' network.")
rootCmd.Flags().Uint64Var(&qemuOptions.DiskSize, "disk-size", qemu.DefaultOptions.DiskSize, "Disk size for each machine.")
rootCmd.Flags().Int64Var(&qemuOptions.MemSize, "mem-size", qemu.DefaultOptions.MemSize, "Memory size for each machine.")
rootCmd.Flags().StringSliceVar(&qemuOptions.Nameservers, "nameservers", qemu.DefaultOptions.Nameservers, "Nameservers for the machines' network.")
}
159 changes: 159 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
module github.com/siderolabs/omni-infra-provider-bare-metal

go 1.23.3

replace (
github.com/pensando/goipmi v0.0.0-20240603174436-eb122d901c23 => github.com/siderolabs/goipmi v0.0.0-20211214143420-35f956689e67
github.com/pin/tftp/v3 v3.1.0 => github.com/utkuozdemir/pin-tftp/v3 v3.0.0-20241021135417-0dd7dba351ad

//github.com/siderolabs/omni/client v0.0.0-20241017162757-284e8b5077cc => github.com/utkuozdemir/sidero-omni/client v0.0.0-20241125223356-d6063fcdb22f
//github.com/siderolabs/talos-metal-agent v0.1.0-alpha.1 => github.com/utkuozdemir/sidero-talos-metal-agent v0.0.0-20241118155617-c07abd7f024c
)

require (
github.com/cosi-project/runtime v0.7.2
github.com/google/uuid v1.6.0
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.1.0
github.com/hashicorp/go-multierror v1.1.1
github.com/insomniacslk/dhcp v0.0.0-20240829085014-a3a4c1f04475
github.com/jhump/grpctunnel v0.3.0
github.com/pensando/goipmi v0.0.0-20240603174436-eb122d901c23
github.com/pin/tftp/v3 v3.1.0
github.com/planetscale/vtprotobuf v0.6.1-0.20240917153116-6f2963f01587
github.com/siderolabs/gen v0.7.0
github.com/siderolabs/image-factory v0.6.1
github.com/siderolabs/net v0.4.0
github.com/siderolabs/omni/client v0.0.0-20241126230020-5a26d4c7ac9d
github.com/siderolabs/talos v1.9.0-alpha.3
github.com/siderolabs/talos-metal-agent v0.1.0-alpha.2
github.com/siderolabs/talos/pkg/machinery v1.9.0-alpha.3
github.com/spf13/cobra v1.8.1
go.uber.org/zap v1.27.0
golang.org/x/net v0.31.0
golang.org/x/sync v0.9.0
google.golang.org/grpc v1.68.0
google.golang.org/protobuf v1.35.2
gopkg.in/yaml.v3 v3.0.1
)

require (
cel.dev/expr v0.18.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/ProtonMail/go-crypto v1.1.3 // indirect
github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f // indirect
github.com/ProtonMail/gopenpgp/v2 v2.8.1 // indirect
github.com/adrg/xdg v0.5.3 // indirect
github.com/alexflint/go-filemutex v1.3.0 // indirect
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
github.com/armon/circbuf v0.0.0-20190214190532-5111143e8da2 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cloudflare/circl v1.5.0 // indirect
github.com/containerd/go-cni v1.1.10 // indirect
github.com/containernetworking/cni v1.2.3 // indirect
github.com/containernetworking/plugins v1.6.0 // indirect
github.com/coreos/go-iptables v0.8.0 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/docker v27.3.1+incompatible // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emicklei/dot v1.6.2 // indirect
github.com/emicklei/go-restful/v3 v3.12.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/florianl/go-tc v0.4.4 // indirect
github.com/fullstorydev/grpchan v1.1.1 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/gertd/go-pluralize v0.2.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.21.0 // indirect
github.com/go-openapi/jsonreference v0.21.0 // indirect
github.com/go-openapi/swag v0.23.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/cel-go v0.22.1 // indirect
github.com/google/gnostic-models v0.6.9-0.20230804172637-c7be7c783f49 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.24.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-getter/v2 v2.2.3 // indirect
github.com/hashicorp/go-safetemp v1.0.0 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/josharian/native v1.1.0 // indirect
github.com/jsimonetti/rtnetlink/v2 v2.0.2 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.11 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mdlayher/ethtool v0.2.0 // indirect
github.com/mdlayher/genetlink v1.3.2 // indirect
github.com/mdlayher/netlink v1.7.2 // indirect
github.com/mdlayher/socket v0.5.1 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
github.com/siderolabs/crypto v0.5.0 // indirect
github.com/siderolabs/go-api-signature v0.3.6 // indirect
github.com/siderolabs/go-blockdevice/v2 v2.0.6 // indirect
github.com/siderolabs/go-cmd v0.1.3 // indirect
github.com/siderolabs/go-kubernetes v0.2.16 // indirect
github.com/siderolabs/go-pointer v1.0.0 // indirect
github.com/siderolabs/go-procfs v0.1.2 // indirect
github.com/siderolabs/go-retry v0.3.3 // indirect
github.com/siderolabs/go-talos-support v0.1.1 // indirect
github.com/siderolabs/proto-codec v0.1.1 // indirect
github.com/siderolabs/protoenc v0.2.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
github.com/u-root/uio v0.0.0-20240224005618-d2acac8f3701 // indirect
github.com/ulikunitz/xz v0.5.12 // indirect
github.com/vishvananda/netlink v1.3.0 // indirect
github.com/vishvananda/netns v0.0.4 // indirect
github.com/x448/float16 v0.8.4 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
go.opentelemetry.io/otel v1.32.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect
go.opentelemetry.io/otel/metric v1.32.0 // indirect
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
go.opentelemetry.io/otel/trace v1.32.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.29.0 // indirect
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
golang.org/x/oauth2 v0.24.0 // indirect
golang.org/x/sys v0.27.0 // indirect
golang.org/x/term v0.26.0 // indirect
golang.org/x/text v0.20.0 // indirect
golang.org/x/time v0.8.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20241118233622-e639e219e697 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20241118233622-e639e219e697 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gotest.tools/v3 v3.5.1 // indirect
k8s.io/api v0.32.0-beta.0 // indirect
k8s.io/apimachinery v0.32.0-beta.0 // indirect
k8s.io/client-go v0.32.0-beta.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/kube-openapi v0.0.0-20240827152857-f7e401e7b4c2 // indirect
k8s.io/utils v0.0.0-20241104163129-6fe5fd82f078 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
sigs.k8s.io/knftables v0.0.17 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
574 changes: 574 additions & 0 deletions go.sum

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions hack/certs/key.private
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
-----BEGIN PGP PRIVATE KEY BLOCK-----

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
hp/KSDr6GKR6H5ggj1v1tBWE95A=
=pdI2
-----END PGP PRIVATE KEY BLOCK-----
52 changes: 52 additions & 0 deletions hack/certs/key.public
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
2lEebIgAF9oRsC9BU9vSsg==
=f37X
-----END PGP PUBLIC KEY BLOCK-----
28 changes: 28 additions & 0 deletions hack/certs/localhost-key.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQC4ilhEy8jLTsSm
YW+hTenFrh8qvNYYYpo9PkQ/pscd4wyPi90BxKPoAIAWRsT5HE3cmJhD8cDtCly7
9N4JOSH8rLoU1OSUQTtL4U84kQ9+rNrOexR9O+URBSLyu338KRdlpvUs25z7an/S
Hwf6CqMGx+pgqIp+6ucwjYXvTgWw56POimVf/u1Xs5xsy/saHhQUzQwlpVBGHOtB
wFVigQzUpCsefLzUGpVZc5J2FVRoRp+k76imHObZXQqMdAIW2DzIRJ6WUB4MHnkK
sO25EdLHlRdGS9r0Bf+CXqPJ6ePYLKXDRA3/KSLlnenShHp0NR2DQMhiG4oDi4Sb
1TQYFlXpAgMBAAECggEBAKPnPD7eQJlSfJbKM7uw19EbtdLfpchCy3tZsoRWPMPu
xVk5gDHx1SJaT2l5sbkPypgDcDnontHqQjMuaYcHl4g0YZHfBKYoyeG7XAGB1aFN
JYn/B1OzvuA/D6tHm747QOyoPVp6NBOZo62cohkTGXkMVr9C8r+HI4+cIzlIswVL
NW4+vCMZ9WQ5z98NpJX3isK6BDemWyfi702oTLG7XIwzn7GQWL0jQX+zOmYkmo+K
InGSnrHl7pILs2InDIA/3AMI4K/w/mqu11h2+VKKmHUyOKi47lBUdtpZp9KLMA6W
kJ3mwQX2RU8mAWpuGE+Bo23WApdcwRV+UYGtU+mE3YECgYEA0Q8OhvtF2/MWyLWp
Q0hNJ4PK7+Htnx/xzxzEOadLwTio19cO51J83zlAqQ6dCE4HUsQmZVlMl7kq6zfL
z7kn1x9H87YcBYnfxUFOQUKco5N/GibhJi85t0tjuReDU3GxZS7MsA7vsOn/uIdC
W91FS01QxgAl1bEnCK2gbNWNYlsCgYEA4fnxDoRuprj83Jz4MxbLSpqOrQE+S1V2
3XGVHSo2x9i1d7T+CzVaug2r1Jqz02cRn15fE24B2KkoYz7eCNEJ7A0HfOLwwq2s
m9RMyAFY/RoktIZb09SwYneleuX3pvIQJ7hkX0oxg7EeVK/1H93lCrgBz4SVeUXe
nNzmkxY8FAsCgYEAt5MNIqJKudU/0IcUVqyKc4RbE0HEstION9v+wtGQx97FBKMn
xyC73hgcG1dltQEvlRIA1UYQ57oFYf7gzUq9HT2upObovERRZpjt6ohfm5PNLF2v
nyQg/j8JFmL7Qq63Iy5xNrgm6abQkmzTbG9khbcikntWvcqNiCVOlcMAH7kCgYEA
pXg02JGGyNSKbC0Q3bAiOkXEldBkQhuZx3tlWg7QQDRiZP6GS8TM45IhMbP6W6GM
WOtsqTiTZ4guR8YAJeqT3mKICh3PeG5eB1lEw+ugsu0S1ZHQ6eNDKUc9SCne10NH
Kx6teM1GRo1KjW6vCp+cGOY2hTMrlLrh0HE88ZWFdpMCgYEAigbuLOfVlSbIQ8vg
UJHf6JM5Lrc6oG6LW6fRUabnJibQ/TboNeV7PYd594swBrSwzJ/yRch8d6UIRVSB
cftPlut2YvHcoMlOhqS0oOOFNJx1JFNj8s0SMfQBd7MXG8r+OSL4pWPL7EhVmsS2
WMXSd3FqGMORF7NKqrtXGb203mk=
-----END PRIVATE KEY-----
26 changes: 26 additions & 0 deletions hack/certs/localhost.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
-----BEGIN CERTIFICATE-----
MIIEVzCCAr+gAwIBAgIRAIfOe7RuXJAXhuacBA29W9EwDQYJKoZIhvcNAQELBQAw
WTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRcwFQYDVQQLDA51dGt1
QHUtaG9tZS1wYzEeMBwGA1UEAwwVbWtjZXJ0IHV0a3VAdS1ob21lLXBjMB4XDTI0
MDgxNjA4MTkwM1oXDTI2MTExNjA5MTkwM1owVjEnMCUGA1UEChMebWtjZXJ0IGRl
dmVsb3BtZW50IGNlcnRpZmljYXRlMSswKQYDVQQLDCJ1dGt1QHUtd29yay1zaWRl
cm8gKFV0a3Ugw5Z6ZGVtaXIpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
AQEAuIpYRMvIy07EpmFvoU3pxa4fKrzWGGKaPT5EP6bHHeMMj4vdAcSj6ACAFkbE
+RxN3JiYQ/HA7Qpcu/TeCTkh/Ky6FNTklEE7S+FPOJEPfqzaznsUfTvlEQUi8rt9
/CkXZab1LNuc+2p/0h8H+gqjBsfqYKiKfurnMI2F704FsOejzoplX/7tV7OcbMv7
Gh4UFM0MJaVQRhzrQcBVYoEM1KQrHny81BqVWXOSdhVUaEafpO+ophzm2V0KjHQC
Ftg8yESellAeDB55CrDtuRHSx5UXRkva9AX/gl6jyenj2Cylw0QN/yki5Z3p0oR6
dDUdg0DIYhuKA4uEm9U0GBZV6QIDAQABo4GcMIGZMA4GA1UdDwEB/wQEAwIFoDAT
BgNVHSUEDDAKBggrBgEFBQcDATAfBgNVHSMEGDAWgBSUwQKJ6xTCiIbTU/iD3Wgy
OE1oFjBRBgNVHREESjBIgglsb2NhbGhvc3SCCyoubG9jYWxob3N0ghVteS1pbnN0
YW5jZS5sb2NhbGhvc3SCFyoubXktaW5zdGFuY2UubG9jYWxob3N0MA0GCSqGSIb3
DQEBCwUAA4IBgQAcK6EcBER1ExJ+jaLRLvyvkw0Z9JhB5AVVpgKuE9XJiJHrQCuJ
4nFeCZ2Nse8VkPtLdUCzup9ycbBFGzEp6XzjoeBpvC+uTJ6AhjNG/vPhSzgwX++a
69BzLGZVvrsh1BOwVy676gif99E5s19slzYHFm4kq/cXhkE8zMww0gFa3Xb9FGJv
hOfPA5yyJAC30bbUU0cKamGMRmS75jnWWlCrIwez+PEzEbLc7jELXfBtfX+zc8Ek
IIpK4S/IgbXNM0dXVNHdhGE56hRB/kBZSjHNy7QSB/mPStInM9YSDz4HKYXCLhQ4
NNXZYst3YFhmgJ8cuVAyP0AZ8gNtbzLhwZXW00UE0q8t+xpgEQ87v4vIqXLCwqOK
iw+G5aGQpsZF6oHmPpPcQ5J7kHLIMvk+VVHVAivn4PRZqRkzbYxVennCcDqPStd4
5Y9cKB4iWIHjfmdwGOGKJEfLlUHpG7R/8NoXJ8Ga9NU0UvgpTXg4yn7ChV/Cj4H6
hCLKZcW/DPjnWiI=
-----END CERTIFICATE-----
149 changes: 149 additions & 0 deletions hack/release.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
#!/usr/bin/env bash

# THIS FILE WAS AUTOMATICALLY GENERATED, PLEASE DO NOT EDIT.
#
# Generated on 2024-10-14T09:32:55Z by kres 34e72ac.

set -e

RELEASE_TOOL_IMAGE="ghcr.io/siderolabs/release-tool:latest"

function release-tool {
docker pull "${RELEASE_TOOL_IMAGE}" >/dev/null
docker run --rm -w /src -v "${PWD}":/src:ro "${RELEASE_TOOL_IMAGE}" -l -d -n -t "${1}" ./hack/release.toml
}

function changelog {
if [ "$#" -eq 1 ]; then
(release-tool ${1}; echo; cat CHANGELOG.md) > CHANGELOG.md- && mv CHANGELOG.md- CHANGELOG.md
else
echo 1>&2 "Usage: $0 changelog [tag]"
exit 1
fi
}

function release-notes {
release-tool "${2}" > "${1}"
}

function cherry-pick {
if [ $# -ne 2 ]; then
echo 1>&2 "Usage: $0 cherry-pick <commit> <branch>"
exit 1
fi

git checkout $2
git fetch
git rebase upstream/$2
git cherry-pick -x $1
}

function commit {
if [ $# -ne 1 ]; then
echo 1>&2 "Usage: $0 commit <tag>"
exit 1
fi

if is_on_main_branch; then
update_license_files
fi

git commit -s -m "release($1): prepare release" -m "This is the official $1 release."
}

function is_on_main_branch {
main_remotes=("upstream" "origin")
branch_names=("main" "master")
current_branch=$(git rev-parse --abbrev-ref HEAD)

echo "Check current branch: $current_branch"

for remote in "${main_remotes[@]}"; do
echo "Fetch remote $remote..."

if ! git fetch --quiet "$remote" &>/dev/null; then
echo "Failed to fetch $remote, skip..."

continue
fi

for branch_name in "${branch_names[@]}"; do
if ! git rev-parse --verify "$branch_name" &>/dev/null; then
echo "Branch $branch_name does not exist, skip..."

continue
fi

echo "Branch $remote/$branch_name exists, comparing..."

merge_base=$(git merge-base "$current_branch" "$remote/$branch_name")
latest_main=$(git rev-parse "$remote/$branch_name")

if [ "$merge_base" = "$latest_main" ]; then
echo "Current branch is up-to-date with $remote/$branch_name"

return 0
else
echo "Current branch is not on $remote/$branch_name"

return 1
fi
done
done

echo "No main or master branch found on any remote"

return 1
}

function update_license_files {
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
parent_dir="$(dirname "$script_dir")"
current_year=$(date +"%Y")
change_date=$(date -v+4y +"%Y-%m-%d" 2>/dev/null || date -d "+4 years" +"%Y-%m-%d" 2>/dev/null || date --date="+4 years" +"%Y-%m-%d")

# Find LICENSE and .kres.yaml files recursively in the parent directory (project root)
find "$parent_dir" \( -name "LICENSE" -o -name ".kres.yaml" \) -type f | while read -r file; do
temp_file="${file}.tmp"

if [[ $file == *"LICENSE" ]]; then
if grep -q "^Business Source License" "$file"; then
sed -e "s/The Licensed Work is (c) [0-9]\{4\}/The Licensed Work is (c) $current_year/" \
-e "s/Change Date: [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}/Change Date: $change_date/" \
"$file" >"$temp_file"
else
continue # Not a Business Source License file
fi
elif [[ $file == *".kres.yaml" ]]; then
sed -E 's/^([[:space:]]*)ChangeDate:.*$/\1ChangeDate: "'"$change_date"'"/' "$file" >"$temp_file"
fi

# Check if the file has changed
if ! cmp -s "$file" "$temp_file"; then
mv "$temp_file" "$file"
echo "Updated: $file"
git add "$file"
else
echo "No changes: $file"
rm "$temp_file"
fi
done
}

if declare -f "$1" > /dev/null
then
cmd="$1"
shift
$cmd "$@"
else
cat <<EOF
Usage:
commit: Create the official release commit message (updates BUSL license dates if there is any).
cherry-pick: Cherry-pick a commit into a release branch.
changelog: Update the specified CHANGELOG.
release-notes: Create release notes for GitHub release.
EOF

exit 1
fi

11 changes: 11 additions & 0 deletions hack/release.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# commit to be tagged for the new release
commit = "HEAD"

project_name = "omni-infra-provider-bare-metal"
github_repo = "siderolabs/omni-infra-provider-bare-metal"
match_deps = "^github.com/(siderolabs/[a-zA-Z0-9-]+)$"

# previous = -
# pre_release = true

# [notes]
136 changes: 136 additions & 0 deletions hack/test/integration.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
#!/bin/bash

set -eoux pipefail

SUBNET_CIDR=172.42.0.0/24
GATEWAY_IP=172.42.0.1

# Register cleanup script

function cleanup() {
sudo killall qemu-up-linux-amd64 || true
_out/qemu-up-linux-amd64 --destroy
docker rm -f omni-integration vault-dev
rm -rf _out/omni/
}

trap cleanup EXIT SIGINT

# Bring some QEMU machines up

sudo -E "${ARTIFACTS}/qemu-up-linux-amd64" --cidr $SUBNET_CIDR 2>&1 &

wait_for_bridge_ip() {
local timeout=60
local interval=5

echo "Waiting for IP address $GATEWAY_IP to appear..."

while ((timeout > 0)); do
if ip a | grep -q "$GATEWAY_IP"; then
echo "IP address $GATEWAY_IP found!"
return 0 # Success
fi

((timeout -= interval)) # Reduce the remaining time
sleep "$interval"
done

echo "Timed out waiting for IP address $GATEWAY_IP."
return 1 # Failure
}

# Wait for the bridge IP address to appear

if ! wait_for_bridge_ip; then
exit 1 # Exit script on failure
fi

# Bring Omni up

OMNI_VERSION=${OMNI_VERSION:-latest}

if [[ "${CI:-false}" == "true" ]]; then
REGISTRY_MIRROR_FLAGS=()

for registry in docker.io k8s.gcr.io quay.io gcr.io ghcr.io registry.k8s.io factory.talos.dev; do
service="registry-${registry//./-}.ci.svc"
addr=$(python3 -c "import socket; print(socket.gethostbyname('${service}'))")

REGISTRY_MIRROR_FLAGS+=("--registry-mirror=${registry}=http://${addr}:5000")
done
else
# use the value from the environment, if present
REGISTRY_MIRROR_FLAGS=("${REGISTRY_MIRROR_FLAGS:-}")
fi

# Start Vault.

docker run --rm -d --cap-add=IPC_LOCK -p 8200:8200 -e 'VAULT_DEV_ROOT_TOKEN_ID=dev-o-token' --name vault-dev hashicorp/vault:1.15

sleep 10

# Load key into Vault.

docker cp hack/certs/key.private vault-dev:/tmp/key.private
docker exec -e VAULT_ADDR='http://0.0.0.0:8200' -e VAULT_TOKEN=dev-o-token vault-dev \
vault kv put -mount=secret omni-private-key \
private-key=@/tmp/key.private

sleep 5

# Launch Omni in the background.

export BASE_URL=https://localhost:8099/
export AUTH_USERNAME="${AUTH0_TEST_USERNAME}"
export AUTH0_CLIENT_ID="${AUTH0_CLIENT_ID}"
export AUTH0_DOMAIN="${AUTH0_DOMAIN}"

docker run -it -d --network host -v ./hack/certs:/certs \
-v "$(pwd)/_out/omni:/_out" \
--cap-add=NET_ADMIN \
--device=/dev/net/tun \
-e SIDEROLINK_DEV_JOIN_TOKEN="${JOIN_TOKEN}" \
-e VAULT_TOKEN=dev-o-token \
-e VAULT_ADDR='http://127.0.0.1:8200' \
"ghcr.io/siderolabs/omni:${OMNI_VERSION}" \
omni-integration \
--siderolink-wireguard-advertised-addr 10.11.0.1:50180 \
--siderolink-api-advertised-url "grpc://10.11.0.1:8090" \
--machine-api-bind-addr 0.0.0.0:8090 \
--siderolink-wireguard-bind-addr 0.0.0.0:50180 \
--event-sink-port 8091 \
--auth-auth0-enabled true \
--advertised-api-url "${BASE_URL}" \
--auth-auth0-client-id "${AUTH0_CLIENT_ID}" \
--auth-auth0-domain "${AUTH0_DOMAIN}" \
--initial-users "${AUTH_USERNAME}" \
--private-key-source "vault://secret/omni-private-key" \
--public-key-files "/certs/key.public" \
--bind-addr 0.0.0.0:8099 \
--key /certs/localhost-key.pem \
--cert /certs/localhost.pem \
--etcd-embedded-unsafe-fsync=true \
--create-initial-service-account \
--initial-service-account-key-path=/_out/key \
"${REGISTRY_MIRROR_FLAGS[@]}" \
2>&1 &

# Determine the local IP
LOCAL_IP=$(ip -o route get to 8.8.8.8 | sed -n 's/.*src \([0-9.]\+\).*/\1/p')

# Launch infra provider in the background
echo "Local IP: $LOCAL_IP"

nice -n 10 _out/provider \
--insecure-skip-tls-verify \
--api-advertise-address="$LOCAL_IP" \
--use-local-boot-assets \
--agent-test-mode \
--api-power-mgmt-state-dir="$HOME/.talos/clusters/bare-metal" \
--dhcp-proxy-iface-or-ip=$GATEWAY_IP \
--debug \
"$@" \
2>&1 &

sleep 120
Loading

0 comments on commit 70acf82

Please sign in to comment.