mirror of
https://github.com/kairos-io/kairos-agent.git
synced 2025-04-27 11:21:44 +00:00
Merge branch 'main' into autoupgrade
This commit is contained in:
commit
319041a813
2
.github/workflows/osv-scanner-pr.yaml
vendored
2
.github/workflows/osv-scanner-pr.yaml
vendored
@ -18,4 +18,4 @@ permissions:
|
||||
|
||||
jobs:
|
||||
scan-pr:
|
||||
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v1.9.0"
|
||||
uses: "google/osv-scanner-action/.github/workflows/osv-scanner-reusable.yml@v1.9.1"
|
||||
|
4
.github/workflows/unit-tests.yml
vendored
4
.github/workflows/unit-tests.yml
vendored
@ -21,14 +21,14 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Go environment
|
||||
uses: actions/setup-go@v5.0.2
|
||||
uses: actions/setup-go@v5.2.0
|
||||
with:
|
||||
go-version: '${{ matrix.go-version }}'
|
||||
- name: Run tests
|
||||
run: |
|
||||
go run github.com/onsi/ginkgo/v2/ginkgo run -p --github-output --covermode=atomic --coverprofile=coverage.out --race -r ./...
|
||||
- name: Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
uses: codecov/codecov-action@v5
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
with:
|
||||
|
119
go.mod
119
go.mod
@ -3,44 +3,45 @@ module github.com/kairos-io/kairos-agent/v2
|
||||
go 1.23.1
|
||||
|
||||
require (
|
||||
github.com/Masterminds/semver/v3 v3.3.0
|
||||
github.com/Masterminds/semver/v3 v3.3.1
|
||||
github.com/Masterminds/sprig/v3 v3.3.0
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1
|
||||
github.com/diskfs/go-diskfs v1.4.1
|
||||
github.com/diskfs/go-diskfs v1.4.2
|
||||
github.com/erikgeiser/promptkit v0.9.0
|
||||
github.com/google/go-containerregistry v0.20.2
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jaypipes/ghw v0.13.0 // indirect
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/kairos-io/kairos-sdk v0.6.0
|
||||
github.com/kairos-io/go-nodepair v0.3.0
|
||||
github.com/kairos-io/kairos-sdk v0.6.1
|
||||
github.com/kairos-io/kcrypt v0.12.2
|
||||
github.com/labstack/echo/v4 v4.12.0
|
||||
github.com/labstack/echo/v4 v4.13.2
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5
|
||||
github.com/mudler/go-processmanager v0.0.0-20240820160718-8b802d3ecf82
|
||||
github.com/mudler/yip v1.11.0
|
||||
github.com/mudler/yip v1.13.0
|
||||
github.com/nxadm/tail v1.4.11
|
||||
github.com/onsi/ginkgo/v2 v2.20.2
|
||||
github.com/onsi/gomega v1.34.2
|
||||
github.com/pterm/pterm v0.12.79
|
||||
github.com/onsi/ginkgo/v2 v2.22.0
|
||||
github.com/onsi/gomega v1.36.1
|
||||
github.com/pterm/pterm v0.12.80
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/sanity-io/litter v1.5.5
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af
|
||||
github.com/sirupsen/logrus v1.9.4-0.20241118143825-d1e633264448
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/urfave/cli/v2 v2.27.4
|
||||
golang.org/x/net v0.29.0
|
||||
golang.org/x/oauth2 v0.23.0
|
||||
golang.org/x/sys v0.25.0
|
||||
github.com/urfave/cli/v2 v2.27.5
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/oauth2 v0.24.0
|
||||
golang.org/x/sys v0.28.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/mount-utils v0.31.1
|
||||
k8s.io/mount-utils v0.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/google/go-github/v63 v63.0.0
|
||||
github.com/twpayne/go-vfs/v4 v4.3.0
|
||||
github.com/google/go-github/v66 v66.0.0
|
||||
github.com/google/go-github/v67 v67.0.0
|
||||
github.com/twpayne/go-vfs/v5 v5.0.4
|
||||
)
|
||||
|
||||
require (
|
||||
@ -50,10 +51,9 @@ require (
|
||||
dario.cat/mergo v1.0.1 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.2 // indirect
|
||||
github.com/Microsoft/hcsshim v0.11.7 // indirect
|
||||
github.com/Microsoft/hcsshim v0.12.9 // indirect
|
||||
github.com/ProtonMail/go-crypto v1.0.0 // indirect
|
||||
github.com/StackExchange/wmi v1.2.1 // indirect
|
||||
github.com/alecthomas/assert/v2 v2.6.0 // indirect
|
||||
github.com/anatol/devmapper.go v0.0.0-20230829043248-59ac2b9706ba // indirect
|
||||
github.com/anatol/luks.go v0.0.0-20240507052915-92f8bb765f98 // indirect
|
||||
github.com/atotto/clipboard v0.1.4 // indirect
|
||||
@ -66,15 +66,16 @@ require (
|
||||
github.com/charmbracelet/lipgloss v0.7.1 // indirect
|
||||
github.com/chuckpreslar/emission v0.0.0-20170206194824-a7ddd980baf9 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 // indirect
|
||||
github.com/containerd/containerd v1.7.22 // indirect
|
||||
github.com/containerd/continuity v0.4.2 // indirect
|
||||
github.com/containerd/errdefs v0.1.0 // indirect
|
||||
github.com/containerd/cgroups/v3 v3.0.3 // indirect
|
||||
github.com/containerd/console v1.0.4 // indirect
|
||||
github.com/containerd/containerd v1.7.23 // indirect
|
||||
github.com/containerd/continuity v0.4.4 // indirect
|
||||
github.com/containerd/errdefs v1.0.0 // indirect
|
||||
github.com/containerd/errdefs/pkg v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/containerd/typeurl/v2 v2.2.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/denisbrodbeck/machineid v1.0.1 // indirect
|
||||
github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d // indirect
|
||||
@ -86,14 +87,14 @@ require (
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/edsrzf/mmap-go v1.1.0 // indirect
|
||||
github.com/eliukblau/pixterm v1.3.1 // indirect
|
||||
github.com/edsrzf/mmap-go v1.2.0 // indirect
|
||||
github.com/eliukblau/pixterm v1.3.2 // indirect
|
||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca // indirect
|
||||
github.com/foxboron/go-uefi v0.0.0-20241017190036-fab4fdf2f2f3 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 // indirect
|
||||
github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
github.com/go-git/go-billy/v5 v5.5.0 // indirect
|
||||
github.com/go-git/go-git/v5 v5.12.0 // indirect
|
||||
@ -101,14 +102,12 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
|
||||
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||
github.com/gofrs/flock v0.8.1 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 // indirect
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
@ -119,12 +118,12 @@ require (
|
||||
github.com/itchyny/timefmt-go v0.1.6 // indirect
|
||||
github.com/jaypipes/pcidb v1.0.1 // indirect
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
|
||||
github.com/jezek/xgb v1.1.0 // indirect
|
||||
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 // indirect
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 // indirect
|
||||
github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 // indirect
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
@ -135,14 +134,14 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
||||
github.com/mauromorales/xpasswd v0.4.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/sys/sequential v0.5.0 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.2 // indirect
|
||||
github.com/moby/sys/sequential v0.6.0 // indirect
|
||||
github.com/moby/sys/userns v0.1.0 // indirect
|
||||
github.com/mudler/entities v0.8.1 // indirect
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||
@ -152,8 +151,6 @@ require (
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/opencontainers/runc v1.1.14 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/otiai10/copy v1.14.0 // indirect
|
||||
github.com/packethost/packngo v0.29.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
@ -191,11 +188,12 @@ require (
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/tredoe/osutil v1.5.0 // indirect
|
||||
github.com/twpayne/go-vfs/v4 v4.3.0 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 // indirect
|
||||
github.com/vishvananda/netlink v1.3.0 // indirect
|
||||
github.com/vishvananda/netns v0.0.4 // indirect
|
||||
github.com/vmware/vmw-guestinfo v0.0.0-20220317130741-510905f0efa3 // indirect
|
||||
github.com/wayneashleyberry/terminal-dimensions v1.1.0 // indirect
|
||||
@ -205,31 +203,30 @@ require (
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zcalusic/sysinfo v1.1.2 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
go.uber.org/multierr v1.9.0 // indirect
|
||||
golang.org/x/crypto v0.27.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
|
||||
golang.org/x/image v0.18.0 // indirect
|
||||
golang.org/x/mod v0.21.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/term v0.24.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/tools v0.24.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 // indirect
|
||||
go.opentelemetry.io/otel v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.31.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.31.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa // indirect
|
||||
golang.org/x/image v0.20.0 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.26.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 // indirect
|
||||
google.golang.org/grpc v1.67.1 // indirect
|
||||
google.golang.org/protobuf v1.35.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
howett.net/plist v1.0.0 // indirect
|
||||
k8s.io/klog/v2 v2.130.1 // indirect
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||
pault.ag/go/modprobe v0.1.2 // indirect
|
||||
pault.ag/go/topsort v0.1.1 // indirect
|
||||
)
|
||||
|
272
go.sum
272
go.sum
@ -24,15 +24,15 @@ github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi
|
||||
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver/v3 v3.3.0 h1:B8LGeaivUe71a5qox1ICM/JLl0NqZSW5CHyL+hmvYS0=
|
||||
github.com/Masterminds/semver/v3 v3.3.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7rj+4nv4=
|
||||
github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs=
|
||||
github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0=
|
||||
github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY=
|
||||
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
|
||||
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
|
||||
github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ=
|
||||
github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU=
|
||||
github.com/Microsoft/hcsshim v0.12.9 h1:2zJy5KA+l0loz1HzEGqyNnjd3fyZA31ZBCGKacp6lLg=
|
||||
github.com/Microsoft/hcsshim v0.12.9/go.mod h1:fJ0gkFAna6ukt0bLdKB8djt4XIJhF/vEPuoIWYVvZ8Y=
|
||||
github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0kC2U78=
|
||||
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
|
||||
github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA=
|
||||
@ -71,8 +71,8 @@ github.com/cavaliergopher/grab v2.0.0+incompatible h1:XLeGNAc7MIRTMb8RlRbN76uO8v
|
||||
github.com/cavaliergopher/grab v2.0.0+incompatible/go.mod h1:6ICNRTQPwkMP0m2sKIDv/9XkhFJJwiEOQyZ+8E4H7Yg=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY=
|
||||
github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc=
|
||||
@ -87,26 +87,29 @@ github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUK
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGDJ9kip0=
|
||||
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5 h1:Ig+OPkE3XQrrl+SKsOqAjlkrBN/zrr+Qpw7rCuDjRCE=
|
||||
github.com/containerd/console v1.0.4-0.20230706203907-8f6c4e4faef5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.22 h1:nZuNnNRA6T6jB975rx2RRNqqH2k6ELYKDZfqTHqwyy0=
|
||||
github.com/containerd/containerd v1.7.22/go.mod h1:e3Jz1rYRUZ2Lt51YrH9Rz0zPyJBOlSvB3ghr2jbVD8g=
|
||||
github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM=
|
||||
github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM=
|
||||
github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.23 h1:H2CClyUkmpKAGlhQp95g2WXHfLYc7whAuvZGBNYOOwQ=
|
||||
github.com/containerd/containerd v1.7.23/go.mod h1:7QUzfURqZWCZV7RLNEn1XjUCQLEf0bkaK4GjUaZehxw=
|
||||
github.com/containerd/continuity v0.4.4 h1:/fNVfTJ7wIl/YPMHjf+5H32uFhl63JucB34PlCpMKII=
|
||||
github.com/containerd/continuity v0.4.4/go.mod h1:/lNJvtJKUQStBzpVQ1+rasXO1LAWtUQssk28EZvJ3nE=
|
||||
github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG8PI=
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/containerd/typeurl/v2 v2.2.2 h1:3jN/k2ysKuPCsln5Qv8bzR9cxal8XjkxPogJfSNO31k=
|
||||
github.com/containerd/typeurl/v2 v2.2.2/go.mod h1:95ljDnPfD3bAbDJRugOiShd/DlAAsxGtUBhJxIn7SCk=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -120,8 +123,8 @@ github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d h1:CPqTNIigGwe
|
||||
github.com/dgryski/go-camellia v0.0.0-20191119043421-69a8a13fb23d/go.mod h1:QX5ZVULjAfZJux/W62Y91HvCh9hyW6enAwcrrv/sLj0=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/diskfs/go-diskfs v1.4.1 h1:iODgkzHLmvXS+1VDztpW53T+dQm8GQzi20y9yUd5UCA=
|
||||
github.com/diskfs/go-diskfs v1.4.1/go.mod h1:+tOkQs8CMMog6Nvljg8DGIxEXrgL48iyT3OM3IlSz74=
|
||||
github.com/diskfs/go-diskfs v1.4.2 h1:khBr9RTkqAZFaMYK7PP8NooL30hqj3bSgRmj3Ouguls=
|
||||
github.com/diskfs/go-diskfs v1.4.2/go.mod h1:ss1uAUBhgDdEOewZFDWWpYqJFjNPbK7hYSjRoQE+D94=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/djherbis/times v1.6.0 h1:w2ctJ92J8fBvWPxugmXIv7Nz7Q3iDMKNx9v5ocVH20c=
|
||||
@ -139,12 +142,13 @@ github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKoh
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
|
||||
github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/edsrzf/mmap-go v1.2.0 h1:hXLYlkbaPzt1SaQk+anYwKSRNhufIDCchSPkUD6dD84=
|
||||
github.com/edsrzf/mmap-go v1.2.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU=
|
||||
github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM=
|
||||
github.com/eliukblau/pixterm v1.3.1 h1:XeouQViH+lmzCa7sMUoK2cd7qlgHYGLIjwRKaOdJbKA=
|
||||
github.com/eliukblau/pixterm v1.3.1/go.mod h1:on5ueknFt+ZFVvIVVzQ7/JXwPjv5fJd8Q1Ybh7XixfU=
|
||||
github.com/eliukblau/pixterm v1.3.2 h1:kAF9qvbaDV3emb9LPHw1Bvd9D5o4y28U0e8Q9vfl24I=
|
||||
github.com/eliukblau/pixterm v1.3.2/go.mod h1:CgaInx2l92Xo3GTldly4UQeNghSFXmIQNk3zL77Xo/A=
|
||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab h1:h1UgjJdAAhj+uPL68n7XASS6bU+07ZX1WJvVS2eyoeY=
|
||||
github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab/go.mod h1:GLo/8fDswSAniFG+BFIaiSPcK610jyzgEhWYPQwuQdw=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
@ -157,8 +161,8 @@ github.com/erikgeiser/promptkit v0.9.0 h1:3qL1mS/ntCrXdb8sTP/ka82CJ9kEQaGuYXNrYJ
|
||||
github.com/erikgeiser/promptkit v0.9.0/go.mod h1:pU9dtogSe3Jlc2AY77EP7R4WFP/vgD4v+iImC83KsCo=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca h1:ErxkaWK5AIt8gQf3KpAuQQBdZI4ps72HzEe123kh+So=
|
||||
github.com/foxboron/go-uefi v0.0.0-20240805124652-e2076f0e58ca/go.mod h1:ffg/fkDeOYicEQLoO2yFFGt00KUTYVXI+rfnc8il6vQ=
|
||||
github.com/foxboron/go-uefi v0.0.0-20241017190036-fab4fdf2f2f3 h1:K8ADp66ulnZ0NhjzwVwE4E3g6Id5KMWu86l0vURusA8=
|
||||
github.com/foxboron/go-uefi v0.0.0-20241017190036-fab4fdf2f2f3/go.mod h1:ffg/fkDeOYicEQLoO2yFFGt00KUTYVXI+rfnc8il6vQ=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
@ -166,8 +170,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5 h1:Y5Q2mEwfzjMt5+3u70Gtw93ZOu2UuPeeeTBDntF7FoY=
|
||||
github.com/gen2brain/shm v0.0.0-20200228170931-49f9650110c5/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7 h1:VLEKvjGJYAMCXw0/32r9io61tEXnMWDRxMk+peyRVFc=
|
||||
github.com/gen2brain/shm v0.0.0-20230802011745-f2460f5984f7/go.mod h1:uF6rMu/1nvu+5DpiRLwusA6xB8zlkNoGzKn8lmYONUo=
|
||||
github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE=
|
||||
github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8=
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||
@ -191,8 +195,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZ
|
||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw=
|
||||
github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
@ -214,8 +216,6 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@ -228,12 +228,13 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.20.2 h1:B1wPJ1SN/S7pB+ZAimcciVD+r+yV/l/DSArMxlbwseo=
|
||||
github.com/google/go-containerregistry v0.20.2/go.mod h1:z38EKdKh4h7IP2gSfUUqEvalZBqs6AoLeWfUy34nQC8=
|
||||
github.com/google/go-github/v63 v63.0.0 h1:13xwK/wk9alSokujB9lJkuzdmQuVn2QCPeck76wR3nE=
|
||||
github.com/google/go-github/v63 v63.0.0/go.mod h1:IqbcrgUmIcEaioWrGYei/09o+ge5vhffGOcxrO0AfmA=
|
||||
github.com/google/go-github/v66 v66.0.0 h1:ADJsaXj9UotwdgK8/iFZtv7MLc8E8WBl62WLd/D/9+M=
|
||||
github.com/google/go-github/v66 v66.0.0/go.mod h1:+4SO9Zkuyf8ytMj0csN1NR/5OTR+MfqPp8P8dVlcvY4=
|
||||
github.com/google/go-github/v67 v67.0.0/go.mod h1:zH3K7BxjFndr9QSeFibx4lTKkYS3K9nDanoI1NjaOtY=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5 h1:5iH8iuqE5apketRbSFBy+X1V0o+l+8NF1avt4HWl7cA=
|
||||
github.com/google/pprof v0.0.0-20240827171923-fa2c70bbbfe5/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -270,35 +271,35 @@ github.com/jaypipes/pcidb v1.0.1/go.mod h1:6xYUz/yYEyOkIkUt2t2J2folIuZ4Yg6uByCGF
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4=
|
||||
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
|
||||
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004 h1:G+9t9cEtnC9jFiTxyptEKuNIAbiN5ZCQzX2a74lj3xg=
|
||||
github.com/jzelinskie/whirlpool v0.0.0-20201016144138-0675e54bb004/go.mod h1:KmHnJWQrgEvbuy0vcvj00gtMqbvNn1L+3YUZLK/B92c=
|
||||
github.com/kairos-io/kairos-sdk v0.4.6 h1:6dbKozJTku99P2vytz9M0xAnpkKKiAggSMPfT2vpw68=
|
||||
github.com/kairos-io/kairos-sdk v0.4.6/go.mod h1:QXYmZ2BMrJ0Iyp7I3+rvCYpZRMvwOtK/6IGCLhNL4tY=
|
||||
github.com/kairos-io/kairos-sdk v0.6.0 h1:A096lZVHE4rkvA5kG0Oss0085T0noUcf7AeppWGySR8=
|
||||
github.com/kairos-io/kairos-sdk v0.6.0/go.mod h1:7Y6Y/McniCyAJcmQfoTfKd09cwmwS40URaIVbJn8V2k=
|
||||
github.com/kairos-io/go-nodepair v0.3.0 h1:JIMBAtbNhIAsx89aP61mQDGMuGFoIQH/woK2tMDYD6k=
|
||||
github.com/kairos-io/go-nodepair v0.3.0/go.mod h1:7i905W/KmR9DAcMSVJr/Wdb84E5Yyu9YLgj7chwX1xs=
|
||||
github.com/kairos-io/kairos-sdk v0.6.1 h1:DplbiHgWjg7W8zzeB5TQPFBthfF3UQxJlcLZqvQGagE=
|
||||
github.com/kairos-io/kairos-sdk v0.6.1/go.mod h1:MT/0k20U1BcN8AzzQUexpfrQ8XCC6jIPDG9ZAmx+I2c=
|
||||
github.com/kairos-io/kcrypt v0.12.2 h1:+lr8FGS0AW6D5dWSmaR3+AobL1TBTnOFgCSYctKY+5I=
|
||||
github.com/kairos-io/kcrypt v0.12.2/go.mod h1:7SPiHzNMYl4MlxeB30s1YlHDYByTusu7u1mU5Nvicm0=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329 h1:qq2nCpSrXrmvDGRxW0ruW9BVEV1CN2a9YDOExdt+U0o=
|
||||
github.com/kbinani/screenshot v0.0.0-20210720154843-7d3a670d8329/go.mod h1:2VPVQDR4wO7KXHwP+DAypEy67rXf+okUx2zjgpCxZw4=
|
||||
github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237 h1:YOp8St+CM/AQ9Vp4XYm4272E77MptJDHkwypQHIRl9Q=
|
||||
github.com/kbinani/screenshot v0.0.0-20230812210009-b87d31814237/go.mod h1:e7qQlOY68wOz4b82D7n+DdaptZAi+SHW0+yKiWZzEYE=
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c h1:eKb4PqwAMhlqwXw0W3atpKaYaPGlXE/Fwh+xpCEYaPk=
|
||||
github.com/kendru/darwin/go/depgraph v0.0.0-20221105232959-877d6a81060c/go.mod h1:VOfm8h1NySetVlpHDSnbpCMsvCgYaU+YDn4XezUy2+4=
|
||||
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=
|
||||
github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU=
|
||||
github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
@ -306,13 +307,14 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
|
||||
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
|
||||
github.com/labstack/echo/v4 v4.13.1 h1:q3+CpQlYhJwpRr9+08pX0IdlabTIpnIhrg2AKPSKhFE=
|
||||
github.com/labstack/echo/v4 v4.13.1/go.mod h1:61j7WN2+bp8V21qerqRs4yVlVTGyOagMBpF0vE7VcmM=
|
||||
github.com/labstack/echo/v4 v4.13.2 h1:9aAt4hstpH54qIcqkuUXRLTf+v7yOTfMPWzDtuqLmtA=
|
||||
github.com/labstack/echo/v4 v4.13.2/go.mod h1:uc9gDtHB8UWt3FfbYx0HyxcCuvR4YuPYOxF/1QjoV/c=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
||||
@ -333,8 +335,8 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J
|
||||
github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mauromorales/xpasswd v0.4.0 h1:Jf6mfA8lwQsYzwgfQADPDGV7l/liAvRrnG+nQTPy0j8=
|
||||
github.com/mauromorales/xpasswd v0.4.0/go.mod h1:Z3+aY19mhNfcGi3st0+RAVSz2vC+pyoju2S/FPN8kEg=
|
||||
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
|
||||
@ -347,10 +349,10 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
|
||||
github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
|
||||
github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g=
|
||||
github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo=
|
||||
github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg=
|
||||
github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4=
|
||||
github.com/moby/sys/sequential v0.6.0 h1:qrx7XFUd/5DxtqcoH1h438hF5TmOvzC/lspjy7zgvCU=
|
||||
github.com/moby/sys/sequential v0.6.0/go.mod h1:uyv8EUTrca5PnDsdMGXhZe6CCe8U/UiTWd+lL+7b/Ko=
|
||||
github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g=
|
||||
github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28=
|
||||
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
|
||||
@ -359,16 +361,12 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mudler/entities v0.8.1 h1:/iZ3VrhZy8bSVr39IqoSwL4jphna2rgSYnJCUZakZ3s=
|
||||
github.com/mudler/entities v0.8.1/go.mod h1:exnXZF6qVnu4b9dEiH3sLEyxYBTknfkcJ3UCxyc/dwE=
|
||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb h1:F6TP0DW7C0U9sgm9g4uAs0Vp2JSkhn2umlyrNlxUKXw=
|
||||
github.com/mudler/go-nodepair v0.0.0-20221223092639-ba399a66fdfb/go.mod h1:6QsBHK5vY/wDnSpueKek3/qfoCZmdJ9pz7FnzQbP/gE=
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5 h1:FaZD86+A9mVt7lh9glAryzQblMsbJYU2VnrdZ8yHlTs=
|
||||
github.com/mudler/go-pluggable v0.0.0-20230126220627-7710299a0ae5/go.mod h1:WmKcT8ONmhDQIqQ+HxU+tkGWjzBEyY/KFO8LTGCu4AI=
|
||||
github.com/mudler/go-processmanager v0.0.0-20240820160718-8b802d3ecf82 h1:FVT07EI8njvsD4tC2Hw8Xhactp5AWhsQWD4oTeQuSAU=
|
||||
github.com/mudler/go-processmanager v0.0.0-20240820160718-8b802d3ecf82/go.mod h1:Urp7LG5jylKoDq0663qeBh0pINGcRl35nXdKx82PSoU=
|
||||
github.com/mudler/yip v1.10.0 h1:MwEIySEfSRRwTUz2BmQQpRn6+M7jqVGf/OldsepBvz0=
|
||||
github.com/mudler/yip v1.10.0/go.mod h1:gwH7iGcr1Jimox2xKtN2AprEO00GzY7smvuycqCL7+Y=
|
||||
github.com/mudler/yip v1.11.0 h1:h+npjzSKM9VbShHxa+ywWZzpGIolKvN/e2FOT+rxKkI=
|
||||
github.com/mudler/yip v1.11.0/go.mod h1:gwH7iGcr1Jimox2xKtN2AprEO00GzY7smvuycqCL7+Y=
|
||||
github.com/mudler/yip v1.13.0 h1:JN62ONxDpliGLH7tXFbk2rxiX+Y7G5jnLAj+LmGpPRw=
|
||||
github.com/mudler/yip v1.13.0/go.mod h1:gwH7iGcr1Jimox2xKtN2AprEO00GzY7smvuycqCL7+Y=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI=
|
||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
@ -387,21 +385,17 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108
|
||||
github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2 h1:7NVCeyIWROIAheY21RLS+3j2bb52W0W82tkberYytp4=
|
||||
github.com/onsi/ginkgo/v2 v2.20.2/go.mod h1:K9gyxPIlb+aIvnZ8bd9Ak+YP18w3APlR+5coaZoE2ag=
|
||||
github.com/onsi/ginkgo/v2 v2.22.0 h1:Yed107/8DjTr0lKCNt7Dn8yQ6ybuDRQoMGrNFKzMfHg=
|
||||
github.com/onsi/ginkgo/v2 v2.22.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc=
|
||||
github.com/onsi/gomega v1.34.2 h1:pNCwDkzrsv7MS9kpaQvVb1aVLahQXyJ/Tv5oAZMI3i8=
|
||||
github.com/onsi/gomega v1.34.2/go.mod h1:v1xfxRgk0KIsG+QOdm7p8UosrOzPYRo60fd3B/1Dukc=
|
||||
github.com/onsi/gomega v1.36.1 h1:bJDPBO7ibjxcbHMgSCoo4Yj18UWbKDlLwX1x9sybDcw=
|
||||
github.com/onsi/gomega v1.36.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
|
||||
github.com/opencontainers/image-spec v1.1.0/go.mod h1:W4s4sFTMaBeK1BQLXbG4AdM2szdn85PY75RI83NrTrM=
|
||||
github.com/opencontainers/runc v1.1.14 h1:rgSuzbmgz5DUJjeSnw337TxDbRuqjs6iqQck/2weR6w=
|
||||
github.com/opencontainers/runc v1.1.14/go.mod h1:E4C2z+7BxR7GHXp0hAY53mek+x49X1LjPNeMTfRGvOA=
|
||||
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
|
||||
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||
@ -434,8 +428,8 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
|
||||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.79 h1:lH3yrYMhdpeqX9y5Ep1u7DejyHy7NSQg9qrBjF9dFT4=
|
||||
github.com/pterm/pterm v0.12.79/go.mod h1:1v/gzOF1N0FsjbgTHZ1wVycRkKiatFvJSJC4IGaQAAo=
|
||||
github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg=
|
||||
github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo=
|
||||
github.com/qeesung/image2ascii v1.0.1 h1:Fe5zTnX/v/qNC3OC4P/cfASOXS501Xyw2UUcgrLgtp4=
|
||||
github.com/qeesung/image2ascii v1.0.1/go.mod h1:kZKhyX0h2g/YXa/zdJR3JnLnJ8avHjZ3LrvEKSYyAyU=
|
||||
github.com/rancher-sandbox/linuxkit v1.0.2 h1:mUFPL2Mgl1XZ5H82ABR57t5H2G2Qd+lu3gMYvUGmeZo=
|
||||
@ -480,8 +474,8 @@ github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af h1:Sp5TG9f7K39yfB+If0vjp97vuT74F72r8hfRpP8jLU0=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20230606125235-dd1b4c2e81af/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20241118143825-d1e633264448 h1:4T/wluVIsyQ0Kqamo3he0Q0FhZG7CBd5LJgb4KOmftM=
|
||||
github.com/sirupsen/logrus v1.9.4-0.20241118143825-d1e633264448/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A=
|
||||
github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo=
|
||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0=
|
||||
@ -533,20 +527,21 @@ github.com/tredoe/osutil v1.5.0 h1:UGVxbbHRoZi8xXVmbNZ2vgG6XoJ15ndE4LniiQ3rJKg=
|
||||
github.com/tredoe/osutil v1.5.0/go.mod h1:TEzphzUUunysbdDRfdOgqkg10POQbnfIPV50ynqOfIg=
|
||||
github.com/twpayne/go-vfs/v4 v4.3.0 h1:rTqFzzOQ/6ESKTSiwVubHlCBedJDOhQyVSnw8rQNZhU=
|
||||
github.com/twpayne/go-vfs/v4 v4.3.0/go.mod h1:tq2UVhnUepesc0lSnPJH/jQ8HruGhzwZe2r5kDFpEIw=
|
||||
github.com/twpayne/go-vfs/v5 v5.0.4 h1:/ne3h+rW7f5YOyOFguz+3ztfUwzOLR0Vts3y0mMAitg=
|
||||
github.com/twpayne/go-vfs/v5 v5.0.4/go.mod h1:zTPFJUbgsEMFNSWnWQlLq9wh4AN83edZzx3VXbxrS1w=
|
||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
|
||||
github.com/urfave/cli/v2 v2.27.4 h1:o1owoI+02Eb+K107p27wEX9Bb8eqIoZCfLXloLUSWJ8=
|
||||
github.com/urfave/cli/v2 v2.27.4/go.mod h1:m4QzxcD2qpra4z7WhzEGn74WZLViBnMpb1ToCAKdGRQ=
|
||||
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
||||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RVck=
|
||||
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2 h1:Llsql0lnQEbHj0I1OuKyp8otXp0r3q0mPkuhwHfStVs=
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho=
|
||||
github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0=
|
||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||
github.com/vishvananda/netns v0.0.4/go.mod h1:SpkAiCQRtJ6TvvxPnOSyH3BMl6unz3xZlaprSwhNNJM=
|
||||
github.com/vmware/vmw-guestinfo v0.0.0-20220317130741-510905f0efa3 h1:v6jG/tdl4O07LNVp74Nt7/OyL+1JsIW1M2f/nSvQheY=
|
||||
@ -571,48 +566,44 @@ github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
github.com/zcalusic/sysinfo v1.1.2 h1:38KUgZQmCxlN9vUTt4miis4rU5ISJXGXOJ2rY7bMC8g=
|
||||
github.com/zcalusic/sysinfo v1.1.2/go.mod h1:NX+qYnWGtJVPV0yWldff9uppNKU4h40hJIRPf/pGLv4=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1 h1:A/5uWzF44DlIgdm/PQFwfMkW0JX+cIcQi/SwLAmZP5M=
|
||||
go.mozilla.org/pkcs7 v0.0.0-20200128120323-432b2356ecb1/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.mozilla.org/pkcs7 v0.9.0 h1:yM4/HS9dYv7ri2biPtxt8ikvB37a980dg69/pKmS+eI=
|
||||
go.mozilla.org/pkcs7 v0.9.0/go.mod h1:SNgMg+EgDFwmvSmLRTNKC5fegJjB7v23qTQ0XLGUNHk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 h1:jq9TW8u3so/bN+JPT166wjOI6/vQPF6Xe7nMNIltagk=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0 h1:UP6IpuHFkUgOQL9FFQFrZ+5LiwhhYRbi7VZSIx6Nj5s=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.56.0/go.mod h1:qxuZLtbq5QDtdeSHsS7bcf6EH6uO6jUAgk764zd3rhM=
|
||||
go.opentelemetry.io/otel v1.31.0 h1:NsJcKPIW0D0H3NgzPDHmo0WW6SptzPdqg/L1zsIm2hY=
|
||||
go.opentelemetry.io/otel v1.31.0/go.mod h1:O0C14Yl9FgkjqcCZAsE053C13OaddMYr/hz6clDkEJE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0 h1:lUsI2TYsQw2r1IASwoROaCnjdj2cvC2+Jbxvk6nHnWU=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.31.0/go.mod h1:2HpZxxQurfGxJlJDblybejHB6RX6pmExPNe517hREw4=
|
||||
go.opentelemetry.io/otel/metric v1.31.0 h1:FSErL0ATQAmYHUIzSezZibnyVlft1ybhy4ozRPcF2fE=
|
||||
go.opentelemetry.io/otel/metric v1.31.0/go.mod h1:C3dEloVbLuYoX41KpmAhOqNriGbA+qqH6PQ5E5mUfnY=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
||||
go.opentelemetry.io/otel/trace v1.31.0 h1:ffjsj1aRouKewfr85U2aGagJ46+MvodynlQ1HYdmJys=
|
||||
go.opentelemetry.io/otel/trace v1.31.0/go.mod h1:TXZkRk7SM2ZQLtR6eoAWQFIHPvzQ06FJAsO1tJg480A=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200420201142-3c4aac89819a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
|
||||
golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa h1:ELnwvuAXPNtPk1TJRuGkI9fDTwym6AYBu0qzT8AcHdI=
|
||||
golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa/go.mod h1:akd2r19cwCdwSwWeIdzYQGa/EZZyqcOdwWiwj5L5eKQ=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20191206065243-da761ea9ff43/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.18.0 h1:jGzIakQa/ZXI1I0Fxvaa9W7yP25TqT6cHIHn+6CqvSQ=
|
||||
golang.org/x/image v0.18.0/go.mod h1:4yyo5vMFQjVjUcVk4jEQcU9MGy/rulF5WvUILseCM2E=
|
||||
golang.org/x/image v0.20.0 h1:7cVCUjQwfL18gyBJOmYvptfSHS8Fb3YUDtfLIZ7Nbpw=
|
||||
golang.org/x/image v0.20.0/go.mod h1:0a88To4CYVBAHp5FXJm8o7QbUl37Vd85ply1vyD8auM=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
@ -620,8 +611,8 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0=
|
||||
golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -640,11 +631,13 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
||||
golang.org/x/net v0.32.0 h1:ZqPmj8Kzc+Y6e0+skZsuACbx+wzMgo5MQsJh9Qd6aYI=
|
||||
golang.org/x/net v0.32.0/go.mod h1:CwU0IoeOlnQQWJ6ioyFrfRuomB8GKF6KbYXZVyeXNfs=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
|
||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.24.0 h1:KTBBxWqUa0ykRPLtV69rRto9TLXcqYkeswu48x/gvNE=
|
||||
golang.org/x/oauth2 v0.24.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@ -652,8 +645,8 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -663,10 +656,8 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200728102440-3e129f6d46b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -693,10 +684,11 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@ -704,8 +696,8 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
@ -715,8 +707,8 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -729,31 +721,31 @@ golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roY
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
|
||||
golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2 h1:rIo7ocm2roD9DcFIX67Ym8icoGCKSARAiPljFhh5suQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240311132316-a219d84964c2/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c h1:lfpJ/2rWPa/kJgxyyXM8PrNnfCzcmxJ265mADgwmvLI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142 h1:wKguEg1hsxI2/L3hUYrpo1RVi48K+uTyzKqprwLXsb8=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240814211410-ddb44dafa142/go.mod h1:d6be+8HhtEtucleCbxpPW9PA9XwISACu8nvpPqF0BVo=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38 h1:zciRKQ4kBpFgpfC5QQCVtnnNAcLIqweL7plyZRQHVpI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241021214115-324edc3d5d38/go.mod h1:GX3210XPVPUjJbTUbvwI8f2IpZDMZuPJWDzDuebbviI=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
|
||||
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
|
||||
google.golang.org/grpc v1.67.1 h1:zWnc1Vrcno+lHZCOofnIMvycFcc0QRGIzm9dhnDX68E=
|
||||
google.golang.org/grpc v1.67.1/go.mod h1:1gLDyUQU7CTLJI90u3nXZ9ekeghjeM7pTDZlqFNg2AA=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
@ -763,8 +755,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg=
|
||||
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
@ -786,18 +778,18 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
|
||||
gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g=
|
||||
gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY=
|
||||
gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
|
||||
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
|
||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/mount-utils v0.31.1 h1:f8UrH9kRynljmdNGM6BaCvFUON5ZPKDgE+ltmYqI4wA=
|
||||
k8s.io/mount-utils v0.31.1/go.mod h1:HV/VYBUGqYUj4vt82YltzpWvgv8FPg0G9ItyInT3NPU=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/mount-utils v0.32.0 h1:KOQAhPzJICATXnc6XCkWoexKbkOexRnMCUW8APFfwg4=
|
||||
k8s.io/mount-utils v0.32.0/go.mod h1:Kun5c2svjAPx0nnvJKYQWhfeNW+O0EpzHgRhDcYoSY0=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 h1:M3sRQVHv7vB20Xc2ybTt7ODCeFj6JSWYFzOFnYeS6Ro=
|
||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
pault.ag/go/modprobe v0.1.2 h1:bblunaPhqpTxGDJ5TVFW/4gheohBPleF2dIV6j6sWkI=
|
||||
pault.ag/go/modprobe v0.1.2/go.mod h1:afr2STC/2Maz/qi4+Bma1s0dszZgO/PcM8AKar9DWhM=
|
||||
pault.ag/go/topsort v0.0.0-20160530003732-f98d2ad46e1a/go.mod h1:INqx0ClF7kmPAMk2zVTX8DRnhZ/yaA/Mg52g8KFKE7k=
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
func TestConfig(t *testing.T) {
|
||||
|
@ -92,7 +92,7 @@ func (k KcryptUKI) Run(c config.Config, spec v1.Spec) error {
|
||||
for _, p := range append([]string{constants.OEMLabel, constants.PersistentLabel}, c.Install.Encrypt...) {
|
||||
c.Logger.Infof("Encrypting %s", p)
|
||||
_ = os.Setenv("SYSTEMD_LOG_LEVEL", "debug")
|
||||
err := kcrypt.LuksifyMeasurements(p, []string{"11"}, []string{}, c.Logger.Logger)
|
||||
err := kcrypt.LuksifyMeasurements(p, c.BindPublicPCRs, c.BindPCRs, c.Logger.Logger)
|
||||
_ = os.Unsetenv("SYSTEMD_LOG_LEVEL")
|
||||
if err != nil {
|
||||
c.Logger.Errorf("could not encrypt partition: %s", err)
|
||||
|
@ -19,6 +19,7 @@ import (
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/sanity-io/litter"
|
||||
|
||||
qr "github.com/kairos-io/go-nodepair/qrcode"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
@ -27,7 +28,6 @@ import (
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/machine"
|
||||
"github.com/kairos-io/kairos-sdk/utils"
|
||||
qr "github.com/mudler/go-nodepair/qrcode"
|
||||
"github.com/mudler/go-pluggable"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
@ -215,6 +215,11 @@ func RunInstall(c *config.Config) error {
|
||||
utils.SetEnv(c.Env)
|
||||
utils.SetEnv(c.Install.Env)
|
||||
|
||||
err := c.CheckForUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// UKI path. Check if we are on UKI AND if we are running off a cd, otherwise it makes no sense to run the install
|
||||
// From the installed system
|
||||
if internalutils.IsUkiWithFs(c.Fs) {
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
|
@ -152,31 +152,45 @@ func InteractiveInstall(debug, spawnShell bool, sourceImgURL string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
userName, err := prompt("User to setup", "kairos", canBeEmpty, true, false)
|
||||
createUser, err := prompt("Do you want to create any users? If not, system will not be accesible via terminal or ssh", "y", yesNo, true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
userPassword, err := prompt("Password", "", canBeEmpty, true, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var userName, userPassword, sshKeys, makeAdmin string
|
||||
|
||||
if userPassword == "" {
|
||||
userPassword = "!"
|
||||
}
|
||||
if isYes(createUser) {
|
||||
userName, err = prompt("User to setup", "kairos", canBeEmpty, true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
users, err := prompt("SSH access (rsakey, github/gitlab supported, comma-separated)", "github:someuser,github:someuser2", canBeEmpty, true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
userPassword, err = prompt("Password", "", canBeEmpty, true, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup the users if we selected the default values as they are not valid users
|
||||
if users == "github:someuser,github:someuser2" {
|
||||
users = ""
|
||||
}
|
||||
if users != "" {
|
||||
sshUsers = strings.Split(users, ",")
|
||||
if userPassword == "" {
|
||||
userPassword = "!"
|
||||
}
|
||||
|
||||
sshKeys, err = prompt("SSH access (rsakey, github/gitlab supported, comma-separated)", "github:someuser,github:someuser2", canBeEmpty, true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
makeAdmin, err = prompt("Make the user an admin (with sudo permissions)?", "y", yesNo, true, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Cleanup the users if we selected the default values as they are not valid users
|
||||
if sshKeys == "github:someuser,github:someuser2" {
|
||||
sshKeys = ""
|
||||
}
|
||||
if sshKeys != "" {
|
||||
sshUsers = strings.Split(sshKeys, ",")
|
||||
}
|
||||
}
|
||||
|
||||
// Prompt the user by prompts defined by the provider
|
||||
@ -216,41 +230,49 @@ func InteractiveInstall(debug, spawnShell bool, sourceImgURL string) error {
|
||||
return InteractiveInstall(debug, spawnShell, sourceImgURL)
|
||||
}
|
||||
|
||||
usersToSet := map[string]schema.User{}
|
||||
|
||||
stage := config.NetworkStage.String()
|
||||
|
||||
if userName != "" {
|
||||
user := schema.User{
|
||||
Name: userName,
|
||||
PasswordHash: userPassword,
|
||||
Groups: []string{"admin"},
|
||||
SSHAuthorizedKeys: sshUsers,
|
||||
}
|
||||
|
||||
// If we got no ssh keys, we don't need network, do the user as soon as possible
|
||||
if len(sshUsers) == 0 {
|
||||
stage = config.InitramfsStage.String()
|
||||
}
|
||||
|
||||
usersToSet = map[string]schema.User{
|
||||
userName: user,
|
||||
}
|
||||
}
|
||||
|
||||
cloudConfig := schema.YipConfig{Name: "Config generated by the installer",
|
||||
Stages: map[string][]schema.Stage{stage: {
|
||||
{
|
||||
Users: usersToSet,
|
||||
},
|
||||
}}}
|
||||
|
||||
// This is temporal to generate a valid cc file, no need to properly initialize everything
|
||||
cc := &config.Config{
|
||||
Install: &config.Install{
|
||||
Device: device,
|
||||
},
|
||||
}
|
||||
|
||||
var cloudConfig schema.YipConfig
|
||||
|
||||
// Only add the user stage if we have any users
|
||||
if userName != "" {
|
||||
var isAdmin []string
|
||||
|
||||
if isYes(makeAdmin) {
|
||||
isAdmin = append(isAdmin, "admin")
|
||||
}
|
||||
|
||||
user := schema.User{
|
||||
Name: userName,
|
||||
PasswordHash: userPassword,
|
||||
Groups: isAdmin,
|
||||
SSHAuthorizedKeys: sshUsers,
|
||||
}
|
||||
|
||||
stage := config.NetworkStage.String()
|
||||
// If we got no ssh keys, we don't need network, do the user as soon as possible
|
||||
if len(sshUsers) == 0 {
|
||||
stage = config.InitramfsStage.String()
|
||||
}
|
||||
|
||||
cloudConfig = schema.YipConfig{Name: "Config generated by the installer",
|
||||
Stages: map[string][]schema.Stage{stage: {
|
||||
{
|
||||
Users: map[string]schema.User{
|
||||
userName: user,
|
||||
},
|
||||
},
|
||||
}}}
|
||||
} else {
|
||||
// If no users, we need to set this option to skip the user validation and confirm that we want a system with no users.
|
||||
cc.Install.NoUsers = true
|
||||
}
|
||||
|
||||
// Merge all yamls into one
|
||||
dat, err := config.MergeYAML(cloudConfig, cc, result)
|
||||
if err != nil {
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
qr "github.com/kairos-io/go-nodepair/qrcode"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
"github.com/kairos-io/kairos-sdk/machine"
|
||||
"github.com/kairos-io/kairos-sdk/utils"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/cmd"
|
||||
qr "github.com/mudler/go-nodepair/qrcode"
|
||||
"github.com/mudler/go-pluggable"
|
||||
"github.com/pterm/pterm"
|
||||
)
|
||||
|
@ -38,6 +38,10 @@ func reset(reboot, unattended, resetOem bool, dir ...string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cfg.CheckForUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Load the installation Config from the cloud-config data
|
||||
resetSpec, err := config.ReadResetSpecFromConfig(cfg)
|
||||
if err != nil {
|
||||
@ -65,6 +69,10 @@ func resetUki(reboot, unattended, resetOem bool, dir ...string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = cfg.CheckForUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Load the installation Config from the cloud-config data
|
||||
resetSpec, err := config.ReadUkiResetSpecFromConfig(cfg)
|
||||
if err != nil {
|
||||
|
@ -3,6 +3,7 @@ package agent
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
hook "github.com/kairos-io/kairos-agent/v2/internal/agent/hooks"
|
||||
@ -11,9 +12,9 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/bus"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
config "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/uki"
|
||||
internalutils "github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
k8sutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/k8s"
|
||||
events "github.com/kairos-io/kairos-sdk/bus"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/utils"
|
||||
@ -64,23 +65,44 @@ func ListNewerReleases(includePrereleases bool) ([]string, error) {
|
||||
return tagList.FullImages()
|
||||
}
|
||||
|
||||
// TODO: Check where force and preReleases is being used? They dont seem to be used anywhere?
|
||||
func Upgrade(
|
||||
source string, force, strictValidations bool, dirs []string, upgradeEntry string, preReleases bool) error {
|
||||
bus.Manager.Initialize()
|
||||
|
||||
fixedDirs := make([]string, len(dirs))
|
||||
// Check and fix dirs if we are under k8s, so we read the actual running system configs instead of only
|
||||
// the container configs
|
||||
// we can run it blindly as it will return an empty string if not under k8s
|
||||
hostdir := k8sutils.GetHostDirForK8s()
|
||||
for _, dir := range dirs {
|
||||
fixedDirs = append(fixedDirs, filepath.Join(hostdir, dir))
|
||||
}
|
||||
|
||||
if internalutils.UkiBootMode() == internalutils.UkiHDD {
|
||||
return upgradeUki(source, dirs, upgradeEntry, strictValidations)
|
||||
return upgradeUki(source, fixedDirs, upgradeEntry, strictValidations)
|
||||
} else {
|
||||
return upgrade(source, force, strictValidations, dirs, upgradeEntry, preReleases)
|
||||
return upgrade(source, fixedDirs, upgradeEntry, strictValidations)
|
||||
}
|
||||
}
|
||||
|
||||
func upgrade(source string, force, strictValidations bool, dirs []string, upgradeEntry string, preReleases bool) error {
|
||||
upgradeSpec, c, err := generateUpgradeSpec(source, force, strictValidations, dirs, upgradeEntry, preReleases)
|
||||
func upgrade(sourceImageURL string, dirs []string, upgradeEntry string, strictValidations bool) error {
|
||||
c, err := getConfig(sourceImageURL, dirs, upgradeEntry, strictValidations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
err = c.CheckForUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the upgrade Config from the system
|
||||
upgradeSpec, err := config.ReadUpgradeSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = upgradeSpec.Sanitize()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -96,6 +118,55 @@ func upgrade(source string, force, strictValidations bool, dirs []string, upgrad
|
||||
return hook.Run(*c, upgradeSpec, hook.AfterUpgrade...)
|
||||
}
|
||||
|
||||
func upgradeUki(sourceImageURL string, dirs []string, upgradeEntry string, strictValidations bool) error {
|
||||
c, err := getConfig(sourceImageURL, dirs, upgradeEntry, strictValidations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
err = c.CheckForUsers()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Load the upgrade Config from the system
|
||||
upgradeSpec, err := config.ReadUkiUpgradeSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = upgradeSpec.Sanitize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
upgradeAction := uki.NewUpgradeAction(c, upgradeSpec)
|
||||
|
||||
err = upgradeAction.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hook.Run(*c, upgradeSpec, hook.AfterUpgrade...)
|
||||
}
|
||||
|
||||
func getConfig(sourceImageURL string, dirs []string, upgradeEntry string, strictValidations bool) (*config.Config, error) {
|
||||
cliConf, err := generateUpgradeConfForCLIArgs(sourceImageURL, upgradeEntry)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c, err := config.Scan(collector.Directories(dirs...),
|
||||
collector.Readers(strings.NewReader(cliConf)),
|
||||
collector.StrictValidation(strictValidations))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return c, err
|
||||
|
||||
}
|
||||
|
||||
func allReleases() (versioneer.TagList, error) {
|
||||
artifact, err := versioneer.NewArtifactFromOSRelease()
|
||||
if err != nil {
|
||||
@ -155,30 +226,6 @@ func generateUpgradeConfForCLIArgs(source, upgradeEntry string) (string, error)
|
||||
return string(d), err
|
||||
}
|
||||
|
||||
func generateUpgradeSpec(sourceImageURL string, force, strictValidations bool, dirs []string, upgradeEntry string, preReleases bool) (*v1.UpgradeSpec, *config.Config, error) {
|
||||
cliConf, err := generateUpgradeConfForCLIArgs(sourceImageURL, upgradeEntry)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
c, err := config.Scan(collector.Directories(dirs...),
|
||||
collector.Readers(strings.NewReader(cliConf)),
|
||||
collector.StrictValidation(strictValidations))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
// Load the upgrade Config from the system
|
||||
upgradeSpec, err := config.ReadUpgradeSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
return upgradeSpec, c, nil
|
||||
}
|
||||
|
||||
func getReleasesFromProvider(includePrereleases bool) ([]string, error) {
|
||||
var result []string
|
||||
bus.Manager.Response(events.EventAvailableReleases, func(p *pluggable.Plugin, r *pluggable.EventResponse) {
|
||||
@ -199,42 +246,6 @@ func getReleasesFromProvider(includePrereleases bool) ([]string, error) {
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func upgradeUki(source string, dirs []string, upgradeEntry string, strictValidations bool) error {
|
||||
cliConf, err := generateUpgradeConfForCLIArgs(source, upgradeEntry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c, err := config.Scan(collector.Directories(dirs...),
|
||||
collector.Readers(strings.NewReader(cliConf)),
|
||||
collector.StrictValidation(strictValidations))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
utils.SetEnv(c.Env)
|
||||
|
||||
// Load the upgrade Config from the system
|
||||
upgradeSpec, err := config.ReadUkiUpgradeSpecFromConfig(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = upgradeSpec.Sanitize()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
upgradeAction := uki.NewUpgradeAction(c, upgradeSpec)
|
||||
|
||||
err = upgradeAction.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hook.Run(*c, upgradeSpec, hook.AfterUpgrade...)
|
||||
}
|
||||
|
||||
// ExtraConfigUpgrade is the struct that holds the upgrade options that come from flags and events
|
||||
type ExtraConfigUpgrade struct {
|
||||
Upgrade struct {
|
||||
|
2195
internal/webui/public/package-lock.json
generated
2195
internal/webui/public/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -129,10 +129,16 @@ func selectBootEntrySystemd(cfg *config.Config, entry string) error {
|
||||
}
|
||||
}
|
||||
}
|
||||
bootName, err := bootNameToSystemdConf(entry)
|
||||
bootFileName, err := bootNameToSystemdConf(entry)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
assessment, err := utils.ReadAssessmentFromEntry(cfg.Fs, bootFileName, cfg.Logger)
|
||||
if err != nil {
|
||||
cfg.Logger.Logger.Err(err).Str("entry", entry).Str("boot file name", bootFileName).Msg("could not read assessment from entry")
|
||||
return err
|
||||
}
|
||||
bootName := fmt.Sprintf("%s%s.conf", bootFileName, assessment)
|
||||
// Set the default entry to the selected entry
|
||||
systemdConf["default"] = bootName
|
||||
err = utils.SystemdBootConfWriter(cfg.Fs, filepath.Join(efiPartition.MountPoint, "loader/loader.conf"), systemdConf)
|
||||
@ -173,6 +179,10 @@ func systemdConfToBootName(conf string) (string, error) {
|
||||
|
||||
fileName := strings.TrimSuffix(conf, ".conf")
|
||||
|
||||
// Remove the boot assesment from the name we show
|
||||
re := regexp.MustCompile(`\+\d+(-\d+)?$`)
|
||||
fileName = re.ReplaceAllString(fileName, "")
|
||||
|
||||
if strings.HasPrefix(fileName, "active") {
|
||||
bootName := "cos"
|
||||
confName := strings.TrimPrefix(fileName, "active")
|
||||
@ -220,6 +230,8 @@ func systemdConfToBootName(conf string) (string, error) {
|
||||
return strings.ReplaceAll(fileName, "_", " "), nil
|
||||
}
|
||||
|
||||
// bootNameToSystemdConf converts a boot name to a systemd-boot conf file name
|
||||
// skips the .conf extension
|
||||
func bootNameToSystemdConf(name string) (string, error) {
|
||||
differenciator := ""
|
||||
|
||||
@ -227,38 +239,38 @@ func bootNameToSystemdConf(name string) (string, error) {
|
||||
if name != "cos" {
|
||||
differenciator = "_" + strings.TrimPrefix(name, "cos ")
|
||||
}
|
||||
return "active" + differenciator + ".conf", nil
|
||||
return "active" + differenciator, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "active") {
|
||||
if name != "active" {
|
||||
differenciator = "_" + strings.TrimPrefix(name, "active ")
|
||||
}
|
||||
return "active" + differenciator + ".conf", nil
|
||||
return "active" + differenciator, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "fallback") {
|
||||
if name != "fallback" {
|
||||
differenciator = "_" + strings.TrimPrefix(name, "fallback ")
|
||||
}
|
||||
return "passive" + differenciator + ".conf", nil
|
||||
return "passive" + differenciator, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "recovery") {
|
||||
if name != "recovery" {
|
||||
differenciator = "_" + strings.TrimPrefix(name, "recovery ")
|
||||
}
|
||||
return "recovery" + differenciator + ".conf", nil
|
||||
return "recovery" + differenciator, nil
|
||||
}
|
||||
|
||||
if strings.HasPrefix(name, "statereset") {
|
||||
if name != "statereset" {
|
||||
differenciator = "_" + strings.TrimPrefix(name, "statereset ")
|
||||
}
|
||||
return "statereset" + differenciator + ".conf", nil
|
||||
return "statereset" + differenciator, nil
|
||||
}
|
||||
|
||||
return strings.ReplaceAll(name, " ", "_") + ".conf", nil
|
||||
return strings.ReplaceAll(name, " ", "_"), nil
|
||||
}
|
||||
|
||||
// listBootEntriesSystemd lists the boot entries available in the systemd-boot config files
|
||||
|
@ -14,8 +14,8 @@ import (
|
||||
sdkTypes "github.com/kairos-io/kairos-sdk/types"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
@ -138,14 +138,42 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(err.Error()).To(ContainSubstring("does not exist"))
|
||||
})
|
||||
It("selects the boot entry in a default installation", func() {
|
||||
It("works without boot assessment", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/active.conf", []byte("title kairos\nefi /EFI/kairos/active.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/passive.conf", []byte("title kairos (fallback)\nefi /EFI/kairos/passive.efi\n"), os.ModePerm)
|
||||
err = fs.WriteFile("/efi/loader/loader.conf", []byte("default active.conf"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery.conf", []byte("title kairos recovery\nefi /EFI/kairos/recovery.efi\n"), os.ModePerm)
|
||||
|
||||
err = SelectBootEntry(config, "active")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/statereset.conf", []byte("title kairos state reset (auto)\nefi /EFI/kairos/statereset.efi\n"), os.ModePerm)
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active"))
|
||||
reader, err := utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("active.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
"/efi",
|
||||
"",
|
||||
syscall.MS_REMOUNT,
|
||||
"")).To(BeTrue())
|
||||
// Should have called a remount to make it RO
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
"/efi",
|
||||
"",
|
||||
syscall.MS_REMOUNT|syscall.MS_RDONLY,
|
||||
"")).To(BeTrue())
|
||||
})
|
||||
|
||||
It("selects the boot entry in a default installation", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/active+2-1.conf", []byte("title kairos\nefi /EFI/kairos/active.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/passive+3.conf", []byte("title kairos (fallback)\nefi /EFI/kairos/passive.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery+1-2.conf", []byte("title kairos recovery\nefi /EFI/kairos/recovery.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/statereset+2-1.conf", []byte("title kairos state reset (auto)\nefi /EFI/kairos/statereset.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/loader.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -155,7 +183,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to fallback"))
|
||||
reader, err := utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("passive.conf"))
|
||||
Expect(reader["default"]).To(Equal("passive+3.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -176,7 +204,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to recovery"))
|
||||
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("recovery.conf"))
|
||||
Expect(reader["default"]).To(Equal("recovery+1-2.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -197,7 +225,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to statereset"))
|
||||
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("statereset.conf"))
|
||||
Expect(reader["default"]).To(Equal("statereset+2-1.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -218,7 +246,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to cos"))
|
||||
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("active.conf"))
|
||||
Expect(reader["default"]).To(Equal("active+2-1.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -240,7 +268,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to active"))
|
||||
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("active.conf"))
|
||||
Expect(reader["default"]).To(Equal("active+2-1.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -260,7 +288,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
It("selects the boot entry in a extend-cmdline installation with boot branding", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/active_install-mode_awesomeos.conf", []byte("title awesomeos\nefi /EFI/kairos/active_install-mode_awesomeos.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/passive_install-mode_awesomeos.conf", []byte("title awesomeos (fallback)\nefi /EFI/kairos/passive_install-mode_awesomeos.efi\n"), os.ModePerm)
|
||||
err = fs.WriteFile("/efi/loader/entries/passive_install-mode_awesomeos+3.conf", []byte("title awesomeos (fallback)\nefi /EFI/kairos/passive_install-mode_awesomeos.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery_install-mode_awesomeos.conf", []byte("title awesomeos recovery\nefi /EFI/kairos/recovery_install-mode_awesomeos.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -274,7 +302,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to fallback"))
|
||||
reader, err := utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("passive_install-mode_awesomeos.conf"))
|
||||
Expect(reader["default"]).To(Equal("passive_install-mode_awesomeos+3.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -381,11 +409,11 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/active_foobar.conf", []byte("title Kairos\nefi /EFI/kairos/active_foobar.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/passive.conf", []byte("title Kairos (fallback)\nefi /EFI/kairos/passive.efi\n"), os.ModePerm)
|
||||
err = fs.WriteFile("/efi/loader/entries/passive+3.conf", []byte("title Kairos (fallback)\nefi /EFI/kairos/passive.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/passive_foobar.conf", []byte("title Kairos (fallback)\nefi /EFI/kairos/passive_foobar.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery.conf", []byte("title Kairos recovery\nefi /EFI/kairos/recovery.efi\n"), os.ModePerm)
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery+3.conf", []byte("title Kairos recovery\nefi /EFI/kairos/recovery.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/recovery_foobar.conf", []byte("title Kairos recovery\nefi /EFI/kairos/recovery_foobar.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
@ -393,7 +421,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/statereset_foobar.conf", []byte("title Kairos state reset (auto)\nefi /EFI/kairos/state_reset_foobar.efi\n"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/loader.conf", []byte(""), os.ModePerm)
|
||||
err = fs.WriteFile("/efi/loader/loader.conf", []byte("default active.conf"), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
err = SelectBootEntry(config, "fallback")
|
||||
@ -401,7 +429,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to fallback"))
|
||||
reader, err := utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("passive.conf"))
|
||||
Expect(reader["default"]).To(Equal("passive+3.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
@ -443,7 +471,7 @@ var _ = Describe("Bootentries tests", Label("bootentry"), func() {
|
||||
Expect(memLog.String()).To(ContainSubstring("Default boot entry set to recovery"))
|
||||
reader, err = utils.SystemdBootConfReader(fs, "/efi/loader/loader.conf")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(reader["default"]).To(Equal("recovery.conf"))
|
||||
Expect(reader["default"]).To(Equal("recovery+3.conf"))
|
||||
// Should have called a remount to make it RW
|
||||
Expect(syscallMock.WasMountCalledWith(
|
||||
"",
|
||||
|
@ -9,8 +9,8 @@ import (
|
||||
sdkTypes "github.com/kairos-io/kairos-sdk/types"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
@ -38,8 +38,8 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Install action tests", func() {
|
||||
|
@ -199,6 +199,16 @@ func (r ResetAction) Run() (err error) {
|
||||
// Create extra dirs in rootfs as afterwards this will be impossible due to RO system
|
||||
createExtraDirsInRootfs(r.cfg, r.spec.ExtraDirsRootfs, r.spec.Active.MountPoint)
|
||||
|
||||
// Mount EFI partition before installing grub as under EFI this copies stuff in there
|
||||
if r.spec.Efi {
|
||||
err = e.MountPartition(r.spec.Partitions.EFI)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cleanup.Push(func() error { return e.UnmountPartition(r.spec.Partitions.EFI) })
|
||||
}
|
||||
//TODO: does bios needs to be mounted here?
|
||||
|
||||
// install grub
|
||||
grub := utils.NewGrub(r.cfg)
|
||||
err = grub.Install(
|
||||
|
@ -20,23 +20,20 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
ghwMock "github.com/kairos-io/kairos-sdk/ghw/mocks"
|
||||
sdkTypes "github.com/kairos-io/kairos-sdk/types"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Reset action tests", func() {
|
||||
@ -159,76 +156,82 @@ var _ = Describe("Reset action tests", func() {
|
||||
_, err = fs.Create(grubCfg)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
runner.SideEffect = func(cmd string, args ...string) ([]byte, error) {
|
||||
regexCmd := regexp.MustCompile(cmdFail)
|
||||
if cmdFail != "" && regexCmd.MatchString(cmd) {
|
||||
return []byte{}, errors.New("command failed")
|
||||
}
|
||||
return []byte{}, nil
|
||||
// create the fake grub dir with modules, it needs an arch in the path
|
||||
Expect(fsutils.MkdirAll(fs, filepath.Join(spec.Active.MountPoint, constants.Archx86), constants.DirPerm)).ToNot(HaveOccurred())
|
||||
for _, mod := range constants.GetGrubModules() {
|
||||
_, err = fs.Create(filepath.Join(spec.Active.MountPoint, constants.Archx86, mod))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
}
|
||||
|
||||
// create fake shim
|
||||
Expect(fsutils.MkdirAll(fs, filepath.Join(spec.Active.MountPoint, "/usr/share/efi/x86_64/"), constants.DirPerm)).ToNot(HaveOccurred())
|
||||
_, err = fs.Create(filepath.Join(spec.Active.MountPoint, "/usr/share/efi/x86_64/", "shim.efi"))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
// create fake grub
|
||||
Expect(fsutils.MkdirAll(fs, filepath.Join(spec.Active.MountPoint, "/usr/share/efi/x86_64/"), constants.DirPerm)).ToNot(HaveOccurred())
|
||||
_, err = fs.Create(filepath.Join(spec.Active.MountPoint, "/usr/share/efi/x86_64/", "grub.efi"))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
reset = action.NewResetAction(config, spec)
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
Describe("With EFI", func() {
|
||||
It("Successfully resets on non-squashfs recovery", func() {
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets on non-squashfs recovery including persistent data", func() {
|
||||
spec.FormatPersistent = true
|
||||
spec.FormatOEM = true
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets from a squashfs recovery image", Label("channel"), func() {
|
||||
err := fsutils.MkdirAll(config.Fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
spec.Active.Source = v1.NewDirSrc(constants.IsoBaseTree)
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets despite having errors on hooks", func() {
|
||||
cloudInit.Error = true
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets from a docker image", Label("docker"), func() {
|
||||
spec.Active.Source = v1.NewDockerSrc("my/image:latest")
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
|
||||
It("Successfully resets on non-squashfs recovery", func() {
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets on non-squashfs recovery including persistent data", func() {
|
||||
spec.FormatPersistent = true
|
||||
spec.FormatOEM = true
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets from a squashfs recovery image", Label("channel"), func() {
|
||||
err := fsutils.MkdirAll(config.Fs, constants.IsoBaseTree, constants.DirPerm)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
spec.Active.Source = v1.NewDirSrc(constants.IsoBaseTree)
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets despite having errors on hooks", func() {
|
||||
cloudInit.Error = true
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
})
|
||||
It("Successfully resets from a docker image", Label("docker"), func() {
|
||||
spec.Active.Source = v1.NewDockerSrc("my/image:latest")
|
||||
Expect(reset.Run()).To(BeNil())
|
||||
|
||||
})
|
||||
It("Fails installing grub", func() {
|
||||
cmdFail = utils.FindCommand("grub2-install", []string{"grub2-install", "grub-install"})
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
Expect(runner.IncludesCmds([][]string{{cmdFail}}))
|
||||
})
|
||||
It("Fails formatting state partition", func() {
|
||||
cmdFail = "mkfs.ext4"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
Expect(runner.IncludesCmds([][]string{{"mkfs.ext4"}}))
|
||||
})
|
||||
It("Fails setting the active label on non-squashfs recovery", func() {
|
||||
cmdFail = "tune2fs"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails setting the passive label on squashfs recovery", func() {
|
||||
cmdFail = "tune2fs"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
Expect(runner.IncludesCmds([][]string{{"tune2fs"}}))
|
||||
})
|
||||
It("Fails mounting partitions", func() {
|
||||
mounter.ErrorOnMount = true
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails unmounting partitions", func() {
|
||||
mounter.ErrorOnUnmount = true
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails unpacking docker image ", func() {
|
||||
spec.Active.Source = v1.NewDockerSrc("my/image:latest")
|
||||
extractor.SideEffect = func(imageRef, destination, platformRef string) error {
|
||||
return fmt.Errorf("error")
|
||||
}
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails formatting state partition", func() {
|
||||
cmdFail = "mkfs.ext4"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
Expect(runner.IncludesCmds([][]string{{"mkfs.ext4"}}))
|
||||
})
|
||||
It("Fails setting the active label on non-squashfs recovery", func() {
|
||||
cmdFail = "tune2fs"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails setting the passive label on squashfs recovery", func() {
|
||||
cmdFail = "tune2fs"
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
Expect(runner.IncludesCmds([][]string{{"tune2fs"}}))
|
||||
})
|
||||
It("Fails mounting partitions", func() {
|
||||
mounter.ErrorOnMount = true
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails unmounting partitions", func() {
|
||||
mounter.ErrorOnUnmount = true
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
It("Fails unpacking docker image ", func() {
|
||||
spec.Active.Source = v1.NewDockerSrc("my/image:latest")
|
||||
extractor.SideEffect = func(imageRef, destination, platformRef string) error {
|
||||
return fmt.Errorf("error")
|
||||
}
|
||||
Expect(reset.Run()).NotTo(BeNil())
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -18,27 +18,22 @@ package action_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/internal/agent"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/action"
|
||||
agentConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
ghwMock "github.com/kairos-io/kairos-sdk/ghw/mocks"
|
||||
sdkTypes "github.com/kairos-io/kairos-sdk/types"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Upgrade Actions test", func() {
|
||||
@ -55,10 +50,8 @@ var _ = Describe("Upgrade Actions test", func() {
|
||||
var ghwTest ghwMock.GhwMock
|
||||
var extractor *v1mock.FakeImageExtractor
|
||||
var dummySourceFile string
|
||||
var dummySourceSizeMb int64
|
||||
|
||||
BeforeEach(func() {
|
||||
dummySourceSizeMb = 20
|
||||
runner = v1mock.NewFakeRunner()
|
||||
syscall = &v1mock.FakeSyscall{}
|
||||
mounter = v1mock.NewErrorMounter()
|
||||
@ -153,34 +146,6 @@ var _ = Describe("Upgrade Actions test", func() {
|
||||
AfterEach(func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("calculates the recovery source size correctly", func() {
|
||||
dummySourceFile = createDummyFile(fs, dummySourceSizeMb)
|
||||
upgradeConfig := agent.ExtraConfigUpgrade{}
|
||||
upgradeConfig.Upgrade.Entry = constants.BootEntryRecovery
|
||||
upgradeConfig.Upgrade.RecoverySystem.URI = fmt.Sprintf("file:%s", dummySourceFile)
|
||||
d, err := json.Marshal(upgradeConfig)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
cliConfig := string(d)
|
||||
|
||||
config, err := agentConfig.Scan(collector.Readers(strings.NewReader(cliConfig)))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
agentConfig.WithFs(fs)(config)
|
||||
agentConfig.WithRunner(runner)(config)
|
||||
agentConfig.WithLogger(logger)(config)
|
||||
agentConfig.WithMounter(mounter)(config)
|
||||
agentConfig.WithSyscall(syscall)(config)
|
||||
agentConfig.WithClient(client)(config)
|
||||
agentConfig.WithCloudInitRunner(cloudInit)(config)
|
||||
agentConfig.WithImageExtractor(extractor)(config)
|
||||
agentConfig.WithPlatform("linux/amd64")(config)
|
||||
config.ImageExtractor = extractor
|
||||
|
||||
spec, err = agentConfig.NewUpgradeSpec(config)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Entry).To(Equal(constants.BootEntryRecovery))
|
||||
Expect(spec.Recovery.Size).To(Equal(uint(100 + dummySourceSizeMb))) // We adding 100Mb on top
|
||||
})
|
||||
Describe(fmt.Sprintf("Booting from %s", constants.ActiveLabel), Label("active_label"), func() {
|
||||
var err error
|
||||
BeforeEach(func() {
|
||||
@ -659,25 +624,3 @@ var _ = Describe("Upgrade Actions test", func() {
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
func createDummyFile(fs vfs.FS, sizeMb int64) string {
|
||||
fileSize := int64(sizeMb * 1024 * 1024)
|
||||
|
||||
tmpFile, err := os.CreateTemp("", "dummyfile_*.tmp")
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
tmpName := tmpFile.Name()
|
||||
tmpFile.Close()
|
||||
os.RemoveAll(tmpName)
|
||||
|
||||
dir := filepath.Dir(tmpName)
|
||||
err = fs.Mkdir(dir, os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
f, err := fs.Create(tmpName)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
err = f.Truncate(fileSize)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
f.Close()
|
||||
|
||||
return tmpName
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import (
|
||||
"github.com/mudler/yip/pkg/executor"
|
||||
"github.com/mudler/yip/pkg/plugins"
|
||||
"github.com/mudler/yip/pkg/schema"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
)
|
||||
|
||||
type YipCloudInitRunner struct {
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
// Parted print sample output
|
||||
|
@ -23,7 +23,7 @@ import (
|
||||
yip "github.com/mudler/yip/pkg/schema"
|
||||
"github.com/sanity-io/litter"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"gopkg.in/yaml.v3"
|
||||
"k8s.io/mount-utils"
|
||||
)
|
||||
@ -55,10 +55,15 @@ type Install struct {
|
||||
ExtraPartitions sdkTypes.PartitionList `yaml:"extra-partitions,omitempty" mapstructure:"extra-partitions"`
|
||||
ExtraDirsRootfs []string `yaml:"extra-dirs-rootfs,omitempty" mapstructure:"extra-dirs-rootfs"`
|
||||
Force bool `yaml:"force,omitempty" mapstructure:"force"`
|
||||
NoUsers bool `yaml:"nousers,omitempty" mapstructure:"nousers"`
|
||||
}
|
||||
|
||||
func NewConfig(opts ...GenericOptions) *Config {
|
||||
log := sdkTypes.NewKairosLogger("agent", "info", false)
|
||||
// Get the viper config in case something in command line or env var has set it and set the level asap
|
||||
if viper.GetBool("debug") {
|
||||
log.SetLevel("debug")
|
||||
}
|
||||
|
||||
hostPlatform, err := v1.NewPlatformFromArch(runtime.GOARCH)
|
||||
if err != nil {
|
||||
@ -150,6 +155,8 @@ type Config struct {
|
||||
SquashFsCompressionConfig []string `yaml:"squash-compression,omitempty" mapstructure:"squash-compression"`
|
||||
SquashFsNoCompression bool `yaml:"squash-no-compression,omitempty" mapstructure:"squash-no-compression"`
|
||||
UkiMaxEntries int `yaml:"uki-max-entries,omitempty" mapstructure:"uki-max-entries"`
|
||||
BindPCRs []string `yaml:"bind-pcrs,omitempty" mapstructure:"bind-pcrs"`
|
||||
BindPublicPCRs []string `yaml:"bind-public-pcrs,omitempty" mapstructure:"bind-public-pcrs"`
|
||||
}
|
||||
|
||||
// WriteInstallState writes the state.yaml file to the given state and recovery paths
|
||||
@ -188,6 +195,54 @@ func (c Config) LoadInstallState() (*v1.InstallState, error) {
|
||||
return installState, nil
|
||||
}
|
||||
|
||||
func contains(s []string, str string) bool {
|
||||
for _, v := range s {
|
||||
if v == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckForUsers will check the config for any users and validate that at least we have 1 admin.
|
||||
// Since Kairos 3.3.x we don't ship a default user with the system, so before a system with no specific users
|
||||
// was relying in our default cloud-configs which created a kairos user ALWAYS (with SUDO!)
|
||||
// But now we don't ship it anymore. So a user upgrading from 3.2.x to 3.3.x that created no users, will end up with a blocked
|
||||
// system.
|
||||
// So we need to see if they are setting a user in their config and if not refuse to continue
|
||||
func (c Config) CheckForUsers() (err error) {
|
||||
// If nousers is enabled we do not check for the validity of the users and such
|
||||
// At this point, the config should be fully parsed and the yip stages ready
|
||||
if !c.Install.NoUsers {
|
||||
anyAdmin := false
|
||||
cc, _ := c.Config.String()
|
||||
yamlConfig, err := yip.Load(cc, vfs.OSFS, nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, stage := range yamlConfig.Stages {
|
||||
for _, x := range stage {
|
||||
if len(x.Users) > 0 {
|
||||
for _, user := range x.Users {
|
||||
if contains(user.Groups, "admin") || user.PrimaryGroup == "admin" {
|
||||
anyAdmin = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if !anyAdmin {
|
||||
return fmt.Errorf("No users found in any stage that are part of the 'admin' group.\n" +
|
||||
"In Kairos 3.3.x we no longer ship a default hardcoded user with the system configs and require users to provide their own user." +
|
||||
"Please provide at least 1 user that is part of the 'admin' group(for sudo) with your cloud configs." +
|
||||
"If you still want to continue without creating any users in the system, set 'install.nousers: true' to be in the config in order to allow a system with no users.")
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// Sanitize checks the consistency of the struct, returns error
|
||||
// if unsolvable inconsistencies are found
|
||||
func (c *Config) Sanitize() error {
|
||||
@ -339,10 +394,11 @@ func FilterKeys(d []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// ScanNoLogs is a wrapper around Scan that sets the logger to null
|
||||
// Also sets the NoLogs option to true by default
|
||||
func ScanNoLogs(opts ...collector.Option) (c *Config, err error) {
|
||||
log := sdkTypes.NewNullLogger()
|
||||
result := NewConfig(WithLogger(log))
|
||||
return scan(result, opts...)
|
||||
return scan(result, append(opts, collector.NoLogs)...)
|
||||
}
|
||||
|
||||
// Scan is a wrapper around collector.Scan that sets the logger to the default Kairos logger
|
||||
|
@ -22,12 +22,13 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
pkgConfig "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
v1mocks "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
. "github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
@ -93,7 +94,7 @@ func structFieldsContainedInOtherStruct(left, right interface{}) {
|
||||
leftFieldName := leftTypes.Field(i).Name
|
||||
if leftTypes.Field(i).IsExported() {
|
||||
It(fmt.Sprintf("Checks that the new schema contians the field %s", leftFieldName), func() {
|
||||
if leftFieldName == "Source" {
|
||||
if leftFieldName == "Source" || leftFieldName == "NoUsers" || leftFieldName == "BindPublicPCRs" || leftFieldName == "BindPCRs" {
|
||||
Skip("Schema not updated yet")
|
||||
}
|
||||
Expect(
|
||||
@ -227,7 +228,7 @@ var _ = Describe("Schema", func() {
|
||||
cleanup()
|
||||
})
|
||||
It("Scan can override options", func() {
|
||||
c, err := Scan(collector.Readers(strings.NewReader(`uki-max-entries: 34`)), collector.NoLogs)
|
||||
c, err := ScanNoLogs(collector.Readers(strings.NewReader(`uki-max-entries: 34`)))
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(c.UkiMaxEntries).To(Equal(34))
|
||||
})
|
||||
@ -265,4 +266,40 @@ var _ = Describe("Schema", func() {
|
||||
Expect(err).Should(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("Validate users in config", func() {
|
||||
It("Validates a existing user in the system", func() {
|
||||
cc := `#cloud-config
|
||||
stages:
|
||||
initramfs:
|
||||
- name: "Set user and password"
|
||||
users:
|
||||
kairos:
|
||||
passwd: "kairos"
|
||||
groups:
|
||||
- "admin"
|
||||
`
|
||||
config, err := pkgConfig.ScanNoLogs(collector.Readers(strings.NewReader(cc)))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(config.CheckForUsers()).ToNot(HaveOccurred())
|
||||
})
|
||||
It("Fails if there is no user", func() {
|
||||
config, err := pkgConfig.ScanNoLogs(collector.NoLogs)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(config.CheckForUsers()).To(HaveOccurred())
|
||||
})
|
||||
It("Fails if there is user but its not admin", func() {
|
||||
cc := `#cloud-config
|
||||
stages:
|
||||
initramfs:
|
||||
- name: "Set user and password"
|
||||
users:
|
||||
kairos:
|
||||
passwd: "kairos"
|
||||
`
|
||||
config, err := pkgConfig.ScanNoLogs(collector.Readers(strings.NewReader(cc)))
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(config.CheckForUsers()).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -27,6 +27,7 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
fsutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
k8sutils "github.com/kairos-io/kairos-agent/v2/pkg/utils/k8s"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"github.com/kairos-io/kairos-sdk/collector"
|
||||
"github.com/kairos-io/kairos-sdk/ghw"
|
||||
@ -402,6 +403,14 @@ func NewUpgradeSpec(cfg *Config) (*v1.UpgradeSpec, error) {
|
||||
func setUpgradeSourceSize(cfg *Config, spec *v1.UpgradeSpec) error {
|
||||
var size int64
|
||||
var err error
|
||||
var originalSize uint
|
||||
|
||||
// Store the default given size in the spec. This includes the user specified values which have already been marshalled in the spec
|
||||
if spec.RecoveryUpgrade() {
|
||||
originalSize = spec.Recovery.Size
|
||||
} else {
|
||||
originalSize = spec.Active.Size
|
||||
}
|
||||
|
||||
var targetSpec *v1.Image
|
||||
if spec.RecoveryUpgrade() {
|
||||
@ -411,16 +420,25 @@ func setUpgradeSourceSize(cfg *Config, spec *v1.UpgradeSpec) error {
|
||||
}
|
||||
|
||||
if targetSpec.Source != nil && targetSpec.Source.IsEmpty() {
|
||||
cfg.Logger.Debugf("No source specified for image, skipping size calculation")
|
||||
return nil
|
||||
}
|
||||
|
||||
size, err = GetSourceSize(cfg, targetSpec.Source)
|
||||
if err != nil {
|
||||
cfg.Logger.Warnf("Failed to infer size for images: %s", err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
cfg.Logger.Infof("Setting image size to %dMb", size)
|
||||
targetSpec.Size = uint(size)
|
||||
if uint(size) < originalSize {
|
||||
cfg.Logger.Debugf("Calculated size (%dMB) is less than specified/default size (%dMB)", size, originalSize)
|
||||
targetSpec.Size = originalSize
|
||||
} else {
|
||||
cfg.Logger.Debugf("Calculated size (%dMB) is higher than specified/default size (%dMB)", size, originalSize)
|
||||
targetSpec.Size = uint(size)
|
||||
}
|
||||
|
||||
cfg.Logger.Infof("Setting image size to %dMB", targetSpec.Size)
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -788,7 +806,7 @@ func ReadUkiUpgradeSpecFromConfig(c *Config) (*v1.UpgradeUkiSpec, error) {
|
||||
// getSize will calculate the size of a file or symlink and will do nothing with directories
|
||||
// fileList: keeps track of the files visited to avoid counting a file more than once if it's a symlink. It could also be used as a way to filter some files
|
||||
// size: will be the memory that adds up all the files sizes. Meaning it could be initialized with a value greater than 0 if needed.
|
||||
func getSize(size *int64, fileList map[string]bool, path string, d fs.DirEntry, err error) error {
|
||||
func getSize(vfs v1.FS, size *int64, fileList map[string]bool, path string, d fs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -801,7 +819,7 @@ func getSize(size *int64, fileList map[string]bool, path string, d fs.DirEntry,
|
||||
if d.Type()&fs.ModeSymlink != 0 {
|
||||
// If it's a symlink, get its target and calculate its size.
|
||||
var err error
|
||||
actualFilePath, err = os.Readlink(path)
|
||||
actualFilePath, err = vfs.Readlink(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -812,7 +830,7 @@ func getSize(size *int64, fileList map[string]bool, path string, d fs.DirEntry,
|
||||
}
|
||||
}
|
||||
|
||||
fileInfo, err := os.Stat(actualFilePath)
|
||||
fileInfo, err := vfs.Stat(actualFilePath)
|
||||
if os.IsNotExist(err) || fileList[actualFilePath] {
|
||||
return nil
|
||||
}
|
||||
@ -849,17 +867,11 @@ func GetSourceSize(config *Config, source *v1.ImageSource) (int64, error) {
|
||||
// , which mounts the host root into $HOST_DIR
|
||||
// we should skip that dir when calculating the size as we would be doubling the calculated size
|
||||
// Plus we will hit the usual things when checking a running system. Processes that go away, tmpfiles, etc...
|
||||
|
||||
// This is always set for pods running under kubernetes
|
||||
_, underKubernetes := os.LookupEnv("KUBERNETES_SERVICE_HOST")
|
||||
config.Logger.Logger.Info().Bool("status", underKubernetes).Msg("Running under kubernetes")
|
||||
// Try to get the HOST_DIR in case we are not using the default one
|
||||
hostDir := os.Getenv("HOST_DIR")
|
||||
// If we are under kubernetes but the HOST_DIR var is empty, default to /host as system-upgrade-controller mounts
|
||||
// the host in that dir by default
|
||||
if underKubernetes && hostDir == "" {
|
||||
hostDir = "/host"
|
||||
}
|
||||
hostDir := k8sutils.GetHostDirForK8s()
|
||||
config.Logger.Logger.Debug().Bool("status", underKubernetes).Str("hostdir", hostDir).Msg("Kubernetes check")
|
||||
err = fsutils.WalkDirFs(config.Fs, source.Value(), func(path string, d fs.DirEntry, err error) error {
|
||||
// If its empty we are just not setting it, so probably out of the k8s upgrade path
|
||||
if hostDir != "" && strings.HasPrefix(path, hostDir) {
|
||||
@ -870,7 +882,7 @@ func GetSourceSize(config *Config, source *v1.ImageSource) (int64, error) {
|
||||
// During install or upgrade outside kubernetes, we dont care about those dirs as they are not expected to be in the source dir
|
||||
config.Logger.Logger.Debug().Str("path", path).Str("hostDir", hostDir).Msg("Skipping dir as it is a runtime directory under kubernetes (/proc, /dev or /run)")
|
||||
} else {
|
||||
v := getSize(&size, filesVisited, path, d, err)
|
||||
v := getSize(config.Fs, &size, filesVisited, path, d, err)
|
||||
return v
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"bytes"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/config"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
@ -33,7 +34,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
"k8s.io/mount-utils"
|
||||
)
|
||||
|
||||
@ -449,6 +450,45 @@ var _ = Describe("Types", Label("types", "config"), func() {
|
||||
Expect(spec.Recovery.Source.IsEmpty()).To(BeTrue())
|
||||
Expect(spec.Recovery.FS).To(Equal(constants.SquashFs))
|
||||
})
|
||||
|
||||
It("sets image size to default value if not set", func() {
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Size).To(Equal(constants.ImgSize))
|
||||
})
|
||||
|
||||
It("sets image size to provided value if set in the config and image is smaller", func() {
|
||||
cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n size: 666\n")))
|
||||
// Set manually the config collector in the cfg file before unmarshalling the spec
|
||||
c.Config = cfg.Config
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Size).To(Equal(uint(666)))
|
||||
})
|
||||
It("sets image size to default value if not set in the config and image is smaller", func() {
|
||||
cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n uri: dir:/\n")))
|
||||
// Set manually the config collector in the cfg file before unmarshalling the spec
|
||||
c.Config = cfg.Config
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
Expect(spec.Active.Size).To(Equal(constants.ImgSize))
|
||||
})
|
||||
|
||||
It("sets image size to the source if default is smaller", func() {
|
||||
cfg, err := config.ScanNoLogs(collector.Readers(strings.NewReader("#cloud-config\nupgrade:\n system:\n uri: file:/tmp/waka\n")))
|
||||
// Set manually the config collector in the cfg file before unmarshalling the spec
|
||||
c.Config = cfg.Config
|
||||
Expect(c.Fs.Mkdir("/tmp", 0777)).ShouldNot(HaveOccurred())
|
||||
Expect(c.Fs.WriteFile("/tmp/waka", []byte("waka"), 0777)).ShouldNot(HaveOccurred())
|
||||
Expect(c.Fs.Truncate("/tmp/waka", 5120*1024*1024)).ShouldNot(HaveOccurred())
|
||||
spec, err := config.NewUpgradeSpec(c)
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
f, err := c.Fs.Stat("/tmp/waka")
|
||||
Expect(err).ShouldNot(HaveOccurred())
|
||||
// Make the same calculation as the code
|
||||
Expect(spec.Active.Size).To(Equal(uint(f.Size()/1000/1000) + 100))
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
Describe("Config from cloudconfig", Label("cloud-config"), func() {
|
||||
@ -703,7 +743,8 @@ var _ = Describe("GetSourceSize", Label("GetSourceSize"), func() {
|
||||
|
||||
Expect(os.Mkdir(filepath.Join(tempDir, "host"), os.ModePerm)).ToNot(HaveOccurred())
|
||||
Expect(createFileOfSizeInMB(filepath.Join(tempDir, "host", "what.txt"), 200)).ToNot(HaveOccurred())
|
||||
// Set env var like the suc upgrade does
|
||||
// Set env var like the suc upgrade and k8s does to trigger the skip
|
||||
Expect(os.Setenv("KUBERNETES_SERVICE_HOST", "10.0.0.1")).ToNot(HaveOccurred())
|
||||
Expect(os.Setenv("HOST_DIR", filepath.Join(tempDir, "host"))).ToNot(HaveOccurred())
|
||||
|
||||
sizeAfter, err := config.GetSourceSize(conf, imageSource)
|
||||
|
@ -126,7 +126,9 @@ const (
|
||||
StateResetBootSuffix = " state reset (auto)"
|
||||
|
||||
// Error
|
||||
UpgradeNoSourceError = "Could not find a proper source for the upgrade.\nThis can be configured in the cloud config files under the 'upgrade.system.uri' key or via cmdline using the '--source' flag."
|
||||
UpgradeNoSourceError = "Could not find a proper source for the upgrade.\nThis can be configured in the cloud config files under the 'upgrade.system.uri' key or via cmdline using the '--source' flag."
|
||||
MultipleEntriesAssessmentError = "multiple boot entries found for %s"
|
||||
NoBootAssessmentWarning = "No boot assessment found in current boot entry config file"
|
||||
)
|
||||
|
||||
func UkiDefaultMenuEntries() []string {
|
||||
|
@ -308,7 +308,23 @@ func (e Elemental) CreateFileSystemImage(img *v1.Image) error {
|
||||
|
||||
// DeployImage will deploy the given image into the target. This method
|
||||
// creates the filesystem image file, mounts it and unmounts it as needed.
|
||||
// Creates the default system dirs by default (/sys,/proc,/dev, etc...)
|
||||
func (e *Elemental) DeployImage(img *v1.Image, leaveMounted bool) (info interface{}, err error) {
|
||||
return e.deployImage(img, leaveMounted, true)
|
||||
}
|
||||
|
||||
// DeployImageNodirs will deploy the given image into the target. This method
|
||||
// creates the filesystem image file, mounts it and unmounts it as needed.
|
||||
// Does not create the default system dirs so it can be used to create generic images from any source
|
||||
func (e *Elemental) DeployImageNodirs(img *v1.Image, leaveMounted bool) (info interface{}, err error) {
|
||||
return e.deployImage(img, leaveMounted, false)
|
||||
}
|
||||
|
||||
// deployImage is the real function that does the actual work
|
||||
// Set leaveMounted to leave the image mounted, otherwise it unmounts before returning
|
||||
// Set createDirStructure to create the directory structure in the target, which creates the expected dirs
|
||||
// for a running system. This is so we can reuse this method for creating random images, not only system ones
|
||||
func (e *Elemental) deployImage(img *v1.Image, leaveMounted, createDirStructure bool) (info interface{}, err error) {
|
||||
target := img.MountPoint
|
||||
if !img.Source.IsFile() {
|
||||
if img.FS != cnst.SquashFs {
|
||||
@ -338,9 +354,11 @@ func (e *Elemental) DeployImage(img *v1.Image, leaveMounted bool) (info interfac
|
||||
return nil, err
|
||||
}
|
||||
if !img.Source.IsFile() {
|
||||
err = utils.CreateDirStructure(e.config.Fs, target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if createDirStructure {
|
||||
err = utils.CreateDirStructure(e.config.Fs, target)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if img.FS == cnst.SquashFs {
|
||||
squashOptions := append(cnst.GetDefaultSquashfsOptions(), e.config.SquashFsCompressionConfig...)
|
||||
|
@ -44,7 +44,7 @@ import (
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/sanity-io/litter"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
func TestElementalSuite(t *testing.T) {
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/google/go-github/v63/github"
|
||||
"github.com/google/go-github/v66/github"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
|
@ -24,9 +24,11 @@ func (d *Disk) NewPartitionTable(partType string, parts sdkTypes.PartitionList)
|
||||
switch partType {
|
||||
case v1.GPT:
|
||||
table = &gpt.Table{
|
||||
ProtectiveMBR: true,
|
||||
GUID: cnst.DiskUUID, // Set know predictable UUID
|
||||
Partitions: kairosPartsToDiskfsGPTParts(parts, d.Size),
|
||||
ProtectiveMBR: true,
|
||||
GUID: cnst.DiskUUID, // Set know predictable UUID
|
||||
Partitions: kairosPartsToDiskfsGPTParts(parts, d.Size, d.LogicalBlocksize),
|
||||
LogicalSectorSize: int(d.LogicalBlocksize),
|
||||
PhysicalSectorSize: int(d.PhysicalBlocksize),
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("invalid partition type: %s", partType)
|
||||
@ -39,11 +41,11 @@ func (d *Disk) NewPartitionTable(partType string, parts sdkTypes.PartitionList)
|
||||
return nil
|
||||
}
|
||||
|
||||
func getSectorEndFromSize(start, size uint64) uint64 {
|
||||
return (size / uint64(diskfs.SectorSize512)) + start - 1
|
||||
func getSectorEndFromSize(start, size uint64, sectorSize int64) uint64 {
|
||||
return (size / uint64(sectorSize)) + start - 1
|
||||
}
|
||||
|
||||
func kairosPartsToDiskfsGPTParts(parts sdkTypes.PartitionList, diskSize int64) []*gpt.Partition {
|
||||
func kairosPartsToDiskfsGPTParts(parts sdkTypes.PartitionList, diskSize int64, sectorSize int64) []*gpt.Partition {
|
||||
var partitions []*gpt.Partition
|
||||
for index, part := range parts {
|
||||
var start uint64
|
||||
@ -51,7 +53,7 @@ func kairosPartsToDiskfsGPTParts(parts sdkTypes.PartitionList, diskSize int64) [
|
||||
var size uint64
|
||||
if len(partitions) == 0 {
|
||||
// first partition, align to 1Mb
|
||||
start = 1024 * 1024 / uint64(diskfs.SectorSize512)
|
||||
start = 1024 * 1024 / uint64(sectorSize)
|
||||
} else {
|
||||
// get latest partition end, sum 1
|
||||
start = partitions[len(partitions)-1].End + 1
|
||||
@ -78,7 +80,7 @@ func kairosPartsToDiskfsGPTParts(parts sdkTypes.PartitionList, diskSize int64) [
|
||||
|
||||
}
|
||||
|
||||
end = getSectorEndFromSize(start, size)
|
||||
end = getSectorEndFromSize(start, size, sectorSize)
|
||||
|
||||
if part.Name == cnst.EfiPartName && part.FS == cnst.EfiFs {
|
||||
// EFI boot partition
|
||||
@ -127,7 +129,7 @@ func WithLogger(logger sdkTypes.KairosLogger) func(d *Disk) error {
|
||||
}
|
||||
|
||||
func NewDisk(device string, opts ...DiskOptions) (*Disk, error) {
|
||||
d, err := diskfs.Open(device, diskfs.WithSectorSize(512))
|
||||
d, err := diskfs.Open(device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ const (
|
||||
// ImageSource represents the source from where an image is created for easy identification
|
||||
type ImageSource struct {
|
||||
source string `yaml:"source"`
|
||||
srcType string
|
||||
srcType string `yaml:"type"`
|
||||
}
|
||||
|
||||
func (i ImageSource) Value() string {
|
||||
|
@ -37,4 +37,5 @@ type FS interface {
|
||||
OpenFile(name string, flag int, perm fs.FileMode) (*os.File, error)
|
||||
WriteFile(filename string, data []byte, perm os.FileMode) error
|
||||
Rename(oldpath, newpath string) error
|
||||
Truncate(name string, size int64) error
|
||||
}
|
||||
|
@ -166,3 +166,47 @@ func copyFile(src, dst string) error {
|
||||
|
||||
return destinationFile.Close()
|
||||
}
|
||||
|
||||
func AddSystemdConfSortKey(fs v1.FS, artifactDir string, log sdkTypes.KairosLogger) error {
|
||||
return fsutils.WalkDirFs(fs, artifactDir, func(path string, info os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Only do files that are conf files but dont match the loader.conf
|
||||
if !info.IsDir() && filepath.Ext(path) == ".conf" && !strings.Contains(info.Name(), "loader.conf") {
|
||||
log.Logger.Debug().Str("path", path).Msg("Adding sort key to file")
|
||||
conf, err := sdkutils.SystemdBootConfReader(path)
|
||||
if err != nil {
|
||||
log.Errorf("Error reading conf file to extract values %s: %s", conf, path)
|
||||
}
|
||||
// Now check and put the proper sort key
|
||||
var sortKey string
|
||||
// If we have 2 different files that start with active, like with the extra-cmdline, how do we set this?
|
||||
// Ideally if they both have the same sort key, they will be sorted by name so the single one will be first
|
||||
// and the extra-cmdline will be second. This is the best we can do currently without making this a mess
|
||||
// Maybe we need the bootentry command to also set the sort key somehow?
|
||||
switch {
|
||||
case strings.Contains(info.Name(), "active"):
|
||||
sortKey = "0001"
|
||||
case strings.Contains(info.Name(), "passive"):
|
||||
sortKey = "0002"
|
||||
case strings.Contains(info.Name(), "recovery"):
|
||||
sortKey = "0003"
|
||||
case strings.Contains(info.Name(), "statereset"):
|
||||
sortKey = "0004"
|
||||
default: // Anything that dont matches, goes to the bottom
|
||||
sortKey = "0010"
|
||||
}
|
||||
conf["sort-key"] = sortKey
|
||||
newContents := ""
|
||||
for k, v := range conf {
|
||||
newContents = fmt.Sprintf("%s%s %s\n", newContents, k, v)
|
||||
}
|
||||
log.Logger.Trace().Str("contents", litter.Sdump(conf)).Str("path", path).Msg("Final values for conf file")
|
||||
|
||||
return os.WriteFile(path, []byte(newContents), 0600)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ import (
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
var _ = Describe("Common functions tests", func() {
|
||||
|
@ -181,6 +181,18 @@ func (i *InstallAction) Run() (err error) {
|
||||
return fmt.Errorf("removing artifact set with role %s: %w", UnassignedArtifactRole, err)
|
||||
}
|
||||
|
||||
// add sort key to all files
|
||||
err = AddSystemdConfSortKey(i.cfg.Fs, i.spec.Partitions.EFI.MountPoint, i.cfg.Logger)
|
||||
if err != nil {
|
||||
i.cfg.Logger.Warnf("adding sort key: %s", err.Error())
|
||||
}
|
||||
|
||||
// Add boot assessment to files by appending +3 to the name
|
||||
err = utils.AddBootAssessment(i.cfg.Fs, i.spec.Partitions.EFI.MountPoint, i.cfg.Logger)
|
||||
if err != nil {
|
||||
i.cfg.Logger.Warnf("adding boot assesment: %s", err.Error())
|
||||
}
|
||||
|
||||
// SelectBootEntry sets the default boot entry to the selected entry
|
||||
err = action.SelectBootEntry(i.cfg, "cos")
|
||||
if err != nil {
|
||||
|
@ -80,6 +80,19 @@ func (r *ResetAction) Run() (err error) {
|
||||
r.cfg.Logger.Errorf("copying recovery to active: %s", err.Error())
|
||||
return fmt.Errorf("copying recovery to active: %w", err)
|
||||
}
|
||||
|
||||
// add sort key to all files
|
||||
err = AddSystemdConfSortKey(r.cfg.Fs, r.spec.Partitions.EFI.MountPoint, r.cfg.Logger)
|
||||
if err != nil {
|
||||
r.cfg.Logger.Warnf("adding sort key: %s", err.Error())
|
||||
}
|
||||
|
||||
// Add boot assessment to files by appending +3 to the name
|
||||
err = elementalUtils.AddBootAssessment(r.cfg.Fs, r.spec.Partitions.EFI.MountPoint, r.cfg.Logger)
|
||||
if err != nil {
|
||||
r.cfg.Logger.Warnf("adding boot assesment: %s", err.Error())
|
||||
}
|
||||
|
||||
// SelectBootEntry sets the default boot entry to the selected entry
|
||||
err = action.SelectBootEntry(r.cfg, "cos")
|
||||
// Should we fail? Or warn?
|
||||
|
@ -110,6 +110,17 @@ func (i *UpgradeAction) Run() (err error) {
|
||||
return fmt.Errorf("removing artifact set: %w", err)
|
||||
}
|
||||
|
||||
// add sort key to all files
|
||||
err = AddSystemdConfSortKey(i.cfg.Fs, i.spec.EfiPartition.MountPoint, i.cfg.Logger)
|
||||
if err != nil {
|
||||
i.cfg.Logger.Warnf("adding sort key: %s", err.Error())
|
||||
}
|
||||
|
||||
// Add boot assessment to files by appending +3 to the name
|
||||
err = elementalUtils.AddBootAssessment(i.cfg.Fs, i.spec.EfiPartition.MountPoint, i.cfg.Logger)
|
||||
if err != nil {
|
||||
i.cfg.Logger.Warnf("adding boot assesment: %s", err.Error())
|
||||
}
|
||||
// SelectBootEntry sets the default boot entry to the selected entry
|
||||
err = action.SelectBootEntry(i.cfg, "cos")
|
||||
// Should we fail? Or warn?
|
||||
|
@ -28,6 +28,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
@ -45,7 +46,7 @@ import (
|
||||
"github.com/joho/godotenv"
|
||||
cnst "github.com/kairos-io/kairos-agent/v2/pkg/constants"
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
)
|
||||
|
||||
func CommandExists(command string) bool {
|
||||
@ -614,3 +615,72 @@ func CheckFailedInstallation(stateFile string) (bool, error) {
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// AddBootAssessment adds boot assessment to files by appending +3 to the name
|
||||
// Only for files that dont have it already as those are the ones upgraded
|
||||
// Existing files that have a boot assessment will be left as is
|
||||
// This should be called during install, upgrade and reset
|
||||
// Mainly everything that updates the config files to point to a new artifact we need to reset the boot assessment
|
||||
// as its a new artifact that needs to be assessed
|
||||
func AddBootAssessment(fs v1.FS, artifactDir string, logger sdkTypes.KairosLogger) error {
|
||||
return fsutils.WalkDirFs(fs, artifactDir, func(path string, info os.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Only do files that are conf files but dont match the loader.conf
|
||||
if !info.IsDir() && filepath.Ext(path) == ".conf" && !strings.Contains(info.Name(), "loader.conf") {
|
||||
dir := filepath.Dir(path)
|
||||
ext := filepath.Ext(path)
|
||||
base := strings.TrimSuffix(filepath.Base(path), ext)
|
||||
// Lets check if the file has a boot assessment already. If it does, we dont need to do anything
|
||||
// If it matches continue
|
||||
re := regexp.MustCompile(`\+\d+(-\d+)?$`)
|
||||
if re.MatchString(base) {
|
||||
logger.Logger.Debug().Str("file", path).Msg("Boot assessment already present in file")
|
||||
return nil
|
||||
}
|
||||
newBase := fmt.Sprintf("%s+3%s", base, ext)
|
||||
newPath := filepath.Join(dir, newBase)
|
||||
logger.Logger.Debug().Str("from", path).Str("to", newPath).Msg("Enabling boot assessment")
|
||||
err = fs.Rename(path, newPath)
|
||||
if err != nil {
|
||||
logger.Logger.Err(err).Str("from", path).Str("to", newPath).Msg("Error renaming file")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func ReadAssessmentFromEntry(fs v1.FS, entry string, logger sdkTypes.KairosLogger) (string, error) {
|
||||
// Read current config for boot assessment from current config. We should already have the final config name
|
||||
// Fix fallback and cos pointing to passive and active
|
||||
if strings.HasPrefix(entry, "fallback") {
|
||||
entry = strings.Replace(entry, "fallback", "passive", 1)
|
||||
}
|
||||
if strings.HasPrefix(entry, "cos") {
|
||||
entry = strings.Replace(entry, "cos", "active", 1)
|
||||
}
|
||||
efiPart, err := partitions.GetEfiPartition(&logger)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// We only want the ones that match the assessment
|
||||
currentfile, err := fsutils.GlobFs(fs, filepath.Join(efiPart.MountPoint, "loader/entries", entry+"+*.conf"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(currentfile) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
if len(currentfile) > 1 {
|
||||
return "", fmt.Errorf(cnst.MultipleEntriesAssessmentError, entry)
|
||||
}
|
||||
re := regexp.MustCompile(`(\+\d+(-\d+)?)\.conf$`)
|
||||
if !re.MatchString(currentfile[0]) {
|
||||
logger.Logger.Debug().Str("file", currentfile[0]).Msg(cnst.NoBootAssessmentWarning)
|
||||
return "", nil
|
||||
}
|
||||
return re.FindStringSubmatch(currentfile[0])[1], nil
|
||||
}
|
||||
|
@ -33,8 +33,8 @@ import (
|
||||
"time"
|
||||
|
||||
v1 "github.com/kairos-io/kairos-agent/v2/pkg/types/v1"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
// DirSize returns the accumulated size of all files in folder
|
||||
@ -273,3 +273,38 @@ func Copy(fs v1.FS, src, dst string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GlobFs returns the names of all files matching pattern or nil if there is no matching file.
|
||||
// Only consider the names of files in the directory included in the pattern, not in subdirectories.
|
||||
// So the pattern "dir/*" will return only the files in the directory "dir", not in "dir/subdir".
|
||||
func GlobFs(fs v1.FS, pattern string) ([]string, error) {
|
||||
var matches []string
|
||||
|
||||
// Check if the pattern is well formed.
|
||||
if _, err := filepath.Match(pattern, ""); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Split the pattern into directory and file parts.
|
||||
dir, file := filepath.Split(pattern)
|
||||
if dir == "" {
|
||||
dir = "."
|
||||
}
|
||||
|
||||
// Read the directory.
|
||||
entries, err := fs.ReadDir(dir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Match the entries against the pattern.
|
||||
for _, entry := range entries {
|
||||
if matched, err := filepath.Match(file, entry.Name()); err != nil {
|
||||
return nil, err
|
||||
} else if matched {
|
||||
matches = append(matches, filepath.Join(dir, entry.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
return matches, nil
|
||||
}
|
||||
|
@ -46,6 +46,9 @@ func NewGrub(config *agentConfig.Config) *Grub {
|
||||
}
|
||||
|
||||
// Install installs grub into the device, copy the config file and add any extra TTY to grub
|
||||
// TODO: Make it more generic to be able to call it from other places
|
||||
// i.e.: filepath.Join(cnst.ActiveDir, "etc/kairos-release") seraches for the file in the active dir, we should be looking into the rootdir?
|
||||
// filepath.Join(cnst.EfiDir, "EFI/boot/grub.cfg") we also write into the efi dir directly, this should be the a var maybe?
|
||||
func (g Grub) Install(target, rootDir, bootDir, grubConf, tty string, efi bool, stateLabel string) (err error) { // nolint:gocyclo
|
||||
var grubargs []string
|
||||
var grubdir, finalContent string
|
||||
|
27
pkg/utils/k8s/common.go
Normal file
27
pkg/utils/k8s/common.go
Normal file
@ -0,0 +1,27 @@
|
||||
package k8s
|
||||
|
||||
import "os"
|
||||
|
||||
// GetHostDirForK8s returns the base dir where the system is
|
||||
// This is because under k8s, we mount the actual system under a dir
|
||||
// So we need to know which paths we need to read the configs from
|
||||
// if we read them from the root directly, we are actually reading the
|
||||
// configs of the upgrade container
|
||||
// If not found returns an empty string
|
||||
func GetHostDirForK8s() string {
|
||||
_, underKubernetes := os.LookupEnv("KUBERNETES_SERVICE_HOST")
|
||||
// Try to get the HOST_DIR in case we are not using the default one
|
||||
hostDirEnv := os.Getenv("HOST_DIR")
|
||||
// If we are under kubernetes but the HOST_DIR var is empty, default to /host as system-upgrade-controller mounts
|
||||
// the host in that dir by default
|
||||
if underKubernetes {
|
||||
if hostDirEnv != "" {
|
||||
return hostDirEnv
|
||||
} else {
|
||||
return "/host"
|
||||
}
|
||||
} else {
|
||||
// We return an empty string so any filepath.join does not alter the paths
|
||||
return ""
|
||||
}
|
||||
}
|
@ -30,8 +30,8 @@ import (
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
func writeCmdline(s string, fs v1.FS) error {
|
||||
|
@ -32,14 +32,15 @@ import (
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/fs"
|
||||
"github.com/kairos-io/kairos-agent/v2/pkg/utils/partitions"
|
||||
"github.com/kairos-io/kairos-agent/v2/tests/matchers"
|
||||
v1mock "github.com/kairos-io/kairos-agent/v2/tests/mocks"
|
||||
ghwMock "github.com/kairos-io/kairos-sdk/ghw/mocks"
|
||||
sdkTypes "github.com/kairos-io/kairos-sdk/types"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/twpayne/go-vfs/v4"
|
||||
"github.com/twpayne/go-vfs/v4/vfst"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"github.com/twpayne/go-vfs/v5/vfst"
|
||||
)
|
||||
|
||||
func getNamesFromListFiles(list []fs.DirEntry) []string {
|
||||
@ -1062,4 +1063,206 @@ var _ = Describe("Utils", Label("utils"), func() {
|
||||
Expect(utils.IsUkiWithFs(fs)).To(BeFalse())
|
||||
})
|
||||
})
|
||||
Describe("AddBootAssessment", func() {
|
||||
BeforeEach(func() {
|
||||
Expect(fsutils.MkdirAll(fs, "/efi/loader/entries", os.ModePerm)).ToNot(HaveOccurred())
|
||||
})
|
||||
It("adds the boot assessment to a file", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/test.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = utils.AddBootAssessment(fs, "/efi/loader/entries", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect("/efi/loader/entries/test.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
// Should match with the +3
|
||||
Expect("/efi/loader/entries/test+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
})
|
||||
It("adds the boot assessment to several files", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/test1.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test3.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = utils.AddBootAssessment(fs, "/efi/loader/entries", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect("/efi/loader/entries/test1.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test2.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test3.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
// Should match with the +3
|
||||
Expect("/efi/loader/entries/test1+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test2+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test3+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
})
|
||||
It("leaves assessment in place for existing files", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/test1.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test2+3.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test3+1-2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = utils.AddBootAssessment(fs, "/efi/loader/entries", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect("/efi/loader/entries/test1.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test3+3.conf").ToNot(matchers.BeAnExistingFileFs(fs))
|
||||
// Should match with the +3 and the existing ones left in place
|
||||
Expect("/efi/loader/entries/test1+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test2+3.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
Expect("/efi/loader/entries/test3+1-2.conf").To(matchers.BeAnExistingFileFs(fs))
|
||||
})
|
||||
It("fails to write the boot assessment in non existing dir", func() {
|
||||
err := utils.AddBootAssessment(fs, "/fake", logger)
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
Describe("ReadAssessmentFromEntry", func() {
|
||||
var ghwTest ghwMock.GhwMock
|
||||
BeforeEach(func() {
|
||||
Expect(fsutils.MkdirAll(fs, "/efi/loader/entries", os.ModePerm)).ToNot(HaveOccurred())
|
||||
mainDisk := sdkTypes.Disk{
|
||||
Name: "device",
|
||||
Partitions: []*sdkTypes.Partition{
|
||||
{
|
||||
Name: "device1",
|
||||
FilesystemLabel: "COS_GRUB",
|
||||
FS: "ext4",
|
||||
MountPoint: "/efi",
|
||||
},
|
||||
},
|
||||
}
|
||||
ghwTest = ghwMock.GhwMock{}
|
||||
ghwTest.AddDisk(mainDisk)
|
||||
ghwTest.CreateDevices()
|
||||
})
|
||||
AfterEach(func() {
|
||||
ghwTest.Clean()
|
||||
})
|
||||
It("reads the assessment from a file", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/test+2-1.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "test", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+2-1"))
|
||||
})
|
||||
It("reads passive when using fallback", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/passive+2-1.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// fallback should point to passive
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "fallback", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+2-1"))
|
||||
|
||||
// Should find the passive entry as well directly
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "passive", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+2-1"))
|
||||
})
|
||||
It("reads active when using cos", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/active+1-2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
// cos should point to active
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "cos", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+1-2"))
|
||||
|
||||
// Should find the active entry as well directly
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "active", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+1-2"))
|
||||
})
|
||||
|
||||
It("empty assessment if it doesnt match", func() {
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "cos", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
|
||||
// Should find the active entry as well directly
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "active", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
})
|
||||
|
||||
It("fails with no EFI partition", func() {
|
||||
ghwTest.Clean()
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "cos", logger)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
})
|
||||
|
||||
It("errors if more than one file matches", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/active+1-2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/active+3-2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "active", logger)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
Expect(err.Error()).To(Equal(fmt.Sprintf(constants.MultipleEntriesAssessmentError, "active")))
|
||||
})
|
||||
|
||||
It("errors if dir doesn't exist", func() {
|
||||
// Remove all dirs
|
||||
cleanup()
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "active", logger)
|
||||
Expect(err).To(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
// Check that error is os.ErrNotExist
|
||||
Expect(errors.Is(err, os.ErrNotExist)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("matches with weird but valid format", func() {
|
||||
// This are valid values, after all the asessment is just a string at the end that starts with + and has
|
||||
// and number and an optional dash after that. It has to be before the .conf so this are valid values
|
||||
// even if they are weird or stupid.
|
||||
// potentially the name can be this if someone is rebuilding efi files and adding the + to indicate the build number
|
||||
// for example.
|
||||
// We dont use this but still want to check if these are valid.
|
||||
err := fs.WriteFile("/efi/loader/entries/test1++++++5.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test2+3+3-1.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "test1", logger)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+5"))
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "test2", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal("+3-1"))
|
||||
})
|
||||
It("doesn't match assessment if format is wrong", func() {
|
||||
err := fs.WriteFile("/efi/loader/entries/test1+1djnfsdjknfsdajf2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test2+1-sadfsbauhdfkj.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test3+asdasd.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test4+-2.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
err = fs.WriteFile("/efi/loader/entries/test5+3&4.conf", []byte(""), os.ModePerm)
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
|
||||
entry, err := utils.ReadAssessmentFromEntry(fs, "test1", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "test2", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "test3", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "test4", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
entry, err = utils.ReadAssessmentFromEntry(fs, "test5", logger)
|
||||
// It actually does not error but just doesn't match
|
||||
Expect(err).ToNot(HaveOccurred())
|
||||
Expect(entry).To(Equal(""))
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
|
@ -11,9 +11,6 @@
|
||||
"reviewers": [ "team:maintainers" ],
|
||||
"timezone": "Europe/Brussels",
|
||||
"rebaseWhen": "behind-base-branch",
|
||||
"constraints": {
|
||||
"go": "1.22"
|
||||
},
|
||||
"packageRules": [
|
||||
{
|
||||
"matchUpdateTypes": ["patch"],
|
||||
|
44
tests/matchers/fs.go
Normal file
44
tests/matchers/fs.go
Normal file
@ -0,0 +1,44 @@
|
||||
package matchers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/onsi/gomega/format"
|
||||
"github.com/onsi/gomega/types"
|
||||
"github.com/twpayne/go-vfs/v5"
|
||||
"os"
|
||||
)
|
||||
|
||||
// BeAnExistingFileFs returns a matcher that checks if a file exists in the given vfs.
|
||||
func BeAnExistingFileFs(fs vfs.FS) types.GomegaMatcher {
|
||||
return &beAnExistingFileFsMatcher{
|
||||
fs: fs,
|
||||
}
|
||||
}
|
||||
|
||||
type beAnExistingFileFsMatcher struct {
|
||||
fs vfs.FS
|
||||
}
|
||||
|
||||
func (matcher *beAnExistingFileFsMatcher) Match(actual interface{}) (success bool, err error) {
|
||||
actualFilename, ok := actual.(string)
|
||||
if !ok {
|
||||
return false, fmt.Errorf("BeAnExistingFileFs matcher expects a file path")
|
||||
}
|
||||
// Here is the magic, check existence against a vfs
|
||||
if _, err = matcher.fs.Stat(actualFilename); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (matcher *beAnExistingFileFsMatcher) FailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "to exist")
|
||||
}
|
||||
|
||||
func (matcher *beAnExistingFileFsMatcher) NegatedFailureMessage(actual interface{}) (message string) {
|
||||
return format.Message(actual, "not to exist")
|
||||
}
|
Loading…
Reference in New Issue
Block a user