Split monolith agent into controller and agent
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.DS_Store
|
||||||
clitools/bin
|
clitools/bin
|
||||||
packages/
|
packages/
|
||||||
out/
|
out/
|
||||||
|
|||||||
@@ -86,11 +86,3 @@ make cluster-config \
|
|||||||
```
|
```
|
||||||
|
|
||||||
Check inside [configs/cluster.env.default](configs/cluster.env.default) for configuration details
|
Check inside [configs/cluster.env.default](configs/cluster.env.default) for configuration details
|
||||||
|
|
||||||
### Making sub stages
|
|
||||||
```bash
|
|
||||||
make build-base # The image that builds the kernel and everything
|
|
||||||
make kernel # Builds our kernel from NXP
|
|
||||||
make initramfs
|
|
||||||
make itb # Builds out/board.itb (contains the kernel and the initramfs)
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ set -euo pipefail
|
|||||||
|
|
||||||
/preload-k8s-images.sh || exit 1
|
/preload-k8s-images.sh || exit 1
|
||||||
|
|
||||||
export CTL_BIN_LAYER=$( skopeo inspect docker-daemon:localhost/monok8s/control-agent:dev | jq -r '.Layers[0] | sub("^sha256:"; "")' )
|
export CTL_BIN_LAYER=$( skopeo inspect docker-daemon:localhost/monok8s/node-control:dev | jq -r '.Layers[0] | sub("^sha256:"; "")' )
|
||||||
|
|
||||||
mkdir -p \
|
mkdir -p \
|
||||||
"$ROOTFS/dev" \
|
"$ROOTFS/dev" \
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ FUSE_OVERLAYFS="${FUSE_OVERLAYFS:-/usr/bin/fuse-overlayfs}"
|
|||||||
# )
|
# )
|
||||||
EXTRA_IMAGES=(
|
EXTRA_IMAGES=(
|
||||||
"${EXTRA_IMAGES[@]:-}"
|
"${EXTRA_IMAGES[@]:-}"
|
||||||
"docker-daemon:localhost/monok8s/control-agent:$TAG"
|
"docker-daemon:localhost/monok8s/node-control:$TAG"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Keep archive cache version/arch scoped so downloads do not get mixed.
|
# Keep archive cache version/arch scoped so downloads do not get mixed.
|
||||||
|
|||||||
20
clitools/devtools/run.sh
Executable file
20
clitools/devtools/run.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
PROJ_ROOT="$( realpath "$SCRIPT_DIR"/../ )"
|
||||||
|
OUT_DIR="$PROJ_ROOT"/out
|
||||||
|
|
||||||
|
if [ "$1" == "controller" ]; then
|
||||||
|
if [ -f "$OUT_DIR/tls.key" ] && [ -f "$OUT_DIR/tls.crt" ]; then
|
||||||
|
echo "Use existing certs"
|
||||||
|
else
|
||||||
|
echo "Generating self signed certs"
|
||||||
|
openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
|
||||||
|
-keyout "$OUT_DIR"/tls.key -out "$OUT_DIR"/tls.crt \
|
||||||
|
-subj "/CN=127.0.0.1" \
|
||||||
|
-addext "subjectAltName=IP:127.0.0.1,DNS:localhost"
|
||||||
|
fi
|
||||||
|
go run "$PROJ_ROOT"/cmd/ctl $@ --tls-cert-file "$OUT_DIR"/tls.crt --tls-private-key-file "$OUT_DIR"/tls.key
|
||||||
|
else
|
||||||
|
go run "$PROJ_ROOT"/cmd/ctl $@
|
||||||
|
fi
|
||||||
@@ -3,31 +3,37 @@ module example.com/monok8s
|
|||||||
go 1.26.0
|
go 1.26.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/emicklei/go-restful/v3 v3.12.2
|
||||||
github.com/klauspost/compress v1.18.5
|
github.com/klauspost/compress v1.18.5
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.10.2
|
||||||
golang.org/x/sys v0.31.0
|
golang.org/x/sys v0.39.0
|
||||||
gopkg.in/yaml.v3 v3.0.1
|
gopkg.in/yaml.v3 v3.0.1
|
||||||
k8s.io/api v0.34.0
|
k8s.io/api v0.35.0
|
||||||
k8s.io/apiextensions-apiserver v0.34.0
|
k8s.io/apiextensions-apiserver v0.35.0
|
||||||
k8s.io/apimachinery v0.34.0
|
k8s.io/apimachinery v0.35.0
|
||||||
|
k8s.io/apiserver v0.35.0
|
||||||
k8s.io/cli-runtime v0.34.0
|
k8s.io/cli-runtime v0.34.0
|
||||||
k8s.io/client-go v0.34.0
|
k8s.io/client-go v0.35.0
|
||||||
|
k8s.io/code-generator v0.35.0
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
|
sigs.k8s.io/controller-tools v0.20.1
|
||||||
sigs.k8s.io/yaml v1.6.0
|
sigs.k8s.io/yaml v1.6.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
|
||||||
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||||
github.com/emicklei/go-restful/v3 v3.12.2 // indirect
|
github.com/fatih/color v1.18.0 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.9.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.3 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gobuffalo/flect v1.0.3 // indirect
|
||||||
github.com/google/btree v1.1.3 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/gnostic-models v0.7.0 // indirect
|
github.com/google/gnostic-models v0.7.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
@@ -37,30 +43,42 @@ require (
|
|||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.0 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/prometheus/client_golang v1.23.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.6 // indirect
|
github.com/prometheus/client_model v0.6.2 // indirect
|
||||||
|
github.com/prometheus/common v0.66.1 // indirect
|
||||||
|
github.com/prometheus/procfs v0.16.1 // indirect
|
||||||
|
github.com/spf13/pflag v1.0.10 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xlab/treeprint v1.2.0 // indirect
|
github.com/xlab/treeprint v1.2.0 // indirect
|
||||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
go.opentelemetry.io/otel v1.36.0 // indirect
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0 // indirect
|
||||||
|
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||||
golang.org/x/net v0.38.0 // indirect
|
golang.org/x/mod v0.31.0 // indirect
|
||||||
golang.org/x/oauth2 v0.27.0 // indirect
|
golang.org/x/net v0.48.0 // indirect
|
||||||
golang.org/x/sync v0.12.0 // indirect
|
golang.org/x/oauth2 v0.30.0 // indirect
|
||||||
golang.org/x/term v0.30.0 // indirect
|
golang.org/x/sync v0.19.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/term v0.38.0 // indirect
|
||||||
|
golang.org/x/text v0.32.0 // indirect
|
||||||
golang.org/x/time v0.9.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.5 // indirect
|
golang.org/x/tools v0.40.0 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
google.golang.org/protobuf v1.36.8 // indirect
|
||||||
|
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
|
k8s.io/component-base v0.35.0 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b // indirect
|
||||||
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 // indirect
|
||||||
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 // indirect
|
||||||
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.20.1 // indirect
|
sigs.k8s.io/kustomize/api v0.20.1 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
|
sigs.k8s.io/kustomize/kyaml v0.20.1 // indirect
|
||||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||||
|
|||||||
231
clitools/go.sum
231
clitools/go.sum
@@ -1,7 +1,19 @@
|
|||||||
|
cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
|
||||||
|
cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
|
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
|
||||||
|
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
|
||||||
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||||
|
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/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY=
|
||||||
@@ -11,12 +23,20 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
github.com/emicklei/go-restful/v3 v3.12.2 h1:DhwDP0vY3k8ZzE0RunuJy8GhNpPL6zqLkDf9B/a0/xU=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.12.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
|
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||||
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ=
|
||||||
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY=
|
||||||
@@ -27,29 +47,31 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
|
|||||||
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
||||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
|
github.com/google/cel-go v0.26.0 h1:DPGjXackMpJWH680oGY4lZhYjIameYmR+/6RBdDGmaI=
|
||||||
|
github.com/google/cel-go v0.26.0/go.mod h1:A9O8OU9rdvrK5MQyrqfIxo1a0u4g3sF8KB6PUIaryMM=
|
||||||
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
github.com/google/gnostic-models v0.7.0 h1:qwTtogB15McXDaNqTZdzPJRHvaVJlAl+HVQnLmJEJxo=
|
||||||
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
github.com/google/gnostic-models v0.7.0/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
|
||||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
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.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
|
github.com/klauspost/compress v1.18.5 h1:/h1gH5Ce+VWNLSWqPzOVn6XBO+vJbCNGvjoaGBFW2IE=
|
||||||
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
github.com/klauspost/compress v1.18.5/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
@@ -59,10 +81,17 @@ 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.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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -75,25 +104,38 @@ github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/
|
|||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.27.2 h1:LzwLj0b89qtIy6SSASkzlNvX6WktqurSHwkk2ipF/Ns=
|
||||||
|
github.com/onsi/ginkgo/v2 v2.27.2/go.mod h1:ArE1D/XhNXBXCBkKOLkbsb2c81dQHCRcF5zwn/ykDRo=
|
||||||
|
github.com/onsi/gomega v1.38.3 h1:eTX+W6dobAYfFeGC2PV6RwXRu/MyT+cQguijutvkpSM=
|
||||||
|
github.com/onsi/gomega v1.38.3/go.mod h1:ZCU1pkQcXDO5Sl9/VVEGlDyp+zm0m1cmeG5TOzLgdh4=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
github.com/prometheus/client_golang v1.23.2 h1:Je96obch5RDVy3FDMndoUsjAhG5Edi49h0RJWRi/o0o=
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
github.com/prometheus/client_golang v1.23.2/go.mod h1:Tb1a6LWHB3/SPIzCoaDXI4I8UHKeFTEQ1YCr+0Gyqmg=
|
||||||
|
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||||
|
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||||
|
github.com/prometheus/common v0.66.1 h1:h5E0h5/Y8niHc5DlaLlWLArTQI7tMrsfQjHV+d9ZoGs=
|
||||||
|
github.com/prometheus/common v0.66.1/go.mod h1:gcaUsgf3KfRSwHY4dIMXLPV0K/Wg1oZ8+SbZk/HH/dA=
|
||||||
|
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||||
|
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
github.com/spf13/cobra v1.10.2/go.mod h1:7C1pvHqHw5A4vrJfjNwvOdzYu0Gml16OCs2GRiTUUS4=
|
||||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||||
|
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/stoewer/go-strcase v1.3.0 h1:g0eASXYtp+yvN9fK8sH94oCIk0fau9uV1/ZdJ0AVEzs=
|
||||||
|
github.com/stoewer/go-strcase v1.3.0/go.mod h1:fAH5hQ5pehh+j3nZfvwdk2RgEgQjAoM8wodgtPmh1xo=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
@@ -104,92 +146,115 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 h1:F7Jx+6hwnZ41NSFTO5q4LYDtJRXBf2PD0rNBkeB/lus=
|
||||||
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0/go.mod h1:UHB22Z8QsdRDrnAtX4PntOl36ajSxcdUMt1sF7Y6E7Q=
|
||||||
|
go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
|
||||||
|
go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0 h1:OeNbIYk/2C15ckl7glBlOBp5+WlYsOElzTNmiPW/x60=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.34.0/go.mod h1:7Bept48yIeqxP2OZ9/AqIpYS94h2or0aB4FypJTc8ZM=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0 h1:tgJ0uaNS4c98WRNUEx5U3aDlrDOI5Rs+1Vifcw4DJ8U=
|
||||||
|
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.34.0/go.mod h1:U7HYyW0zt/a9x5J1Kjs+r1f/d4ZHnYFclhYY2+YbeoE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
|
||||||
|
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
|
||||||
|
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
|
||||||
|
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.5.0 h1:xJvq7gMzB31/d406fB8U5CBdyQGw4P399D1aQWU/3i4=
|
||||||
|
go.opentelemetry.io/proto/otlp v1.5.0/go.mod h1:keN8WnHxOy8PG0rQZjJJ5A2ebUoafqWp0eVQ4yIXvJ4=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||||
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
||||||
golang.org/x/oauth2 v0.27.0 h1:da9Vo7/tDv5RH/7nZDz1eMGS/q1Vv1N/7FCrBhI9I3M=
|
|
||||||
golang.org/x/oauth2 v0.27.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
|
||||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY=
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated h1:1h2MnaIAIXISqTFKdENegdpAgUXz6NrPEsbIeWaBRvM=
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated/go.mod h1:RVAQXBGNv1ib0J382/DPCRS/BPnsGebyM1Gj5VSDpG8=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a h1:v2PbRU4K3llS09c7zodFpNePeamkAwG3mPrAery9VeE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250528174236-200df99c418a/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
google.golang.org/grpc v1.72.2 h1:TdbGzwb82ty4OusHWepvFWGLgIbNo1/SUynEN0ssqv8=
|
||||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/grpc v1.72.2/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
|
google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc=
|
||||||
|
google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
|
gopkg.in/evanphx/json-patch.v4 v4.13.0 h1:czT3CmqEaQ1aanPc5SdlgQrrEIb8w/wwCvWWnfEbYzo=
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
gopkg.in/evanphx/json-patch.v4 v4.13.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
|
||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
k8s.io/api v0.34.0 h1:L+JtP2wDbEYPUeNGbeSa/5GwFtIA662EmT2YSLOkAVE=
|
k8s.io/api v0.35.0 h1:iBAU5LTyBI9vw3L5glmat1njFK34srdLmktWwLTprlY=
|
||||||
k8s.io/api v0.34.0/go.mod h1:YzgkIzOOlhl9uwWCZNqpw6RJy9L2FK4dlJeayUoydug=
|
k8s.io/api v0.35.0/go.mod h1:AQ0SNTzm4ZAczM03QH42c7l3bih1TbAXYo0DkF8ktnA=
|
||||||
k8s.io/apiextensions-apiserver v0.34.0 h1:B3hiB32jV7BcyKcMU5fDaDxk882YrJ1KU+ZSkA9Qxoc=
|
k8s.io/apiextensions-apiserver v0.35.0 h1:3xHk2rTOdWXXJM+RDQZJvdx0yEOgC0FgQ1PlJatA5T4=
|
||||||
k8s.io/apiextensions-apiserver v0.34.0/go.mod h1:hLI4GxE1BDBy9adJKxUxCEHBGZtGfIg98Q+JmTD7+g0=
|
k8s.io/apiextensions-apiserver v0.35.0/go.mod h1:E1Ahk9SADaLQ4qtzYFkwUqusXTcaV2uw3l14aqpL2LU=
|
||||||
k8s.io/apimachinery v0.34.0 h1:eR1WO5fo0HyoQZt1wdISpFDffnWOvFLOOeJ7MgIv4z0=
|
k8s.io/apimachinery v0.35.0 h1:Z2L3IHvPVv/MJ7xRxHEtk6GoJElaAqDCCU0S6ncYok8=
|
||||||
k8s.io/apimachinery v0.34.0/go.mod h1:/GwIlEcWuTX9zKIg2mbw0LRFIsXwrfoVxn+ef0X13lw=
|
k8s.io/apimachinery v0.35.0/go.mod h1:jQCgFZFR1F4Ik7hvr2g84RTJSZegBc8yHgFWKn//hns=
|
||||||
|
k8s.io/apiserver v0.35.0 h1:CUGo5o+7hW9GcAEF3x3usT3fX4f9r8xmgQeCBDaOgX4=
|
||||||
|
k8s.io/apiserver v0.35.0/go.mod h1:QUy1U4+PrzbJaM3XGu2tQ7U9A4udRRo5cyxkFX0GEds=
|
||||||
k8s.io/cli-runtime v0.34.0 h1:N2/rUlJg6TMEBgtQ3SDRJwa8XyKUizwjlOknT1mB2Cw=
|
k8s.io/cli-runtime v0.34.0 h1:N2/rUlJg6TMEBgtQ3SDRJwa8XyKUizwjlOknT1mB2Cw=
|
||||||
k8s.io/cli-runtime v0.34.0/go.mod h1:t/skRecS73Piv+J+FmWIQA2N2/rDjdYSQzEE67LUUs8=
|
k8s.io/cli-runtime v0.34.0/go.mod h1:t/skRecS73Piv+J+FmWIQA2N2/rDjdYSQzEE67LUUs8=
|
||||||
k8s.io/client-go v0.34.0 h1:YoWv5r7bsBfb0Hs2jh8SOvFbKzzxyNo0nSb0zC19KZo=
|
k8s.io/client-go v0.35.0 h1:IAW0ifFbfQQwQmga0UdoH0yvdqrbwMdq9vIFEhRpxBE=
|
||||||
k8s.io/client-go v0.34.0/go.mod h1:ozgMnEKXkRjeMvBZdV1AijMHLTh3pbACPvK7zFR+QQY=
|
k8s.io/client-go v0.35.0/go.mod h1:q2E5AAyqcbeLGPdoRB+Nxe3KYTfPce1Dnu1myQdqz9o=
|
||||||
|
k8s.io/code-generator v0.35.0 h1:TvrtfKYZTm9oDF2z+veFKSCcgZE3Igv0svY+ehCmjHQ=
|
||||||
|
k8s.io/code-generator v0.35.0/go.mod h1:iS1gvVf3c/T71N5DOGYO+Gt3PdJ6B9LYSvIyQ4FHzgc=
|
||||||
|
k8s.io/component-base v0.35.0 h1:+yBrOhzri2S1BVqyVSvcM3PtPyx5GUxCK2tinZz1G94=
|
||||||
|
k8s.io/component-base v0.35.0/go.mod h1:85SCX4UCa6SCFt6p3IKAPej7jSnF3L8EbfSyMZayJR0=
|
||||||
|
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b h1:gMplByicHV/TJBizHd9aVEsTYoJBnnUAT5MHlTkbjhQ=
|
||||||
|
k8s.io/gengo/v2 v2.0.0-20250922181213-ec3ebc5fd46b/go.mod h1:CgujABENc3KuTrcsdpGmrrASjtQsWCT7R99mEV4U/fM=
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b h1:MloQ9/bdJyIu9lb1PzujOPolHyvO06MXG5TUIj2mNAA=
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912 h1:Y3gxNAuB0OBLImH611+UDZcmKS3g6CthxToOb37KgwE=
|
||||||
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b/go.mod h1:UZ2yyWbFTpuhSbFhv24aGNOdoRdJZgsIObGBUaYVsts=
|
k8s.io/kube-openapi v0.0.0-20250910181357-589584f1c912/go.mod h1:kdmbQkyfwUagLfXIad1y2TdrjPFWp2Q89B3qkRwf/pQ=
|
||||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 h1:hwvWFiBzdWw1FhfY1FooPn3kzWuJ8tmbZBHi4zVsl1Y=
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4 h1:SjGebBtkBqHFOli+05xYbK8YF1Dzkbzn+gDM4X9T4Ck=
|
||||||
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20251002143259-bc988d571ff4/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
|
||||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw=
|
||||||
|
sigs.k8s.io/controller-tools v0.20.1 h1:gkfMt9YodI0K85oT8rVi80NTXO/kDmabKR5Ajn5GYxs=
|
||||||
|
sigs.k8s.io/controller-tools v0.20.1/go.mod h1:b4qPmjGU3iZwqn34alUU5tILhNa9+VXK+J3QV0fT/uU=
|
||||||
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
|
||||||
|
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||||
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
|
sigs.k8s.io/kustomize/api v0.20.1 h1:iWP1Ydh3/lmldBnH/S5RXgT98vWYMaTUL1ADcr+Sv7I=
|
||||||
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
|
sigs.k8s.io/kustomize/api v0.20.1/go.mod h1:t6hUFxO+Ph0VxIk1sKp1WS0dOjbPCtLJ4p8aADLwqjM=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
|
sigs.k8s.io/kustomize/kyaml v0.20.1 h1:PCMnA2mrVbRP3NIB6v9kYCAc38uvFLVs8j/CD567A78=
|
||||||
|
|||||||
1
clitools/hack/boilerplate.go.txt
Normal file
1
clitools/hack/boilerplate.go.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/* MIT License */
|
||||||
9
clitools/hack/tool.go
Normal file
9
clitools/hack/tool.go
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
//go:build tools
|
||||||
|
// +build tools
|
||||||
|
|
||||||
|
package tools
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "k8s.io/code-generator"
|
||||||
|
_ "sigs.k8s.io/controller-tools/cmd/controller-gen"
|
||||||
|
)
|
||||||
36
clitools/hack/update-codegen.sh
Executable file
36
clitools/hack/update-codegen.sh
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
MODULE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
echo "MODULE ROOT: ${MODULE_ROOT}"
|
||||||
|
|
||||||
|
cd "${MODULE_ROOT}"
|
||||||
|
mkdir -p \
|
||||||
|
"${MODULE_ROOT}/pkg/generated/clientset" \
|
||||||
|
"${MODULE_ROOT}/pkg/generated/listers" \
|
||||||
|
"${MODULE_ROOT}/pkg/generated/informers"
|
||||||
|
|
||||||
|
controller-gen \
|
||||||
|
object:headerFile=hack/boilerplate.go.txt \
|
||||||
|
paths=./pkg/apis/...
|
||||||
|
|
||||||
|
MODULE="$(go list -m -f '{{.Path}}')"
|
||||||
|
echo "MODULE: ${MODULE}"
|
||||||
|
|
||||||
|
CODEGEN_PKG="$(go list -f '{{.Dir}}' -m k8s.io/code-generator)"
|
||||||
|
echo "CODEGEN PKG: ${CODEGEN_PKG}"
|
||||||
|
|
||||||
|
source "${CODEGEN_PKG}/kube_codegen.sh"
|
||||||
|
|
||||||
|
mkdir -p "${MODULE_ROOT}/pkg/generated"
|
||||||
|
|
||||||
|
kube::codegen::gen_helpers \
|
||||||
|
--boilerplate "${MODULE_ROOT}/hack/boilerplate.go.txt" \
|
||||||
|
"${MODULE_ROOT}/pkg/apis"
|
||||||
|
|
||||||
|
kube::codegen::gen_client \
|
||||||
|
--with-watch \
|
||||||
|
--output-dir "${MODULE_ROOT}/pkg/generated" \
|
||||||
|
--output-pkg "${MODULE}/pkg/generated" \
|
||||||
|
--boilerplate "${MODULE_ROOT}/hack/boilerplate.go.txt" \
|
||||||
|
"${MODULE_ROOT}/pkg/apis"
|
||||||
@@ -125,7 +125,7 @@ build-agent: build uboot-tools
|
|||||||
-f docker/ctl-agent.Dockerfile \
|
-f docker/ctl-agent.Dockerfile \
|
||||||
--build-arg VERSION=$(VERSION) \
|
--build-arg VERSION=$(VERSION) \
|
||||||
--load \
|
--load \
|
||||||
-t localhost/monok8s/control-agent:$(VERSION) .
|
-t localhost/monok8s/node-control:$(VERSION) .
|
||||||
|
|
||||||
build-local: .buildinfo | $(BIN_DIR)
|
build-local: .buildinfo | $(BIN_DIR)
|
||||||
docker buildx build \
|
docker buildx build \
|
||||||
@@ -138,13 +138,13 @@ build-local: .buildinfo | $(BIN_DIR)
|
|||||||
run-agent:
|
run-agent:
|
||||||
docker run --rm \
|
docker run --rm \
|
||||||
-v "$$(pwd)/out:/work/out" \
|
-v "$$(pwd)/out:/work/out" \
|
||||||
localhost/monok8s/control-agent:$(VERSION) \
|
localhost/monok8s/node-control:$(VERSION) \
|
||||||
agent --env-file /work/out/cluster.env
|
agent --env-file /work/out/cluster.env
|
||||||
|
|
||||||
build: build-bin build-crds
|
build: build-bin build-crds
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-docker image rm localhost/monok8s/control-agent:$(VERSION) >/dev/null 2>&1 || true
|
-docker image rm localhost/monok8s/node-control:$(VERSION) >/dev/null 2>&1 || true
|
||||||
rm -rf \
|
rm -rf \
|
||||||
$(BIN_DIR) \
|
$(BIN_DIR) \
|
||||||
$(OUT_DIR)/crds \
|
$(OUT_DIR)/crds \
|
||||||
@@ -157,7 +157,7 @@ dockerclean:
|
|||||||
@echo "Removing tagged images..."
|
@echo "Removing tagged images..."
|
||||||
- docker rmi \
|
- docker rmi \
|
||||||
localhost/monok8s/ctl-build-base:$(VERSION) \
|
localhost/monok8s/ctl-build-base:$(VERSION) \
|
||||||
localhost/monok8s/control-agent:$(VERSION) \
|
localhost/monok8s/node-control:$(VERSION) \
|
||||||
localhost/monok8s/ctl-builder:$(VERSION) \
|
localhost/monok8s/ctl-builder:$(VERSION) \
|
||||||
localhost/monok8s/crdgen:$(VERSION) \
|
localhost/monok8s/crdgen:$(VERSION) \
|
||||||
2>/dev/null || true
|
2>/dev/null || true
|
||||||
|
|||||||
@@ -14,10 +14,12 @@ var (
|
|||||||
APIVersion = "monok8s.io/v1alpha1"
|
APIVersion = "monok8s.io/v1alpha1"
|
||||||
|
|
||||||
AltPartDeviceLink = "/dev/mksaltpart"
|
AltPartDeviceLink = "/dev/mksaltpart"
|
||||||
Annotation = "monok8s.io/annotation"
|
|
||||||
BootStateFile = "/run/monok8s/boot-state.env"
|
BootStateFile = "/run/monok8s/boot-state.env"
|
||||||
CatalogURL = "https://example.com/monok8s.io/v1alpha1/catalog.yaml"
|
CatalogURL = "https://example.com/monok8s.io/v1alpha1/catalog.yaml"
|
||||||
ControlAgentKey = "monok8s.io/control-agent"
|
NodeControlKey = "monok8s.io/node-control"
|
||||||
|
NodeControlName = "node-control"
|
||||||
|
ControllerName = "node-controller"
|
||||||
|
NodeAgentName = "node-agent"
|
||||||
EnvConfigDir = "/opt/monok8s/config"
|
EnvConfigDir = "/opt/monok8s/config"
|
||||||
Label = "monok8s.io/label"
|
Label = "monok8s.io/label"
|
||||||
MonoKSConfigCRD = "monoksconfigs.monok8s.io"
|
MonoKSConfigCRD = "monoksconfigs.monok8s.io"
|
||||||
@@ -25,18 +27,29 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
GroupVersion = schema.GroupVersion{Group: Group, Version: Version}
|
SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version}
|
||||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||||
AddToScheme = SchemeBuilder.AddToScheme
|
AddToScheme = SchemeBuilder.AddToScheme
|
||||||
)
|
)
|
||||||
|
|
||||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||||
scheme.AddKnownTypes(GroupVersion,
|
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||||
&MonoKSConfig{},
|
&MonoKSConfig{},
|
||||||
&MonoKSConfigList{},
|
&MonoKSConfigList{},
|
||||||
&OSUpgrade{},
|
&OSUpgrade{},
|
||||||
&OSUpgradeList{},
|
&OSUpgradeList{},
|
||||||
|
&OSUpgradeProgress{},
|
||||||
|
&OSUpgradeProgressList{},
|
||||||
)
|
)
|
||||||
metav1.AddToGroupVersion(scheme, GroupVersion)
|
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NodeAgentLabels() map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"app.kubernetes.io/name": NodeAgentName,
|
||||||
|
"app.kubernetes.io/component": "agent",
|
||||||
|
"app.kubernetes.io/part-of": "monok8s",
|
||||||
|
"app.kubernetes.io/managed-by": NodeControlName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ type MonoKSConfigSpec struct {
|
|||||||
ClusterDomain string `json:"clusterDomain,omitempty" yaml:"clusterDomain,omitempty"`
|
ClusterDomain string `json:"clusterDomain,omitempty" yaml:"clusterDomain,omitempty"`
|
||||||
ClusterRole string `json:"clusterRole,omitempty" yaml:"clusterRole,omitempty"`
|
ClusterRole string `json:"clusterRole,omitempty" yaml:"clusterRole,omitempty"`
|
||||||
InitControlPlane bool `json:"initControlPlane,omitempty" yaml:"initControlPlane,omitempty"`
|
InitControlPlane bool `json:"initControlPlane,omitempty" yaml:"initControlPlane,omitempty"`
|
||||||
EnableControlAgent bool `json:"enableControlAgent,omitempty" yaml:"enableControlAgent,omitempty"`
|
EnableNodeControl bool `json:"enableNodeControl,omitempty" yaml:"enableNodeControl,omitempty"`
|
||||||
PodSubnet string `json:"podSubnet,omitempty" yaml:"podSubnet,omitempty"`
|
PodSubnet string `json:"podSubnet,omitempty" yaml:"podSubnet,omitempty"`
|
||||||
ServiceSubnet string `json:"serviceSubnet,omitempty" yaml:"serviceSubnet,omitempty"`
|
ServiceSubnet string `json:"serviceSubnet,omitempty" yaml:"serviceSubnet,omitempty"`
|
||||||
APIServerAdvertiseAddress string `json:"apiServerAdvertiseAddress,omitempty" yaml:"apiServerAdvertiseAddress,omitempty"`
|
APIServerAdvertiseAddress string `json:"apiServerAdvertiseAddress,omitempty" yaml:"apiServerAdvertiseAddress,omitempty"`
|
||||||
@@ -40,7 +40,6 @@ type MonoKSConfigSpec struct {
|
|||||||
KubeProxyNodePortAddresses []string `json:"kubeProxyNodePortAddresses,omitempty" yaml:"kubeProxyNodePortAddresses,omitempty"`
|
KubeProxyNodePortAddresses []string `json:"kubeProxyNodePortAddresses,omitempty" yaml:"kubeProxyNodePortAddresses,omitempty"`
|
||||||
SubjectAltNames []string `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
|
SubjectAltNames []string `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
|
||||||
NodeLabels map[string]string `json:"nodeLabels,omitempty" yaml:"nodeLabels,omitempty"`
|
NodeLabels map[string]string `json:"nodeLabels,omitempty" yaml:"nodeLabels,omitempty"`
|
||||||
NodeAnnotations map[string]string `json:"nodeAnnotations,omitempty" yaml:"nodeAnnotations,omitempty"`
|
|
||||||
Network NetworkSpec `json:"network,omitempty" yaml:"network,omitempty"`
|
Network NetworkSpec `json:"network,omitempty" yaml:"network,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package v1alpha1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type OSUpgradePhase string
|
type OSUpgradePhase string
|
||||||
@@ -10,8 +9,6 @@ type OSUpgradePhase string
|
|||||||
const (
|
const (
|
||||||
OSUpgradePhasePending OSUpgradePhase = "Pending"
|
OSUpgradePhasePending OSUpgradePhase = "Pending"
|
||||||
OSUpgradePhaseAccepted OSUpgradePhase = "Accepted"
|
OSUpgradePhaseAccepted OSUpgradePhase = "Accepted"
|
||||||
OSUpgradePhaseRollingOut OSUpgradePhase = "RollingOut"
|
|
||||||
OSUpgradePhaseCompleted OSUpgradePhase = "Completed"
|
|
||||||
OSUpgradePhaseRejected OSUpgradePhase = "Rejected"
|
OSUpgradePhaseRejected OSUpgradePhase = "Rejected"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,27 +18,35 @@ const (
|
|||||||
OSUpgradeProgressPhasePending OSUpgradeProgressPhase = "pending"
|
OSUpgradeProgressPhasePending OSUpgradeProgressPhase = "pending"
|
||||||
OSUpgradeProgressPhaseDownloading OSUpgradeProgressPhase = "downloading"
|
OSUpgradeProgressPhaseDownloading OSUpgradeProgressPhase = "downloading"
|
||||||
OSUpgradeProgressPhaseWriting OSUpgradeProgressPhase = "writing"
|
OSUpgradeProgressPhaseWriting OSUpgradeProgressPhase = "writing"
|
||||||
OSUpgradeProgressPhaseRebooting OSUpgradeProgressPhase = "rebooting"
|
|
||||||
OSUpgradeProgressPhaseVerifying OSUpgradeProgressPhase = "verifying"
|
OSUpgradeProgressPhaseVerifying OSUpgradeProgressPhase = "verifying"
|
||||||
OSUpgradeProgressPhaseCompleted OSUpgradeProgressPhase = "completed"
|
OSUpgradeProgressPhaseCompleted OSUpgradeProgressPhase = "completed"
|
||||||
OSUpgradeProgressPhaseFailed OSUpgradeProgressPhase = "failed"
|
OSUpgradeProgressPhaseFailed OSUpgradeProgressPhase = "failed"
|
||||||
OSUpgradeProgressPhaseRejected OSUpgradeProgressPhase = "rejected"
|
OSUpgradeProgressPhaseRejected OSUpgradeProgressPhase = "rejected"
|
||||||
|
|
||||||
|
// Rebooting is the point-of-no-return phase.
|
||||||
|
//
|
||||||
|
// Once a node reaches Rebooting, the agent may have already changed the boot
|
||||||
|
// environment and requested a reboot. The controller must not supersede,
|
||||||
|
// retry, retarget, or otherwise mutate this progress object until the node
|
||||||
|
// comes back and the agent reports Completed or Failed.
|
||||||
|
OSUpgradeProgressPhaseRebooting OSUpgradeProgressPhase = "rebooting"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +genclient
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
// +kubebuilder:resource:scope=Namespaced,shortName=osu
|
// +kubebuilder:resource:scope=Namespaced,shortName=osu
|
||||||
// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.spec.desiredVersion`
|
// +kubebuilder:printcolumn:name="Desired",type=string,JSONPath=`.spec.desiredVersion`
|
||||||
// +kubebuilder:printcolumn:name="Resolved",type=string,JSONPath=`.status.resolvedVersion`
|
// +kubebuilder:printcolumn:name="Resolved",type=string,JSONPath=`.status.resolvedVersion`
|
||||||
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
|
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
|
||||||
// +kubebuilder:printcolumn:name="Targets",type=integer,JSONPath=`.status.summary.targetedNodes`
|
|
||||||
// +kubebuilder:printcolumn:name="OK",type=integer,JSONPath=`.status.summary.succeededNodes`
|
|
||||||
// +kubebuilder:printcolumn:name="Fail",type=integer,JSONPath=`.status.summary.failedNodes`
|
|
||||||
type OSUpgrade struct {
|
type OSUpgrade struct {
|
||||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||||
|
|
||||||
|
// Specification of the desired behavior of the OSUpgrade.
|
||||||
Spec OSUpgradeSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
|
Spec OSUpgradeSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
|
||||||
|
|
||||||
|
// Most recently observed status of the OSUpgrade.
|
||||||
Status *OSUpgradeStatus `json:"status,omitempty" yaml:"status,omitempty"`
|
Status *OSUpgradeStatus `json:"status,omitempty" yaml:"status,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,68 +57,38 @@ type OSUpgradeList struct {
|
|||||||
Items []OSUpgrade `json:"items" yaml:"items"`
|
Items []OSUpgrade `json:"items" yaml:"items"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// OSUpgradeSpec defines the desired state of an OSUpgrade.
|
|
||||||
type OSUpgradeSpec struct {
|
type OSUpgradeSpec struct {
|
||||||
// DesiredVersion is the requested target version.
|
|
||||||
//
|
|
||||||
// It may be either:
|
|
||||||
// - "stable" to use the catalog's current stable version
|
|
||||||
// - an explicit version such as "v1.35.3"
|
|
||||||
//
|
|
||||||
// The resolved target version is reported in status.
|
|
||||||
// +kubebuilder:validation:MinLength=1
|
// +kubebuilder:validation:MinLength=1
|
||||||
DesiredVersion string `json:"desiredVersion,omitempty" yaml:"desiredVersion,omitempty"`
|
DesiredVersion string `json:"desiredVersion,omitempty" yaml:"desiredVersion,omitempty"`
|
||||||
|
|
||||||
// FlashProfile controls how aggressively the image is written to disk.
|
|
||||||
//
|
|
||||||
// Supported values are:
|
|
||||||
// - "fast": prioritize speed
|
|
||||||
// - "balanced": default tradeoff between speed and system impact
|
|
||||||
// - "safe": minimize I/O pressure on the node
|
|
||||||
//
|
|
||||||
// If unset, the controller should use a default profile.
|
|
||||||
// +kubebuilder:validation:Enum=fast;balanced;safe
|
// +kubebuilder:validation:Enum=fast;balanced;safe
|
||||||
// +kubebuilder:default=balanced
|
// +kubebuilder:default=balanced
|
||||||
FlashProfile string `json:"flashProfile,omitempty"`
|
// Profiles (TODO)
|
||||||
|
// safe - api-server can be responsive most of the time
|
||||||
|
// balanced - api-server can sometimes be unresponsive
|
||||||
|
// fast - disable throttling. Good for worker node.
|
||||||
|
FlashProfile string `json:"flashProfile,omitempty" yaml:"flashProfile,omitempty"`
|
||||||
|
|
||||||
// Catalog specifies how available versions and images are resolved.
|
Catalog *VersionCatalogSource `json:"catalog,omitempty" yaml:"catalog,omitempty"`
|
||||||
//
|
|
||||||
// This may point to a remote catalog, inline catalog data, or another source,
|
|
||||||
// depending on the VersionCatalogSource definition.
|
|
||||||
Catalog *VersionCatalogSource `json:"catalog,omitempty"`
|
|
||||||
|
|
||||||
// NodeSelector limits the upgrade to nodes whose labels match this selector.
|
|
||||||
//
|
|
||||||
// If unset, the upgrade applies to all eligible nodes.
|
|
||||||
NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VersionCatalogSource struct {
|
type VersionCatalogSource struct {
|
||||||
URL string `json:"url,omitempty"`
|
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||||
Inline string `json:"inline,omitempty"`
|
Inline string `json:"inline,omitempty" yaml:"inline,omitempty"`
|
||||||
ConfigMap string `json:"configMapRef,omitempty"`
|
ConfigMap string `json:"configMapRef,omitempty" yaml:"configMapRef,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSUpgradeStatus struct {
|
type OSUpgradeStatus struct {
|
||||||
Phase OSUpgradePhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
Phase OSUpgradePhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
||||||
ResolvedVersion string `json:"resolvedVersion,omitempty" yaml:"resolvedVersion,omitempty"`
|
ResolvedVersion string `json:"resolvedVersion,omitempty" yaml:"resolvedVersion,omitempty"`
|
||||||
ObservedGeneration int64 `json:"observedGeneration,omitempty" yaml:"observedGeneration,omitempty"`
|
ObservedGeneration int64 `json:"observedGeneration,omitempty" yaml:"observedGeneration,omitempty"`
|
||||||
Summary OSUpgradeSummary `json:"summary,omitempty" yaml:"summary,omitempty"`
|
|
||||||
Conditions []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
|
Conditions []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
|
||||||
|
|
||||||
// Optional, useful when rejected.
|
|
||||||
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
||||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSUpgradeSummary struct {
|
// +genclient
|
||||||
TargetedNodes int32 `json:"targetedNodes,omitempty" yaml:"targetedNodes,omitempty"`
|
|
||||||
PendingNodes int32 `json:"pendingNodes,omitempty" yaml:"pendingNodes,omitempty"`
|
|
||||||
RunningNodes int32 `json:"runningNodes,omitempty" yaml:"runningNodes,omitempty"`
|
|
||||||
SucceededNodes int32 `json:"succeededNodes,omitempty" yaml:"succeededNodes,omitempty"`
|
|
||||||
FailedNodes int32 `json:"failedNodes,omitempty" yaml:"failedNodes,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// +kubebuilder:object:root=true
|
// +kubebuilder:object:root=true
|
||||||
// +kubebuilder:subresource:status
|
// +kubebuilder:subresource:status
|
||||||
// +kubebuilder:resource:scope=Namespaced,shortName=osup
|
// +kubebuilder:resource:scope=Namespaced,shortName=osup
|
||||||
@@ -121,12 +96,15 @@ type OSUpgradeSummary struct {
|
|||||||
// +kubebuilder:printcolumn:name="Source",type=string,JSONPath=`.spec.sourceRef.name`
|
// +kubebuilder:printcolumn:name="Source",type=string,JSONPath=`.spec.sourceRef.name`
|
||||||
// +kubebuilder:printcolumn:name="Current",type=string,JSONPath=`.status.currentVersion`
|
// +kubebuilder:printcolumn:name="Current",type=string,JSONPath=`.status.currentVersion`
|
||||||
// +kubebuilder:printcolumn:name="Target",type=string,JSONPath=`.status.targetVersion`
|
// +kubebuilder:printcolumn:name="Target",type=string,JSONPath=`.status.targetVersion`
|
||||||
// +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.phase`
|
// +kubebuilder:printcolumn:name="Phase",type=string,JSONPath=`.status.phase`
|
||||||
type OSUpgradeProgress struct {
|
type OSUpgradeProgress struct {
|
||||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||||
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||||
|
|
||||||
|
// Specification of the desired behavior of the OSUpgradeProgress.
|
||||||
Spec OSUpgradeProgressSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
|
Spec OSUpgradeProgressSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
|
||||||
|
|
||||||
|
// Most recently observed status of the OSUpgradeProgress.
|
||||||
Status *OSUpgradeProgressStatus `json:"status,omitempty" yaml:"status,omitempty"`
|
Status *OSUpgradeProgressStatus `json:"status,omitempty" yaml:"status,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,18 +117,24 @@ type OSUpgradeProgressList struct {
|
|||||||
|
|
||||||
type OSUpgradeProgressSpec struct {
|
type OSUpgradeProgressSpec struct {
|
||||||
SourceRef OSUpgradeSourceRef `json:"sourceRef,omitempty" yaml:"sourceRef,omitempty"`
|
SourceRef OSUpgradeSourceRef `json:"sourceRef,omitempty" yaml:"sourceRef,omitempty"`
|
||||||
|
|
||||||
|
// RetryNonce triggers a retry when its value changes.
|
||||||
|
// Users can update this field (for example, set it to the current time)
|
||||||
|
// to request a retry of a failed OS upgrade.
|
||||||
|
RetryNonce string `json:"retryNonce,omitempty" yaml:"retryNonce,omitempty"`
|
||||||
|
|
||||||
NodeName string `json:"nodeName,omitempty" yaml:"nodeName,omitempty"`
|
NodeName string `json:"nodeName,omitempty" yaml:"nodeName,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSUpgradeSourceRef struct {
|
type OSUpgradeSourceRef struct {
|
||||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||||
|
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type OSUpgradeProgressStatus struct {
|
type OSUpgradeProgressStatus struct {
|
||||||
CurrentVersion string `json:"currentVersion,omitempty" yaml:"currentVersion,omitempty"`
|
CurrentVersion string `json:"currentVersion,omitempty" yaml:"currentVersion,omitempty"`
|
||||||
TargetVersion string `json:"targetVersion,omitempty" yaml:"targetVersion,omitempty"`
|
TargetVersion string `json:"targetVersion,omitempty" yaml:"targetVersion,omitempty"`
|
||||||
Phase OSUpgradeProgressPhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
Phase OSUpgradeProgressPhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
||||||
|
|
||||||
StartedAt *metav1.Time `json:"startedAt,omitempty" yaml:"startedAt,omitempty"`
|
StartedAt *metav1.Time `json:"startedAt,omitempty" yaml:"startedAt,omitempty"`
|
||||||
CompletedAt *metav1.Time `json:"completedAt,omitempty" yaml:"completedAt,omitempty"`
|
CompletedAt *metav1.Time `json:"completedAt,omitempty" yaml:"completedAt,omitempty"`
|
||||||
LastUpdatedAt *metav1.Time `json:"lastUpdatedAt,omitempty" yaml:"lastUpdatedAt,omitempty"`
|
LastUpdatedAt *metav1.Time `json:"lastUpdatedAt,omitempty" yaml:"lastUpdatedAt,omitempty"`
|
||||||
@@ -158,41 +142,30 @@ type OSUpgradeProgressStatus struct {
|
|||||||
InactivePartition string `json:"inactivePartition,omitempty" yaml:"inactivePartition,omitempty"`
|
InactivePartition string `json:"inactivePartition,omitempty" yaml:"inactivePartition,omitempty"`
|
||||||
FailureReason string `json:"failureReason,omitempty" yaml:"failureReason,omitempty"`
|
FailureReason string `json:"failureReason,omitempty" yaml:"failureReason,omitempty"`
|
||||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||||
|
PlannedPath []string `json:"plannedPath,omitempty" yaml:"plannedPath,omitempty"`
|
||||||
|
CurrentStep int32 `json:"currentStep,omitempty" yaml:"currentStep,omitempty"`
|
||||||
|
CurrentFrom string `json:"currentFrom,omitempty" yaml:"currentFrom,omitempty"`
|
||||||
|
CurrentTo string `json:"currentTo,omitempty" yaml:"currentTo,omitempty"`
|
||||||
|
|
||||||
PlannedPath []string `json:"plannedPath,omitempty"`
|
// ObservedRetryNonce records the last retryNonce value the agent accepted.
|
||||||
CurrentStep int32 `json:"currentStep,omitempty"`
|
// When spec.retryNonce is changed by the user and differs from this value,
|
||||||
CurrentFrom string `json:"currentFrom,omitempty"`
|
// the agent may retry a failed upgrade.
|
||||||
CurrentTo string `json:"currentTo,omitempty"`
|
// +optional
|
||||||
|
ObservedRetryNonce string `json:"observedRetryNonce,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *OSUpgrade) DeepCopyObject() runtime.Object {
|
func (osu OSUpgrade) StatusPhase() string {
|
||||||
if in == nil {
|
phase := ""
|
||||||
return nil
|
if osu.Status != nil {
|
||||||
|
phase = string(osu.Status.Phase)
|
||||||
}
|
}
|
||||||
out := *in
|
return phase
|
||||||
return &out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
|
func (osup OSUpgradeProgress) StatusPhase() string {
|
||||||
if in == nil {
|
phase := ""
|
||||||
return nil
|
if osup.Status != nil {
|
||||||
|
phase = string(osup.Status.Phase)
|
||||||
}
|
}
|
||||||
out := *in
|
return phase
|
||||||
return &out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (in *OSUpgradeProgress) DeepCopyObject() runtime.Object {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := *in
|
|
||||||
return &out
|
|
||||||
}
|
|
||||||
|
|
||||||
func (in *OSUpgradeProgressList) DeepCopyObject() runtime.Object {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := *in
|
|
||||||
return &out
|
|
||||||
}
|
}
|
||||||
|
|||||||
395
clitools/pkg/apis/monok8s/v1alpha1/zz_generated.deepcopy.go
Normal file
395
clitools/pkg/apis/monok8s/v1alpha1/zz_generated.deepcopy.go
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
//go:build !ignore_autogenerated
|
||||||
|
|
||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by controller-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *MonoKSConfig) DeepCopyInto(out *MonoKSConfig) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
|
if in.Status != nil {
|
||||||
|
in, out := &in.Status, &out.Status
|
||||||
|
*out = new(MonoKSConfigStatus)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfig.
|
||||||
|
func (in *MonoKSConfig) DeepCopy() *MonoKSConfig {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(MonoKSConfig)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *MonoKSConfigList) DeepCopyInto(out *MonoKSConfigList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]MonoKSConfig, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigList.
|
||||||
|
func (in *MonoKSConfigList) DeepCopy() *MonoKSConfigList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(MonoKSConfigList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *MonoKSConfigSpec) DeepCopyInto(out *MonoKSConfigSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.KubeProxyNodePortAddresses != nil {
|
||||||
|
in, out := &in.KubeProxyNodePortAddresses, &out.KubeProxyNodePortAddresses
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.SubjectAltNames != nil {
|
||||||
|
in, out := &in.SubjectAltNames, &out.SubjectAltNames
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.NodeLabels != nil {
|
||||||
|
in, out := &in.NodeLabels, &out.NodeLabels
|
||||||
|
*out = make(map[string]string, len(*in))
|
||||||
|
for key, val := range *in {
|
||||||
|
(*out)[key] = val
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.Network.DeepCopyInto(&out.Network)
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigSpec.
|
||||||
|
func (in *MonoKSConfigSpec) DeepCopy() *MonoKSConfigSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(MonoKSConfigSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *MonoKSConfigStatus) DeepCopyInto(out *MonoKSConfigStatus) {
|
||||||
|
*out = *in
|
||||||
|
if in.Conditions != nil {
|
||||||
|
in, out := &in.Conditions, &out.Conditions
|
||||||
|
*out = make([]v1.Condition, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if in.AppliedSteps != nil {
|
||||||
|
in, out := &in.AppliedSteps, &out.AppliedSteps
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigStatus.
|
||||||
|
func (in *MonoKSConfigStatus) DeepCopy() *MonoKSConfigStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(MonoKSConfigStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.DNSNameservers != nil {
|
||||||
|
in, out := &in.DNSNameservers, &out.DNSNameservers
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
if in.DNSSearchDomains != nil {
|
||||||
|
in, out := &in.DNSSearchDomains, &out.DNSSearchDomains
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec.
|
||||||
|
func (in *NetworkSpec) DeepCopy() *NetworkSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(NetworkSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgrade) DeepCopyInto(out *OSUpgrade) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
|
if in.Status != nil {
|
||||||
|
in, out := &in.Status, &out.Status
|
||||||
|
*out = new(OSUpgradeStatus)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgrade.
|
||||||
|
func (in *OSUpgrade) DeepCopy() *OSUpgrade {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgrade)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *OSUpgrade) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeList) DeepCopyInto(out *OSUpgradeList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]OSUpgrade, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeList.
|
||||||
|
func (in *OSUpgradeList) DeepCopy() *OSUpgradeList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeProgress) DeepCopyInto(out *OSUpgradeProgress) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
|
out.Spec = in.Spec
|
||||||
|
if in.Status != nil {
|
||||||
|
in, out := &in.Status, &out.Status
|
||||||
|
*out = new(OSUpgradeProgressStatus)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgress.
|
||||||
|
func (in *OSUpgradeProgress) DeepCopy() *OSUpgradeProgress {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeProgress)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *OSUpgradeProgress) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeProgressList) DeepCopyInto(out *OSUpgradeProgressList) {
|
||||||
|
*out = *in
|
||||||
|
out.TypeMeta = in.TypeMeta
|
||||||
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
|
if in.Items != nil {
|
||||||
|
in, out := &in.Items, &out.Items
|
||||||
|
*out = make([]OSUpgradeProgress, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressList.
|
||||||
|
func (in *OSUpgradeProgressList) DeepCopy() *OSUpgradeProgressList {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeProgressList)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||||
|
func (in *OSUpgradeProgressList) DeepCopyObject() runtime.Object {
|
||||||
|
if c := in.DeepCopy(); c != nil {
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeProgressSpec) DeepCopyInto(out *OSUpgradeProgressSpec) {
|
||||||
|
*out = *in
|
||||||
|
out.SourceRef = in.SourceRef
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressSpec.
|
||||||
|
func (in *OSUpgradeProgressSpec) DeepCopy() *OSUpgradeProgressSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeProgressSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeProgressStatus) DeepCopyInto(out *OSUpgradeProgressStatus) {
|
||||||
|
*out = *in
|
||||||
|
if in.StartedAt != nil {
|
||||||
|
in, out := &in.StartedAt, &out.StartedAt
|
||||||
|
*out = (*in).DeepCopy()
|
||||||
|
}
|
||||||
|
if in.CompletedAt != nil {
|
||||||
|
in, out := &in.CompletedAt, &out.CompletedAt
|
||||||
|
*out = (*in).DeepCopy()
|
||||||
|
}
|
||||||
|
if in.LastUpdatedAt != nil {
|
||||||
|
in, out := &in.LastUpdatedAt, &out.LastUpdatedAt
|
||||||
|
*out = (*in).DeepCopy()
|
||||||
|
}
|
||||||
|
if in.PlannedPath != nil {
|
||||||
|
in, out := &in.PlannedPath, &out.PlannedPath
|
||||||
|
*out = make([]string, len(*in))
|
||||||
|
copy(*out, *in)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressStatus.
|
||||||
|
func (in *OSUpgradeProgressStatus) DeepCopy() *OSUpgradeProgressStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeProgressStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeSourceRef) DeepCopyInto(out *OSUpgradeSourceRef) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeSourceRef.
|
||||||
|
func (in *OSUpgradeSourceRef) DeepCopy() *OSUpgradeSourceRef {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeSourceRef)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeSpec) DeepCopyInto(out *OSUpgradeSpec) {
|
||||||
|
*out = *in
|
||||||
|
if in.Catalog != nil {
|
||||||
|
in, out := &in.Catalog, &out.Catalog
|
||||||
|
*out = new(VersionCatalogSource)
|
||||||
|
**out = **in
|
||||||
|
}
|
||||||
|
if in.NodeSelector != nil {
|
||||||
|
in, out := &in.NodeSelector, &out.NodeSelector
|
||||||
|
*out = new(v1.LabelSelector)
|
||||||
|
(*in).DeepCopyInto(*out)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeSpec.
|
||||||
|
func (in *OSUpgradeSpec) DeepCopy() *OSUpgradeSpec {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeSpec)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *OSUpgradeStatus) DeepCopyInto(out *OSUpgradeStatus) {
|
||||||
|
*out = *in
|
||||||
|
if in.Conditions != nil {
|
||||||
|
in, out := &in.Conditions, &out.Conditions
|
||||||
|
*out = make([]v1.Condition, len(*in))
|
||||||
|
for i := range *in {
|
||||||
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeStatus.
|
||||||
|
func (in *OSUpgradeStatus) DeepCopy() *OSUpgradeStatus {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(OSUpgradeStatus)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
func (in *VersionCatalogSource) DeepCopyInto(out *VersionCatalogSource) {
|
||||||
|
*out = *in
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VersionCatalogSource.
|
||||||
|
func (in *VersionCatalogSource) DeepCopy() *VersionCatalogSource {
|
||||||
|
if in == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := new(VersionCatalogSource)
|
||||||
|
in.DeepCopyInto(out)
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -23,7 +23,7 @@ func NewRegistry(ctx *node.NodeContext) *Registry {
|
|||||||
|
|
||||||
return &Registry{
|
return &Registry{
|
||||||
steps: map[string]node.Step{
|
steps: map[string]node.Step{
|
||||||
"ApplyControlAgentDaemonSetResources": node.ApplyControlAgentDaemonSetResources,
|
"ApplyNodeControlDaemonSetResources": node.ApplyNodeControlDaemonSetResources,
|
||||||
"ApplyLocalNodeMetadataIfPossible": node.ApplyLocalNodeMetadataIfPossible,
|
"ApplyLocalNodeMetadataIfPossible": node.ApplyLocalNodeMetadataIfPossible,
|
||||||
"CheckForVersionSkew": node.CheckForVersionSkew,
|
"CheckForVersionSkew": node.CheckForVersionSkew,
|
||||||
"ClassifyBootstrapAction": node.ClassifyBootstrapAction,
|
"ClassifyBootstrapAction": node.ClassifyBootstrapAction,
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ func NewRunner(cfg *monov1alpha1.MonoKSConfig) *Runner {
|
|||||||
Desc: "Make A/B booting possible",
|
Desc: "Make A/B booting possible",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
RegKey: "ApplyControlAgentDaemonSetResources",
|
RegKey: "ApplyNodeControlDaemonSetResources",
|
||||||
Name: "Apply daemonset for control agent",
|
Name: "Apply daemonset for control agent",
|
||||||
Desc: "Control agent handles OSUpgrade resources",
|
Desc: "Control agent handles OSUpgrade resources",
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,10 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
@@ -23,19 +20,18 @@ import (
|
|||||||
"example.com/monok8s/pkg/templates"
|
"example.com/monok8s/pkg/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultPollInterval = 15 * time.Second
|
|
||||||
|
|
||||||
var runtimeDefaultUnstructuredConverter = runtime.DefaultUnstructuredConverter
|
|
||||||
|
|
||||||
func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||||
var namespace string
|
|
||||||
var envFile string
|
var envFile string
|
||||||
var pollInterval time.Duration
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "agent --env-file path",
|
Use: "agent --env-file path",
|
||||||
Short: "Watch OSUpgrade resources and process matching upgrades for this node",
|
Short: "Watch OSUpgradeProgress resources for this node and process upgrades",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
|
ns, _, err := flags.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if envFile == "" {
|
if envFile == "" {
|
||||||
return fmt.Errorf("--env-file is required")
|
return fmt.Errorf("--env-file is required")
|
||||||
}
|
}
|
||||||
@@ -59,9 +55,8 @@ func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
|||||||
|
|
||||||
klog.InfoS("starting agent",
|
klog.InfoS("starting agent",
|
||||||
"node", cfg.Spec.NodeName,
|
"node", cfg.Spec.NodeName,
|
||||||
"namespace", namespace,
|
"namespace", ns,
|
||||||
"envFile", envFile,
|
"envFile", envFile,
|
||||||
"pollInterval", pollInterval,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
clients, err := kube.NewClients(flags)
|
clients, err := kube.NewClients(flags)
|
||||||
@@ -69,13 +64,11 @@ func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
|||||||
return fmt.Errorf("create kube clients: %w", err)
|
return fmt.Errorf("create kube clients: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return runPollLoop(ctx, clients, namespace, cfg.Spec.NodeName, pollInterval)
|
return runWatchLoop(ctx, clients, ns, cfg.Spec.NodeName)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.Flags().StringVar(&namespace, "namespace", "kube-system", "namespace to watch")
|
|
||||||
cmd.Flags().StringVar(&envFile, "env-file", "", "path to env file containing MKS_* variables")
|
cmd.Flags().StringVar(&envFile, "env-file", "", "path to env file containing MKS_* variables")
|
||||||
cmd.Flags().DurationVar(&pollInterval, "poll-interval", defaultPollInterval, "poll interval for OSUpgrade resources")
|
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -94,9 +87,9 @@ func waitForControlGate(ctx context.Context, envFile string, pollInterval time.D
|
|||||||
for {
|
for {
|
||||||
_, err := os.Stat(marker)
|
_, err := os.Stat(marker)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.InfoS("Control gate is present; waiting before starting poll loop", "path", marker)
|
klog.InfoS("Control gate is present; waiting before starting watch loop", "path", marker)
|
||||||
} else if os.IsNotExist(err) {
|
} else if os.IsNotExist(err) {
|
||||||
klog.InfoS("Control gate not present; starting poll loop", "path", marker)
|
klog.InfoS("Control gate not present; starting watch loop", "path", marker)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return fmt.Errorf("stat upgrade marker %s: %w", marker, err)
|
return fmt.Errorf("stat upgrade marker %s: %w", marker, err)
|
||||||
@@ -110,128 +103,150 @@ func waitForControlGate(ctx context.Context, envFile string, pollInterval time.D
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runPollLoop(ctx context.Context, clients *kube.Clients, namespace, nodeName string, interval time.Duration) error {
|
func runWatchLoop(ctx context.Context, clients *kube.Clients, namespace, nodeName string) error {
|
||||||
gvr := schema.GroupVersionResource{
|
var resourceVersion string
|
||||||
Group: monov1alpha1.Group,
|
|
||||||
Version: monov1alpha1.Version,
|
|
||||||
Resource: "osupgrades",
|
|
||||||
}
|
|
||||||
|
|
||||||
ticker := time.NewTicker(interval)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if err := pollOnce(ctx, clients, gvr, namespace, nodeName); err != nil {
|
if ctx.Err() != nil {
|
||||||
klog.ErrorS(err, "poll failed", "namespace", namespace, "node", nodeName)
|
return ctx.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err := watchOnce(ctx, clients, namespace, nodeName, &resourceVersion)
|
||||||
|
if err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
klog.ErrorS(err, "watch failed; retrying",
|
||||||
|
"namespace", namespace,
|
||||||
|
"node", nodeName,
|
||||||
|
"resourceVersion", resourceVersion,
|
||||||
|
)
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
case <-ticker.C:
|
case <-time.After(2 * time.Second):
|
||||||
|
}
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pollOnce(
|
func watchOnce(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
clients *kube.Clients,
|
clients *kube.Clients,
|
||||||
gvr schema.GroupVersionResource,
|
|
||||||
namespace string,
|
namespace string,
|
||||||
nodeName string,
|
nodeName string,
|
||||||
|
resourceVersion *string,
|
||||||
) error {
|
) error {
|
||||||
list, err := clients.Dynamic.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{})
|
|
||||||
|
list, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgradeProgresses(namespace).
|
||||||
|
List(ctx, metav1.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("list osupgrades: %w", err)
|
return fmt.Errorf("list osupgradeprogresses: %w", err)
|
||||||
}
|
|
||||||
|
|
||||||
klog.InfoS("agent tick", "namespace", namespace, "items", len(list.Items), "node", nodeName)
|
|
||||||
|
|
||||||
nodeLabels := labels.Set{
|
|
||||||
"kubernetes.io/hostname": nodeName,
|
|
||||||
"monok8s.io/node-name": nodeName,
|
|
||||||
"monok8s.io/control-agent": "true",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := range list.Items {
|
for i := range list.Items {
|
||||||
item := &list.Items[i]
|
item := &list.Items[i]
|
||||||
|
if !targetsNode(item, nodeName) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
osu, err := decodeOSUpgrade(item)
|
klog.InfoS("found existing osupgradeprogress",
|
||||||
|
"name", item.Name,
|
||||||
|
"node", nodeName,
|
||||||
|
"phase", item.StatusPhase(),
|
||||||
|
"resourceVersion", item.ResourceVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
if err := osupgradeController.HandleOSUpgradeProgress(ctx, clients, namespace, nodeName, item); err != nil {
|
||||||
|
klog.ErrorS(err, "failed to handle existing osupgradeprogress",
|
||||||
|
"name", item.Name,
|
||||||
|
"node", nodeName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*resourceVersion = list.ResourceVersion
|
||||||
|
|
||||||
|
w, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgradeProgresses(namespace).
|
||||||
|
Watch(ctx, metav1.ListOptions{
|
||||||
|
ResourceVersion: *resourceVersion,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "failed to decode osupgrade",
|
return fmt.Errorf("watch osupgradeprogresses: %w", err)
|
||||||
"name", item.GetName(),
|
}
|
||||||
"resourceVersion", item.GetResourceVersion(),
|
defer w.Stop()
|
||||||
|
|
||||||
|
klog.InfoS("watching osupgradeprogresses",
|
||||||
|
"namespace", namespace,
|
||||||
|
"node", nodeName,
|
||||||
|
"resourceVersion", *resourceVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
|
||||||
|
case evt, ok := <-w.ResultChan():
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("watch channel closed")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch evt.Type {
|
||||||
|
case watch.Bookmark:
|
||||||
|
obj, ok := evt.Object.(*monov1alpha1.OSUpgradeProgress)
|
||||||
|
if ok && obj != nil && obj.ResourceVersion != "" {
|
||||||
|
*resourceVersion = obj.ResourceVersion
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
case watch.Error:
|
||||||
|
return fmt.Errorf("watch returned error event")
|
||||||
|
}
|
||||||
|
|
||||||
|
osup, ok := evt.Object.(*monov1alpha1.OSUpgradeProgress)
|
||||||
|
if !ok {
|
||||||
|
klog.V(1).InfoS("skipping unexpected watch object type",
|
||||||
|
"type", fmt.Sprintf("%T", evt.Object),
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !matchesNode(osu, nodeName, nodeLabels) {
|
if osup.ResourceVersion != "" {
|
||||||
klog.V(2).InfoS("skipping osupgrade; not targeted to this node",
|
*resourceVersion = osup.ResourceVersion
|
||||||
"name", osu.Name,
|
}
|
||||||
"node", nodeName,
|
|
||||||
)
|
if !targetsNode(osup, nodeName) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.InfoS("matched osupgrade",
|
klog.V(4).InfoS("received osupgradeprogress event",
|
||||||
"name", osu.Name,
|
"name", osup.Name,
|
||||||
"node", nodeName,
|
"node", nodeName,
|
||||||
"desiredVersion", osu.Spec.DesiredVersion,
|
"phase", osup.StatusPhase(),
|
||||||
"phase", statusPhase(osu.Status),
|
"eventType", evt.Type,
|
||||||
"resourceVersion", osu.ResourceVersion,
|
"resourceVersion", osup.ResourceVersion,
|
||||||
)
|
)
|
||||||
|
|
||||||
if err := osupgradeController.HandleOSUpgrade(ctx, clients, namespace, nodeName, osu); err != nil {
|
if err := osupgradeController.HandleOSUpgradeProgress(ctx, clients, namespace, nodeName, osup); err != nil {
|
||||||
klog.ErrorS(err, "failed to handle osupgrade",
|
klog.ErrorS(err, "failed to handle osupgradeprogress",
|
||||||
"name", osu.Name,
|
"name", osup.Name,
|
||||||
"node", nodeName,
|
"node", nodeName,
|
||||||
|
"eventType", evt.Type,
|
||||||
)
|
)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func decodeOSUpgrade(item *unstructured.Unstructured) (*monov1alpha1.OSUpgrade, error) {
|
func targetsNode(osup *monov1alpha1.OSUpgradeProgress, nodeName string) bool {
|
||||||
var osu monov1alpha1.OSUpgrade
|
if osup == nil {
|
||||||
if err := runtimeDefaultUnstructuredConverter.FromUnstructured(item.Object, &osu); err != nil {
|
|
||||||
return nil, fmt.Errorf("convert unstructured to OSUpgrade: %w", err)
|
|
||||||
}
|
|
||||||
return &osu, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func matchesNode(osu *monov1alpha1.OSUpgrade, nodeName string, nodeLabels labels.Set) bool {
|
|
||||||
if osu == nil {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
return osup.Spec.NodeName == nodeName
|
||||||
sel := osu.Spec.NodeSelector
|
|
||||||
if sel == nil {
|
|
||||||
// No selector means "match all nodes".
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
selector, err := metav1.LabelSelectorAsSelector(sel)
|
|
||||||
if err != nil {
|
|
||||||
klog.ErrorS(err, "invalid node selector on osupgrade", "name", osu.Name)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if selector.Empty() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if selector.Matches(nodeLabels) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func statusPhase(st *monov1alpha1.OSUpgradeStatus) string {
|
|
||||||
if st == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return string(st.Phase)
|
|
||||||
}
|
}
|
||||||
|
|||||||
217
clitools/pkg/cmd/controller/controller.go
Normal file
217
clitools/pkg/cmd/controller/controller.go
Normal file
@@ -0,0 +1,217 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
mkscontroller "example.com/monok8s/pkg/controller"
|
||||||
|
osupgradectrl "example.com/monok8s/pkg/controller/osupgrade"
|
||||||
|
"example.com/monok8s/pkg/kube"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ServerConfig struct {
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
TLSCertFile string `json:"tlsCertFile,omitempty"`
|
||||||
|
TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmdController(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||||
|
var conf ServerConfig
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "controller",
|
||||||
|
Short: "Start a controller that handles OSUpgrade resources",
|
||||||
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
|
ns, _, err := flags.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
conf.Namespace = ns
|
||||||
|
|
||||||
|
ctx := cmd.Context()
|
||||||
|
|
||||||
|
klog.InfoS("starting controller", "namespace", conf.Namespace)
|
||||||
|
|
||||||
|
clients, err := kube.NewClients(flags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
httpErrCh := make(chan error, 1)
|
||||||
|
watchErrCh := make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
klog.InfoS("starting OSUpgrade watch loop", "namespace", conf.Namespace)
|
||||||
|
watchErrCh <- osupgradectrl.Watch(ctx, clients, conf.Namespace)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
httpErrCh <- listenAndServe(ctx, clients, conf)
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
klog.InfoS("controller context canceled")
|
||||||
|
return ctx.Err()
|
||||||
|
|
||||||
|
case err := <-watchErrCh:
|
||||||
|
if err != nil && !errors.Is(err, context.Canceled) {
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case err := <-httpErrCh:
|
||||||
|
if err != nil && !errors.Is(err, context.Canceled) {
|
||||||
|
cancel()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cancel()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.Flags().StringVar(&conf.TLSCertFile, "tls-cert-file", conf.TLSCertFile,
|
||||||
|
"File containing x509 Certificate used for serving HTTPS (with intermediate certs, if any, concatenated after server cert).")
|
||||||
|
cmd.Flags().StringVar(&conf.TLSPrivateKeyFile, "tls-private-key-file", conf.TLSPrivateKeyFile,
|
||||||
|
"File containing x509 private key matching --tls-cert-file.")
|
||||||
|
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func listenAndServe(ctx context.Context, clients *kube.Clients, conf ServerConfig) error {
|
||||||
|
nodeName := os.Getenv("NODE_NAME")
|
||||||
|
|
||||||
|
controllerServer := mkscontroller.NewServer(ctx, clients, conf.Namespace, nodeName)
|
||||||
|
|
||||||
|
healthMux := http.NewServeMux()
|
||||||
|
healthMux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("ok\n"))
|
||||||
|
})
|
||||||
|
healthMux.HandleFunc("/readyz", func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("ok\n"))
|
||||||
|
})
|
||||||
|
|
||||||
|
healthAddr := net.JoinHostPort("", "8080")
|
||||||
|
controllerAddr := net.JoinHostPort("", "8443")
|
||||||
|
|
||||||
|
healthHTTPServer := &http.Server{
|
||||||
|
Addr: healthAddr,
|
||||||
|
Handler: healthMux,
|
||||||
|
IdleTimeout: 90 * time.Second,
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
MaxHeaderBytes: 1 << 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
controllerHTTPServer := &http.Server{
|
||||||
|
Addr: controllerAddr,
|
||||||
|
Handler: controllerServer,
|
||||||
|
IdleTimeout: 90 * time.Second,
|
||||||
|
ReadTimeout: 4 * time.Minute,
|
||||||
|
WriteTimeout: 4 * time.Minute,
|
||||||
|
MaxHeaderBytes: 1 << 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
serverErrCh := make(chan error, 2)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
klog.InfoS("starting health HTTP server", "addr", healthAddr)
|
||||||
|
|
||||||
|
err := healthHTTPServer.ListenAndServe()
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
serverErrCh <- fmt.Errorf("health HTTP server: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serverErrCh <- nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
if conf.TLSCertFile != "" {
|
||||||
|
klog.InfoS("starting controller HTTPS server",
|
||||||
|
"addr", controllerAddr,
|
||||||
|
"certFile", conf.TLSCertFile,
|
||||||
|
"keyFile", conf.TLSPrivateKeyFile,
|
||||||
|
)
|
||||||
|
|
||||||
|
err := controllerHTTPServer.ListenAndServeTLS(conf.TLSCertFile, conf.TLSPrivateKeyFile)
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
serverErrCh <- fmt.Errorf("controller HTTPS server: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serverErrCh <- nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.InfoS("starting controller HTTP server", "addr", controllerAddr)
|
||||||
|
|
||||||
|
err := controllerHTTPServer.ListenAndServe()
|
||||||
|
if err != nil && !errors.Is(err, http.ErrServerClosed) {
|
||||||
|
serverErrCh <- fmt.Errorf("controller HTTP server: %w", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
serverErrCh <- nil
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
klog.InfoS("shutting down HTTP servers",
|
||||||
|
"healthAddr", healthAddr,
|
||||||
|
"controllerAddr", controllerAddr,
|
||||||
|
)
|
||||||
|
|
||||||
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
if err := healthHTTPServer.Shutdown(shutdownCtx); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("shutdown health HTTP server: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := controllerHTTPServer.Shutdown(shutdownCtx); err != nil {
|
||||||
|
errs = append(errs, fmt.Errorf("shutdown controller HTTP server: %w", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < 2; i++ {
|
||||||
|
if err := <-serverErrCh; err != nil {
|
||||||
|
errs = append(errs, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return errors.Join(errs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return context.Canceled
|
||||||
|
|
||||||
|
case err := <-serverErrCh:
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "HTTP server failed")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// One server exited cleanly unexpectedly. Treat that as failure because
|
||||||
|
// the process should keep both servers alive until ctx is canceled.
|
||||||
|
return fmt.Errorf("HTTP server exited unexpectedly")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
package create
|
package create
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"os"
|
||||||
|
|
||||||
render "example.com/monok8s/pkg/render"
|
render "example.com/monok8s/pkg/render"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewCmdCreate() *cobra.Command {
|
func NewCmdCreate(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||||
cmd := &cobra.Command{Use: "create", Short: "Create starter resources"}
|
cmd := &cobra.Command{Use: "create", Short: "Create starter resources"}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
&cobra.Command{
|
&cobra.Command{
|
||||||
@@ -26,7 +29,12 @@ func NewCmdCreate() *cobra.Command {
|
|||||||
Use: "osupgrade",
|
Use: "osupgrade",
|
||||||
Short: "Print an OSUpgrade template",
|
Short: "Print an OSUpgrade template",
|
||||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
out, err := render.RenderOSUpgrade()
|
ns, _, err := flags.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := render.RenderOSUpgrade(ns)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -35,5 +43,84 @@ func NewCmdCreate() *cobra.Command {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var authorizedKeysPath string
|
||||||
|
|
||||||
|
sshdcmd := cobra.Command{
|
||||||
|
Use: "sshd",
|
||||||
|
Short: "Print sshd deployment template",
|
||||||
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
|
ns, _, err := flags.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
authorizedKeys, err := readAuthorizedKeysFile(authorizedKeysPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
out, err := render.RenderSSHDDeployments(ns, authorizedKeys)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fmt.Fprint(cmd.OutOrStdout(), out)
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
sshdcmd.Flags().StringVar(&authorizedKeysPath, "authkeys", "", "path to authorized_keys file")
|
||||||
|
|
||||||
|
cmd.AddCommand(&sshdcmd)
|
||||||
|
|
||||||
|
cconf := render.ControllerConf{}
|
||||||
|
controllercmd := cobra.Command{
|
||||||
|
Use: "controller",
|
||||||
|
Short: "Print controller deployment template",
|
||||||
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||||
|
ns, _, err := flags.ToRawKubeConfigLoader().Namespace()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
cconf.Namespace = ns
|
||||||
|
|
||||||
|
out, err := render.RenderControllerDeployments(cconf)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = fmt.Fprint(cmd.OutOrStdout(), out)
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
controllercmd.Flags().StringVar(
|
||||||
|
&cconf.Image,
|
||||||
|
"image",
|
||||||
|
"",
|
||||||
|
"Controller image, including optional registry and tag",
|
||||||
|
)
|
||||||
|
|
||||||
|
cmd.AddCommand(&controllercmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func readAuthorizedKeysFile(path string) (string, error) {
|
||||||
|
if path == "" {
|
||||||
|
return "", fmt.Errorf("--authkeys is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := os.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("read authorized_keys file %q: %w", path, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(bytes.TrimSpace(b)) == 0 {
|
||||||
|
return "", fmt.Errorf("authorized_keys file %q is empty", path)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(b), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
|
|
||||||
agentcmd "example.com/monok8s/pkg/cmd/agent"
|
agentcmd "example.com/monok8s/pkg/cmd/agent"
|
||||||
checkconfigcmd "example.com/monok8s/pkg/cmd/checkconfig"
|
checkconfigcmd "example.com/monok8s/pkg/cmd/checkconfig"
|
||||||
|
controllercmd "example.com/monok8s/pkg/cmd/controller"
|
||||||
createcmd "example.com/monok8s/pkg/cmd/create"
|
createcmd "example.com/monok8s/pkg/cmd/create"
|
||||||
initcmd "example.com/monok8s/pkg/cmd/initcmd"
|
initcmd "example.com/monok8s/pkg/cmd/initcmd"
|
||||||
internalcmd "example.com/monok8s/pkg/cmd/internal"
|
internalcmd "example.com/monok8s/pkg/cmd/internal"
|
||||||
@@ -18,8 +19,10 @@ import (
|
|||||||
func init() {
|
func init() {
|
||||||
klog.InitFlags(nil)
|
klog.InitFlags(nil)
|
||||||
|
|
||||||
|
_ = flag.Set("logtostderr", "true")
|
||||||
|
|
||||||
if os.Getenv("DEBUG") != "" {
|
if os.Getenv("DEBUG") != "" {
|
||||||
_ = flag.Set("v", "4") // debug level
|
_ = flag.Set("v", "4")
|
||||||
} else {
|
} else {
|
||||||
_ = flag.Set("v", "0")
|
_ = flag.Set("v", "0")
|
||||||
}
|
}
|
||||||
@@ -38,14 +41,20 @@ func NewRootCmd() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose klog stdlib flags through Cobra/pflag.
|
||||||
|
cmd.PersistentFlags().AddGoFlagSet(flag.CommandLine)
|
||||||
|
|
||||||
flags.AddFlags(cmd.PersistentFlags())
|
flags.AddFlags(cmd.PersistentFlags())
|
||||||
|
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
versioncmd.NewCmdVersion(),
|
versioncmd.NewCmdVersion(),
|
||||||
initcmd.NewCmdInit(flags),
|
initcmd.NewCmdInit(flags),
|
||||||
checkconfigcmd.NewCmdCheckConfig(),
|
checkconfigcmd.NewCmdCheckConfig(),
|
||||||
createcmd.NewCmdCreate(),
|
createcmd.NewCmdCreate(flags),
|
||||||
agentcmd.NewCmdAgent(flags),
|
agentcmd.NewCmdAgent(flags),
|
||||||
|
controllercmd.NewCmdController(flags),
|
||||||
internalcmd.NewCmdInternal(),
|
internalcmd.NewCmdInternal(),
|
||||||
)
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,26 +41,62 @@ func (r *UpgradeRunner) Run(fn func() error) error {
|
|||||||
return fn()
|
return fn()
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleOSUpgrade(ctx context.Context, clients *kube.Clients,
|
func HandleOSUpgradeProgress(
|
||||||
namespace string, nodeName string,
|
ctx context.Context,
|
||||||
osu *monov1alpha1.OSUpgrade,
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
nodeName string,
|
||||||
|
osup *monov1alpha1.OSUpgradeProgress,
|
||||||
) error {
|
) error {
|
||||||
return r.Run(func() error {
|
return r.Run(func() error {
|
||||||
return handleOSUpgradeLocked(ctx, clients, namespace, nodeName, osu)
|
return handleOSUpgradeProgressLocked(ctx, clients, namespace, nodeName, osup)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleOSUpgradeLocked(ctx context.Context, clients *kube.Clients,
|
func handleOSUpgradeProgressLocked(
|
||||||
namespace string, nodeName string,
|
ctx context.Context,
|
||||||
osu *monov1alpha1.OSUpgrade,
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
nodeName string,
|
||||||
|
osup *monov1alpha1.OSUpgradeProgress,
|
||||||
) error {
|
) error {
|
||||||
osup, err := ensureProgressHeartbeat(ctx, clients, namespace, nodeName, osu)
|
if osup == nil {
|
||||||
if err != nil {
|
return fmt.Errorf("osupgradeprogress is nil")
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.InfoS("handling osupgrade",
|
if osup.Spec.NodeName != nodeName {
|
||||||
"name", osu.Name,
|
klog.V(4).InfoS("skipping osupgradeprogress due to nodeName mismatch",
|
||||||
|
"name", osup.Name,
|
||||||
|
"node", nodeName,
|
||||||
|
"target", osup.Spec.NodeName,
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !shouldProcessProgress(osup) {
|
||||||
|
klog.V(2).InfoS("skipping osupgradeprogress due to phase",
|
||||||
|
"name", osup.Name,
|
||||||
|
"node", nodeName,
|
||||||
|
"phase", osup.StatusPhase(),
|
||||||
|
)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
parentName := osup.Spec.SourceRef.Name
|
||||||
|
if parentName == "" {
|
||||||
|
return failProgress(ctx, clients, osup, "resolve parent osupgrade", fmt.Errorf("missing spec.osUpgradeName"))
|
||||||
|
}
|
||||||
|
|
||||||
|
osu, err := clients.MonoKS.Monok8sV1alpha1().
|
||||||
|
OSUpgrades(namespace).
|
||||||
|
Get(ctx, parentName, metav1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return failProgress(ctx, clients, osup, "resolve parent osupgrade", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.InfoS("handling osupgradeprogress",
|
||||||
|
"name", osup.Name,
|
||||||
|
"osupgrade", osu.Name,
|
||||||
"node", nodeName,
|
"node", nodeName,
|
||||||
"desiredVersion", osu.Spec.DesiredVersion,
|
"desiredVersion", osu.Spec.DesiredVersion,
|
||||||
)
|
)
|
||||||
@@ -95,7 +131,9 @@ func handleOSUpgradeLocked(ctx context.Context, clients *kube.Clients,
|
|||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
cur.Status.CurrentVersion = buildinfo.KubeVersion
|
cur.Status.CurrentVersion = buildinfo.KubeVersion
|
||||||
cur.Status.TargetVersion = plan.ResolvedTarget
|
cur.Status.TargetVersion = plan.ResolvedTarget
|
||||||
|
cur.Status.PlannedPath = plannedPath(plan)
|
||||||
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseDownloading
|
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseDownloading
|
||||||
|
cur.Status.ObservedRetryNonce = cur.Spec.RetryNonce
|
||||||
cur.Status.Message = fmt.Sprintf("downloading image: %s", first.URL)
|
cur.Status.Message = fmt.Sprintf("downloading image: %s", first.URL)
|
||||||
cur.Status.LastUpdatedAt = &now
|
cur.Status.LastUpdatedAt = &now
|
||||||
})
|
})
|
||||||
@@ -209,6 +247,27 @@ func handleOSUpgradeLocked(ctx context.Context, clients *kube.Clients,
|
|||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldProcessProgress(osup *monov1alpha1.OSUpgradeProgress) bool {
|
||||||
|
if osup == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if osup.Status == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
switch osup.Status.Phase {
|
||||||
|
case "",
|
||||||
|
monov1alpha1.OSUpgradeProgressPhasePending,
|
||||||
|
monov1alpha1.OSUpgradeProgressPhaseRebooting:
|
||||||
|
return true
|
||||||
|
case monov1alpha1.OSUpgradeProgressPhaseFailed:
|
||||||
|
return osup.Spec.RetryNonce != osup.Status.ObservedRetryNonce
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func triggerReboot() error {
|
func triggerReboot() error {
|
||||||
_ = os.WriteFile("/proc/sysrq-trigger", []byte("s\n"), 0)
|
_ = os.WriteFile("/proc/sysrq-trigger", []byte("s\n"), 0)
|
||||||
_ = os.WriteFile("/proc/sysrq-trigger", []byte("u\n"), 0)
|
_ = os.WriteFile("/proc/sysrq-trigger", []byte("u\n"), 0)
|
||||||
|
|||||||
@@ -335,6 +335,14 @@ func lowestPatchInMinor(versions []Version, major, minor int) (Version, bool) {
|
|||||||
return Version{}, false
|
return Version{}, false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func plannedPath(plan *Plan) []string {
|
||||||
|
ppath := []string{}
|
||||||
|
for _, img := range plan.Path {
|
||||||
|
ppath = append(ppath, img.Version)
|
||||||
|
}
|
||||||
|
return ppath
|
||||||
|
}
|
||||||
|
|
||||||
func versionsToStrings(vs []Version) []string {
|
func versionsToStrings(vs []Version) []string {
|
||||||
out := make([]string, 0, len(vs))
|
out := make([]string, 0, len(vs))
|
||||||
for _, v := range vs {
|
for _, v := range vs {
|
||||||
|
|||||||
@@ -7,40 +7,27 @@ import (
|
|||||||
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
"example.com/monok8s/pkg/buildinfo"
|
|
||||||
"example.com/monok8s/pkg/kube"
|
"example.com/monok8s/pkg/kube"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
func EnsureOSUpgradeProgressForNode(
|
||||||
unstructuredConverter = runtime.DefaultUnstructuredConverter
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
osup_gvr = schema.GroupVersionResource{
|
namespace string,
|
||||||
Group: monov1alpha1.Group,
|
nodeName string,
|
||||||
Version: monov1alpha1.Version,
|
|
||||||
Resource: "osupgradeprogresses",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func ensureProgressHeartbeat(ctx context.Context, clients *kube.Clients,
|
|
||||||
namespace string, nodeName string,
|
|
||||||
osu *monov1alpha1.OSUpgrade,
|
osu *monov1alpha1.OSUpgrade,
|
||||||
) (*monov1alpha1.OSUpgradeProgress, error) {
|
) error {
|
||||||
|
if osu == nil {
|
||||||
|
return fmt.Errorf("osupgrade is nil")
|
||||||
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("%s-%s", osu.Name, nodeName)
|
name := fmt.Sprintf("%s-%s", osu.Name, nodeName)
|
||||||
now := metav1.Now()
|
now := metav1.Now()
|
||||||
|
|
||||||
currentVersion := buildinfo.KubeVersion
|
|
||||||
targetVersion := ""
|
|
||||||
if osu.Status != nil {
|
|
||||||
targetVersion = osu.Status.ResolvedVersion
|
|
||||||
}
|
|
||||||
|
|
||||||
progress := &monov1alpha1.OSUpgradeProgress{
|
progress := &monov1alpha1.OSUpgradeProgress{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
APIVersion: monov1alpha1.APIVersion,
|
APIVersion: monov1alpha1.APIVersion,
|
||||||
@@ -57,83 +44,38 @@ func ensureProgressHeartbeat(ctx context.Context, clients *kube.Clients,
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Status: &monov1alpha1.OSUpgradeProgressStatus{
|
Status: &monov1alpha1.OSUpgradeProgressStatus{
|
||||||
CurrentVersion: currentVersion,
|
|
||||||
TargetVersion: targetVersion,
|
|
||||||
Phase: monov1alpha1.OSUpgradeProgressPhasePending,
|
Phase: monov1alpha1.OSUpgradeProgressPhasePending,
|
||||||
LastUpdatedAt: &now,
|
LastUpdatedAt: &now,
|
||||||
Message: "acknowledged",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := createProgress(ctx, clients, osup_gvr, progress)
|
created, err := createProgress(ctx, clients, progress)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
klog.InfoS("created osupgradeprogress", "name", created.Name, "namespace", created.Namespace)
|
klog.InfoS("created osupgradeprogress", "name", created.Name, "namespace", created.Namespace)
|
||||||
return created, nil
|
return nil
|
||||||
}
|
}
|
||||||
if !apierrors.IsAlreadyExists(err) {
|
if !apierrors.IsAlreadyExists(err) {
|
||||||
return nil, fmt.Errorf("create OSUpgradeProgress %s/%s: %w", namespace, name, err)
|
return fmt.Errorf("create OSUpgradeProgress %s/%s: %w", namespace, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var out *monov1alpha1.OSUpgradeProgress
|
existing, err := getProgress(ctx, clients, namespace, name)
|
||||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
|
||||||
existing, err := getProgress(ctx, clients, osup_gvr, namespace, name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("get existing OSUpgradeProgress %s/%s: %w", namespace, name, err)
|
return fmt.Errorf("get existing OSUpgradeProgress %s/%s: %w", namespace, name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep spec aligned with source and node.
|
if existing.Spec.NodeName != nodeName || existing.Spec.SourceRef.Name != osu.Name {
|
||||||
existing.Spec.NodeName = nodeName
|
return fmt.Errorf(
|
||||||
existing.Spec.SourceRef.Name = osu.Name
|
"conflicting OSUpgradeProgress %s/%s already exists: got spec.nodeName=%q spec.sourceRef.name=%q, want nodeName=%q sourceRef.name=%q",
|
||||||
|
namespace,
|
||||||
existing, err = updateProgressSpec(ctx, clients, osup_gvr, existing)
|
name,
|
||||||
if err != nil {
|
existing.Spec.NodeName,
|
||||||
if isUnknownUpdateResult(err) {
|
existing.Spec.SourceRef.Name,
|
||||||
latest, getErr := getProgress(ctx, clients, osup_gvr, namespace, name)
|
nodeName,
|
||||||
if getErr == nil {
|
osu.Name,
|
||||||
out = latest
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("update OSUpgradeProgress spec %s/%s: %w", namespace, name, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if existing.Status == nil {
|
|
||||||
existing.Status = &monov1alpha1.OSUpgradeProgressStatus{}
|
|
||||||
}
|
|
||||||
|
|
||||||
existing.Status.CurrentVersion = currentVersion
|
|
||||||
existing.Status.TargetVersion = targetVersion
|
|
||||||
existing.Status.LastUpdatedAt = &now
|
|
||||||
|
|
||||||
if existing.Status.Phase == "" {
|
|
||||||
existing.Status.Phase = monov1alpha1.OSUpgradeProgressPhasePending
|
|
||||||
}
|
|
||||||
if existing.Status.Message == "" {
|
|
||||||
existing.Status.Message = "acknowledged"
|
|
||||||
}
|
|
||||||
|
|
||||||
existing, err = updateProgressStatus(ctx, clients, osup_gvr, existing)
|
|
||||||
if err != nil {
|
|
||||||
if isUnknownUpdateResult(err) {
|
|
||||||
latest, getErr := getProgress(ctx, clients, osup_gvr, namespace, name)
|
|
||||||
if getErr == nil {
|
|
||||||
out = latest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return fmt.Errorf("update OSUpgradeProgress status %s/%s: %w", namespace, name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out = existing
|
|
||||||
return nil
|
return nil
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
if out != nil {
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
klog.InfoS("updated osupgradeprogress", "name", out.Name, "namespace", out.Namespace)
|
|
||||||
return out, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateProgressRobust(
|
func updateProgressRobust(
|
||||||
@@ -146,7 +88,7 @@ func updateProgressRobust(
|
|||||||
var out *monov1alpha1.OSUpgradeProgress
|
var out *monov1alpha1.OSUpgradeProgress
|
||||||
|
|
||||||
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||||
current, err := getProgress(ctx, clients, osup_gvr, namespace, name)
|
current, err := getProgress(ctx, clients, namespace, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -157,10 +99,10 @@ func updateProgressRobust(
|
|||||||
|
|
||||||
mutate(current)
|
mutate(current)
|
||||||
|
|
||||||
updated, err := updateProgressStatus(ctx, clients, osup_gvr, current)
|
updated, err := updateProgressStatus(ctx, clients, current)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isUnknownUpdateResult(err) {
|
if isUnknownUpdateResult(err) {
|
||||||
latest, getErr := getProgress(ctx, clients, osup_gvr, namespace, name)
|
latest, getErr := getProgress(ctx, clients, namespace, name)
|
||||||
if getErr == nil {
|
if getErr == nil {
|
||||||
out = latest
|
out = latest
|
||||||
}
|
}
|
||||||
@@ -202,84 +144,55 @@ func isUnknownUpdateResult(err error) bool {
|
|||||||
func createProgress(
|
func createProgress(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
clients *kube.Clients,
|
clients *kube.Clients,
|
||||||
gvr schema.GroupVersionResource,
|
|
||||||
progress *monov1alpha1.OSUpgradeProgress,
|
progress *monov1alpha1.OSUpgradeProgress,
|
||||||
) (*monov1alpha1.OSUpgradeProgress, error) {
|
) (*monov1alpha1.OSUpgradeProgress, error) {
|
||||||
obj, err := toUnstructured(progress)
|
toCreate := progress.DeepCopy()
|
||||||
|
toCreate.Status = nil
|
||||||
|
|
||||||
|
created, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgradeProgresses(toCreate.Namespace).
|
||||||
|
Create(ctx, toCreate, metav1.CreateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
created, err := clients.Dynamic.
|
if progress.Status != nil {
|
||||||
Resource(gvr).
|
toUpdate := created.DeepCopy()
|
||||||
Namespace(progress.Namespace).
|
toUpdate.Status = progress.Status
|
||||||
Create(ctx, obj, metav1.CreateOptions{})
|
return updateProgressStatus(ctx, clients, toUpdate)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return fromUnstructuredProgress(created)
|
return created, nil
|
||||||
}
|
|
||||||
|
|
||||||
func getProgress(
|
|
||||||
ctx context.Context,
|
|
||||||
clients *kube.Clients,
|
|
||||||
gvr schema.GroupVersionResource,
|
|
||||||
namespace, name string,
|
|
||||||
) (*monov1alpha1.OSUpgradeProgress, error) {
|
|
||||||
got, err := clients.Dynamic.
|
|
||||||
Resource(gvr).
|
|
||||||
Namespace(namespace).
|
|
||||||
Get(ctx, name, metav1.GetOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fromUnstructuredProgress(got)
|
|
||||||
}
|
|
||||||
|
|
||||||
func updateProgressSpec(
|
|
||||||
ctx context.Context,
|
|
||||||
clients *kube.Clients,
|
|
||||||
gvr schema.GroupVersionResource,
|
|
||||||
progress *monov1alpha1.OSUpgradeProgress,
|
|
||||||
) (*monov1alpha1.OSUpgradeProgress, error) {
|
|
||||||
obj, err := toUnstructured(progress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
updated, err := clients.Dynamic.
|
|
||||||
Resource(gvr).
|
|
||||||
Namespace(progress.Namespace).
|
|
||||||
Update(ctx, obj, metav1.UpdateOptions{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return fromUnstructuredProgress(updated)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateProgressStatus(
|
func updateProgressStatus(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
clients *kube.Clients,
|
clients *kube.Clients,
|
||||||
gvr schema.GroupVersionResource,
|
|
||||||
progress *monov1alpha1.OSUpgradeProgress,
|
progress *monov1alpha1.OSUpgradeProgress,
|
||||||
) (*monov1alpha1.OSUpgradeProgress, error) {
|
) (*monov1alpha1.OSUpgradeProgress, error) {
|
||||||
obj, err := toUnstructured(progress)
|
updated, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgradeProgresses(progress.Namespace).
|
||||||
|
UpdateStatus(ctx, progress, metav1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf(
|
||||||
|
"update status for OSUpgradeProgress %s/%s: %w",
|
||||||
|
progress.Namespace, progress.Name, err,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
return updated, nil
|
||||||
|
}
|
||||||
|
|
||||||
updated, err := clients.Dynamic.
|
func getProgress(
|
||||||
Resource(gvr).
|
ctx context.Context,
|
||||||
Namespace(progress.Namespace).
|
clients *kube.Clients,
|
||||||
UpdateStatus(ctx, obj, metav1.UpdateOptions{})
|
namespace, name string,
|
||||||
if err != nil {
|
) (*monov1alpha1.OSUpgradeProgress, error) {
|
||||||
return nil, err
|
return clients.MonoKS.
|
||||||
}
|
Monok8sV1alpha1().
|
||||||
|
OSUpgradeProgresses(namespace).
|
||||||
return fromUnstructuredProgress(updated)
|
Get(ctx, name, metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
|
|
||||||
func failProgress(
|
func failProgress(
|
||||||
@@ -296,6 +209,7 @@ func failProgress(
|
|||||||
cur.Status = &monov1alpha1.OSUpgradeProgressStatus{}
|
cur.Status = &monov1alpha1.OSUpgradeProgressStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur.Status.ObservedRetryNonce = cur.Spec.RetryNonce
|
||||||
cur.Status.LastUpdatedAt = &now
|
cur.Status.LastUpdatedAt = &now
|
||||||
cur.Status.Message = fmt.Sprintf("%s: %v", action, cause)
|
cur.Status.Message = fmt.Sprintf("%s: %v", action, cause)
|
||||||
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseFailed
|
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseFailed
|
||||||
@@ -324,6 +238,7 @@ func markProgressCompleted(
|
|||||||
cur.Status = &monov1alpha1.OSUpgradeProgressStatus{}
|
cur.Status = &monov1alpha1.OSUpgradeProgressStatus{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cur.Status.ObservedRetryNonce = cur.Spec.RetryNonce
|
||||||
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseCompleted
|
cur.Status.Phase = monov1alpha1.OSUpgradeProgressPhaseCompleted
|
||||||
cur.Status.Message = message
|
cur.Status.Message = message
|
||||||
cur.Status.CurrentVersion = osup.Status.CurrentVersion
|
cur.Status.CurrentVersion = osup.Status.CurrentVersion
|
||||||
@@ -337,19 +252,3 @@ func markProgressCompleted(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func toUnstructured(progress *monov1alpha1.OSUpgradeProgress) (*unstructured.Unstructured, error) {
|
|
||||||
m, err := unstructuredConverter.ToUnstructured(progress)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("convert OSUpgradeProgress to unstructured: %w", err)
|
|
||||||
}
|
|
||||||
return &unstructured.Unstructured{Object: m}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func fromUnstructuredProgress(obj *unstructured.Unstructured) (*monov1alpha1.OSUpgradeProgress, error) {
|
|
||||||
var progress monov1alpha1.OSUpgradeProgress
|
|
||||||
if err := unstructuredConverter.FromUnstructured(obj.Object, &progress); err != nil {
|
|
||||||
return nil, fmt.Errorf("convert unstructured to OSUpgradeProgress: %w", err)
|
|
||||||
}
|
|
||||||
return &progress, nil
|
|
||||||
}
|
|
||||||
|
|||||||
339
clitools/pkg/controller/osupgrade/watch.go
Normal file
339
clitools/pkg/controller/osupgrade/watch.go
Normal file
@@ -0,0 +1,339 @@
|
|||||||
|
package osupgrade
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
"example.com/monok8s/pkg/kube"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Watch(ctx context.Context, clients *kube.Clients, namespace string) error {
|
||||||
|
var resourceVersion string
|
||||||
|
|
||||||
|
for {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
err := watchOnce(ctx, clients, namespace, &resourceVersion)
|
||||||
|
if err != nil {
|
||||||
|
if ctx.Err() != nil {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expired RV is normal enough; clear it and relist.
|
||||||
|
if apierrors.IsResourceExpired(err) {
|
||||||
|
klog.InfoS("OSUpgrade watch resourceVersion expired; resetting",
|
||||||
|
"namespace", namespace,
|
||||||
|
"resourceVersion", resourceVersion,
|
||||||
|
)
|
||||||
|
resourceVersion = ""
|
||||||
|
} else {
|
||||||
|
klog.ErrorS(err, "OSUpgrade watch failed; retrying",
|
||||||
|
"namespace", namespace,
|
||||||
|
"resourceVersion", resourceVersion,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-time.After(2 * time.Second):
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func watchOnce(
|
||||||
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
resourceVersion *string,
|
||||||
|
) error {
|
||||||
|
// Cold start: list existing objects once, handle them, then watch from list RV.
|
||||||
|
if *resourceVersion == "" {
|
||||||
|
list, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgrades(namespace).
|
||||||
|
List(ctx, metav1.ListOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("list OSUpgrades: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := range list.Items {
|
||||||
|
osu := &list.Items[i]
|
||||||
|
handled, err := handleOSUpgrade(ctx, clients, namespace, osu)
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "reconcile existing OSUpgrade failed",
|
||||||
|
"name", osu.Name,
|
||||||
|
"resourceVersion", osu.ResourceVersion,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !handled {
|
||||||
|
klog.V(2).InfoS("skipping existing OSUpgrade",
|
||||||
|
"name", osu.Name,
|
||||||
|
"phase", osu.StatusPhase(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*resourceVersion = list.ResourceVersion
|
||||||
|
klog.InfoS("initial OSUpgrade sync complete",
|
||||||
|
"namespace", namespace,
|
||||||
|
"resourceVersion", *resourceVersion,
|
||||||
|
"count", len(list.Items),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
w, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgrades(namespace).
|
||||||
|
Watch(ctx, metav1.ListOptions{
|
||||||
|
ResourceVersion: *resourceVersion,
|
||||||
|
AllowWatchBookmarks: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("watch OSUpgrades: %w", err)
|
||||||
|
}
|
||||||
|
defer w.Stop()
|
||||||
|
|
||||||
|
klog.InfoS("watching OSUpgrades",
|
||||||
|
"namespace", namespace,
|
||||||
|
"resourceVersion", *resourceVersion,
|
||||||
|
)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
|
||||||
|
case evt, ok := <-w.ResultChan():
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("watch channel closed")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch evt.Type {
|
||||||
|
case watch.Bookmark:
|
||||||
|
if rv := extractResourceVersion(evt.Object); rv != "" {
|
||||||
|
*resourceVersion = rv
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
|
||||||
|
case watch.Error:
|
||||||
|
// Let outer loop retry / relist.
|
||||||
|
return fmt.Errorf("watch returned error event")
|
||||||
|
|
||||||
|
case watch.Deleted:
|
||||||
|
// Top-level delete does not require action here.
|
||||||
|
continue
|
||||||
|
|
||||||
|
case watch.Added, watch.Modified:
|
||||||
|
// handled below
|
||||||
|
|
||||||
|
default:
|
||||||
|
klog.V(1).InfoS("skipping unexpected watch event type",
|
||||||
|
"eventType", evt.Type,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
osu, ok := evt.Object.(*monov1alpha1.OSUpgrade)
|
||||||
|
if !ok {
|
||||||
|
klog.V(1).InfoS("skipping unexpected watch object type",
|
||||||
|
"type", fmt.Sprintf("%T", evt.Object),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if osu.ResourceVersion != "" {
|
||||||
|
*resourceVersion = osu.ResourceVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
handled, err := handleOSUpgrade(ctx, clients, namespace, osu)
|
||||||
|
if err != nil {
|
||||||
|
klog.ErrorS(err, "reconcile OSUpgrade failed",
|
||||||
|
"name", osu.Name,
|
||||||
|
"eventType", evt.Type,
|
||||||
|
"resourceVersion", osu.ResourceVersion,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !handled {
|
||||||
|
klog.V(2).InfoS("skipping OSUpgrade",
|
||||||
|
"name", osu.Name,
|
||||||
|
"eventType", evt.Type,
|
||||||
|
"phase", osu.StatusPhase(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleOSUpgrade(
|
||||||
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
osu *monov1alpha1.OSUpgrade,
|
||||||
|
) (bool, error) {
|
||||||
|
if !shouldHandle(osu) {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if osu.Status == nil || osu.Status.ObservedGeneration != osu.Generation {
|
||||||
|
return true, reconcileSpec(ctx, clients, namespace, osu)
|
||||||
|
}
|
||||||
|
|
||||||
|
if osu.Status.Phase == monov1alpha1.OSUpgradePhaseAccepted {
|
||||||
|
return true, reconcileFanout(ctx, clients, namespace, osu)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func reconcileSpec(
|
||||||
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
osu *monov1alpha1.OSUpgrade,
|
||||||
|
) error {
|
||||||
|
osu = osu.DeepCopy()
|
||||||
|
|
||||||
|
osu.Status = &monov1alpha1.OSUpgradeStatus{
|
||||||
|
Phase: monov1alpha1.OSUpgradePhaseAccepted,
|
||||||
|
ResolvedVersion: osu.Spec.DesiredVersion,
|
||||||
|
ObservedGeneration: osu.Generation,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := clients.MonoKS.
|
||||||
|
Monok8sV1alpha1().
|
||||||
|
OSUpgrades(namespace).
|
||||||
|
UpdateStatus(ctx, osu, metav1.UpdateOptions{})
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func reconcileFanout(
|
||||||
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
|
namespace string,
|
||||||
|
osu *monov1alpha1.OSUpgrade,
|
||||||
|
) error {
|
||||||
|
nodeNames, err := listTargetNodeNames(ctx, clients, osu)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("list target nodes for %s: %w", osu.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(nodeNames) == 0 {
|
||||||
|
klog.InfoS("no targets", "osupgrade", osu.Name)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
klog.InfoS("ensuring OSUpgradeProgress for target nodes",
|
||||||
|
"osupgrade", osu.Name,
|
||||||
|
"targets", len(nodeNames),
|
||||||
|
)
|
||||||
|
|
||||||
|
for _, nodeName := range nodeNames {
|
||||||
|
if err := EnsureOSUpgradeProgressForNode(
|
||||||
|
ctx,
|
||||||
|
clients,
|
||||||
|
namespace,
|
||||||
|
nodeName,
|
||||||
|
osu,
|
||||||
|
); err != nil {
|
||||||
|
klog.ErrorS(err, "ensure OSUpgradeProgress for node failed",
|
||||||
|
"osupgrade", osu.Name,
|
||||||
|
"node", nodeName,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func listTargetNodeNames(
|
||||||
|
ctx context.Context,
|
||||||
|
clients *kube.Clients,
|
||||||
|
osu *monov1alpha1.OSUpgrade,
|
||||||
|
) ([]string, error) {
|
||||||
|
selector := labels.SelectorFromSet(labels.Set{
|
||||||
|
monov1alpha1.NodeControlKey: "true",
|
||||||
|
})
|
||||||
|
|
||||||
|
if osu.Spec.NodeSelector != nil {
|
||||||
|
sel, err := metav1.LabelSelectorAsSelector(osu.Spec.NodeSelector)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid nodeSelector: %w", err)
|
||||||
|
}
|
||||||
|
selector = sel
|
||||||
|
}
|
||||||
|
|
||||||
|
list, err := clients.Kubernetes.CoreV1().
|
||||||
|
Nodes().
|
||||||
|
List(ctx, metav1.ListOptions{
|
||||||
|
LabelSelector: selector.String(),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("list nodes: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make([]string, 0, len(list.Items))
|
||||||
|
for i := range list.Items {
|
||||||
|
node := &list.Items[i]
|
||||||
|
if shouldUseNode(node) {
|
||||||
|
out = append(out, node.Name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldUseNode(node *corev1.Node) bool {
|
||||||
|
return node != nil && node.Name != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func shouldHandle(osu *monov1alpha1.OSUpgrade) bool {
|
||||||
|
if osu == nil || osu.DeletionTimestamp != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if osu.Spec.DesiredVersion == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// NEW: initial processing stage
|
||||||
|
if osu.Status == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reconcile if spec changed
|
||||||
|
if osu.Status.ObservedGeneration != osu.Generation {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fanout stage
|
||||||
|
return osu.Status.Phase == monov1alpha1.OSUpgradePhaseAccepted
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractResourceVersion(obj interface{}) string {
|
||||||
|
type hasRV interface {
|
||||||
|
GetResourceVersion() string
|
||||||
|
}
|
||||||
|
|
||||||
|
if o, ok := obj.(hasRV); ok {
|
||||||
|
return o.GetResourceVersion()
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
92
clitools/pkg/controller/server.go
Normal file
92
clitools/pkg/controller/server.go
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
package controller
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"example.com/monok8s/pkg/kube"
|
||||||
|
|
||||||
|
"github.com/emicklei/go-restful/v3"
|
||||||
|
"k8s.io/apiserver/pkg/server/httplog"
|
||||||
|
)
|
||||||
|
|
||||||
|
var statusesNoTracePred = httplog.StatusIsNot(
|
||||||
|
http.StatusOK,
|
||||||
|
http.StatusFound,
|
||||||
|
http.StatusMovedPermanently,
|
||||||
|
http.StatusTemporaryRedirect,
|
||||||
|
http.StatusBadRequest,
|
||||||
|
http.StatusNotFound,
|
||||||
|
http.StatusSwitchingProtocols,
|
||||||
|
)
|
||||||
|
|
||||||
|
type Server struct {
|
||||||
|
restfulCont *restful.Container
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
clients *kube.Clients
|
||||||
|
namespace string
|
||||||
|
nodeName string
|
||||||
|
startedAt time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
type StatusResponse struct {
|
||||||
|
OK bool `json:"ok"`
|
||||||
|
Service string `json:"service"`
|
||||||
|
Namespace string `json:"namespace,omitempty"`
|
||||||
|
NodeName string `json:"nodeName,omitempty"`
|
||||||
|
UptimeSec int64 `json:"uptimeSec"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewServer(ctx context.Context, clients *kube.Clients, namespace, nodeName string) *Server {
|
||||||
|
s := &Server{
|
||||||
|
ctx: ctx,
|
||||||
|
clients: clients,
|
||||||
|
namespace: namespace,
|
||||||
|
nodeName: nodeName,
|
||||||
|
startedAt: time.Now(),
|
||||||
|
}
|
||||||
|
s.Initialize()
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||||
|
if s == nil {
|
||||||
|
http.Error(w, "server is nil", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.restfulCont == nil {
|
||||||
|
http.Error(w, "server not initialized", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := httplog.WithLogging(s.restfulCont, statusesNoTracePred)
|
||||||
|
handler.ServeHTTP(w, req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) Initialize() {
|
||||||
|
s.restfulCont = restful.NewContainer()
|
||||||
|
|
||||||
|
ws := new(restful.WebService)
|
||||||
|
ws.Path("/")
|
||||||
|
ws.Consumes(restful.MIME_JSON)
|
||||||
|
ws.Produces(restful.MIME_JSON)
|
||||||
|
|
||||||
|
ws.Route(ws.GET("/status").To(s.queryStatus).
|
||||||
|
Doc("Return basic controller status"))
|
||||||
|
|
||||||
|
s.restfulCont.Add(ws)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Server) queryStatus(request *restful.Request, response *restful.Response) {
|
||||||
|
resp := StatusResponse{
|
||||||
|
OK: true,
|
||||||
|
Service: "monok8s-controller",
|
||||||
|
Namespace: s.namespace,
|
||||||
|
NodeName: s.nodeName,
|
||||||
|
UptimeSec: int64(time.Since(s.startedAt).Seconds()),
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = response.WriteHeaderAndEntity(http.StatusOK, resp)
|
||||||
|
}
|
||||||
106
clitools/pkg/generated/clientset/versioned/clientset.go
Normal file
106
clitools/pkg/generated/clientset/versioned/clientset.go
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package versioned
|
||||||
|
|
||||||
|
import (
|
||||||
|
fmt "fmt"
|
||||||
|
http "net/http"
|
||||||
|
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||||
|
discovery "k8s.io/client-go/discovery"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Interface interface {
|
||||||
|
Discovery() discovery.DiscoveryInterface
|
||||||
|
Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clientset contains the clients for groups.
|
||||||
|
type Clientset struct {
|
||||||
|
*discovery.DiscoveryClient
|
||||||
|
monok8sV1alpha1 *monok8sv1alpha1.Monok8sV1alpha1Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monok8sV1alpha1 retrieves the Monok8sV1alpha1Client
|
||||||
|
func (c *Clientset) Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface {
|
||||||
|
return c.monok8sV1alpha1
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discovery retrieves the DiscoveryClient
|
||||||
|
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.DiscoveryClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfig creates a new Clientset for the given config.
|
||||||
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
|
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
|
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||||
|
configShallowCopy := *c
|
||||||
|
|
||||||
|
if configShallowCopy.UserAgent == "" {
|
||||||
|
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||||
|
}
|
||||||
|
|
||||||
|
// share the transport between all clients
|
||||||
|
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new Clientset for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||||
|
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
|
||||||
|
configShallowCopy := *c
|
||||||
|
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||||
|
if configShallowCopy.Burst <= 0 {
|
||||||
|
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||||
|
}
|
||||||
|
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||||
|
}
|
||||||
|
|
||||||
|
var cs Clientset
|
||||||
|
var err error
|
||||||
|
cs.monok8sV1alpha1, err = monok8sv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &cs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||||
|
// panics if there is an error in the config.
|
||||||
|
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||||
|
cs, err := NewForConfig(c)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Clientset for the given RESTClient.
|
||||||
|
func New(c rest.Interface) *Clientset {
|
||||||
|
var cs Clientset
|
||||||
|
cs.monok8sV1alpha1 = monok8sv1alpha1.New(c)
|
||||||
|
|
||||||
|
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||||
|
return &cs
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
clientset "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||||
|
fakemonok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1/fake"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
|
"k8s.io/client-go/discovery"
|
||||||
|
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||||
|
"k8s.io/client-go/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||||
|
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||||
|
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
|
||||||
|
// for a real clientset and is mostly useful in simple unit tests.
|
||||||
|
//
|
||||||
|
// Deprecated: NewClientset replaces this with support for field management, which significantly improves
|
||||||
|
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
|
||||||
|
// via --with-applyconfig).
|
||||||
|
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||||
|
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||||
|
for _, obj := range objects {
|
||||||
|
if err := o.Add(obj); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := &Clientset{tracker: o}
|
||||||
|
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||||
|
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||||
|
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||||
|
var opts metav1.ListOptions
|
||||||
|
if watchAction, ok := action.(testing.WatchActionImpl); ok {
|
||||||
|
opts = watchAction.ListOptions
|
||||||
|
}
|
||||||
|
gvr := action.GetResource()
|
||||||
|
ns := action.GetNamespace()
|
||||||
|
watch, err := o.Watch(gvr, ns, opts)
|
||||||
|
if err != nil {
|
||||||
|
return false, nil, err
|
||||||
|
}
|
||||||
|
return true, watch, nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return cs
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||||
|
// struct to get a default implementation. This makes faking out just the method
|
||||||
|
// you want to test easier.
|
||||||
|
type Clientset struct {
|
||||||
|
testing.Fake
|
||||||
|
discovery *fakediscovery.FakeDiscovery
|
||||||
|
tracker testing.ObjectTracker
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||||
|
return c.discovery
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||||
|
return c.tracker
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsWatchListSemanticsSupported informs the reflector that this client
|
||||||
|
// doesn't support WatchList semantics.
|
||||||
|
//
|
||||||
|
// This is a synthetic method whose sole purpose is to satisfy the optional
|
||||||
|
// interface check performed by the reflector.
|
||||||
|
// Returning true signals that WatchList can NOT be used.
|
||||||
|
// No additional logic is implemented here.
|
||||||
|
func (c *Clientset) IsWatchListSemanticsUnSupported() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ clientset.Interface = &Clientset{}
|
||||||
|
_ testing.FakeClient = &Clientset{}
|
||||||
|
)
|
||||||
|
|
||||||
|
// Monok8sV1alpha1 retrieves the Monok8sV1alpha1Client
|
||||||
|
func (c *Clientset) Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface {
|
||||||
|
return &fakemonok8sv1alpha1.FakeMonok8sV1alpha1{Fake: &c.Fake}
|
||||||
|
}
|
||||||
6
clitools/pkg/generated/clientset/versioned/fake/doc.go
Normal file
6
clitools/pkg/generated/clientset/versioned/fake/doc.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
// This package has the automatically generated fake clientset.
|
||||||
|
package fake
|
||||||
42
clitools/pkg/generated/clientset/versioned/fake/register.go
Normal file
42
clitools/pkg/generated/clientset/versioned/fake/register.go
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var scheme = runtime.NewScheme()
|
||||||
|
var codecs = serializer.NewCodecFactory(scheme)
|
||||||
|
|
||||||
|
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||||
|
monok8sv1alpha1.AddToScheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||||
|
// of clientsets, like in:
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "k8s.io/client-go/kubernetes"
|
||||||
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||||
|
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||||
|
//
|
||||||
|
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||||
|
// correctly.
|
||||||
|
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||||
|
utilruntime.Must(AddToScheme(scheme))
|
||||||
|
}
|
||||||
6
clitools/pkg/generated/clientset/versioned/scheme/doc.go
Normal file
6
clitools/pkg/generated/clientset/versioned/scheme/doc.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
// This package contains the scheme of the automatically generated clientset.
|
||||||
|
package scheme
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package scheme
|
||||||
|
|
||||||
|
import (
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Scheme = runtime.NewScheme()
|
||||||
|
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||||
|
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||||
|
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||||
|
monok8sv1alpha1.AddToScheme,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||||
|
// of clientsets, like in:
|
||||||
|
//
|
||||||
|
// import (
|
||||||
|
// "k8s.io/client-go/kubernetes"
|
||||||
|
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
|
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||||
|
// )
|
||||||
|
//
|
||||||
|
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||||
|
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||||
|
//
|
||||||
|
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||||
|
// correctly.
|
||||||
|
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||||
|
utilruntime.Must(AddToScheme(Scheme))
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
// This package has the automatically generated typed clients.
|
||||||
|
package v1alpha1
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
// Package fake has the automatically generated clients.
|
||||||
|
package fake
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
testing "k8s.io/client-go/testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FakeMonok8sV1alpha1 struct {
|
||||||
|
*testing.Fake
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FakeMonok8sV1alpha1) OSUpgrades(namespace string) v1alpha1.OSUpgradeInterface {
|
||||||
|
return newFakeOSUpgrades(c, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *FakeMonok8sV1alpha1) OSUpgradeProgresses(namespace string) v1alpha1.OSUpgradeProgressInterface {
|
||||||
|
return newFakeOSUpgradeProgresses(c, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTClient returns a RESTClient that is used to communicate
|
||||||
|
// with API server by this client implementation.
|
||||||
|
func (c *FakeMonok8sV1alpha1) RESTClient() rest.Interface {
|
||||||
|
var ret *rest.RESTClient
|
||||||
|
return ret
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||||
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fakeOSUpgrades implements OSUpgradeInterface
|
||||||
|
type fakeOSUpgrades struct {
|
||||||
|
*gentype.FakeClientWithList[*v1alpha1.OSUpgrade, *v1alpha1.OSUpgradeList]
|
||||||
|
Fake *FakeMonok8sV1alpha1
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFakeOSUpgrades(fake *FakeMonok8sV1alpha1, namespace string) monok8sv1alpha1.OSUpgradeInterface {
|
||||||
|
return &fakeOSUpgrades{
|
||||||
|
gentype.NewFakeClientWithList[*v1alpha1.OSUpgrade, *v1alpha1.OSUpgradeList](
|
||||||
|
fake.Fake,
|
||||||
|
namespace,
|
||||||
|
v1alpha1.SchemeGroupVersion.WithResource("osupgrades"),
|
||||||
|
v1alpha1.SchemeGroupVersion.WithKind("OSUpgrade"),
|
||||||
|
func() *v1alpha1.OSUpgrade { return &v1alpha1.OSUpgrade{} },
|
||||||
|
func() *v1alpha1.OSUpgradeList { return &v1alpha1.OSUpgradeList{} },
|
||||||
|
func(dst, src *v1alpha1.OSUpgradeList) { dst.ListMeta = src.ListMeta },
|
||||||
|
func(list *v1alpha1.OSUpgradeList) []*v1alpha1.OSUpgrade { return gentype.ToPointerSlice(list.Items) },
|
||||||
|
func(list *v1alpha1.OSUpgradeList, items []*v1alpha1.OSUpgrade) {
|
||||||
|
list.Items = gentype.FromPointerSlice(items)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fake,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package fake
|
||||||
|
|
||||||
|
import (
|
||||||
|
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||||
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
)
|
||||||
|
|
||||||
|
// fakeOSUpgradeProgresses implements OSUpgradeProgressInterface
|
||||||
|
type fakeOSUpgradeProgresses struct {
|
||||||
|
*gentype.FakeClientWithList[*v1alpha1.OSUpgradeProgress, *v1alpha1.OSUpgradeProgressList]
|
||||||
|
Fake *FakeMonok8sV1alpha1
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFakeOSUpgradeProgresses(fake *FakeMonok8sV1alpha1, namespace string) monok8sv1alpha1.OSUpgradeProgressInterface {
|
||||||
|
return &fakeOSUpgradeProgresses{
|
||||||
|
gentype.NewFakeClientWithList[*v1alpha1.OSUpgradeProgress, *v1alpha1.OSUpgradeProgressList](
|
||||||
|
fake.Fake,
|
||||||
|
namespace,
|
||||||
|
v1alpha1.SchemeGroupVersion.WithResource("osupgradeprogresses"),
|
||||||
|
v1alpha1.SchemeGroupVersion.WithKind("OSUpgradeProgress"),
|
||||||
|
func() *v1alpha1.OSUpgradeProgress { return &v1alpha1.OSUpgradeProgress{} },
|
||||||
|
func() *v1alpha1.OSUpgradeProgressList { return &v1alpha1.OSUpgradeProgressList{} },
|
||||||
|
func(dst, src *v1alpha1.OSUpgradeProgressList) { dst.ListMeta = src.ListMeta },
|
||||||
|
func(list *v1alpha1.OSUpgradeProgressList) []*v1alpha1.OSUpgradeProgress {
|
||||||
|
return gentype.ToPointerSlice(list.Items)
|
||||||
|
},
|
||||||
|
func(list *v1alpha1.OSUpgradeProgressList, items []*v1alpha1.OSUpgradeProgress) {
|
||||||
|
list.Items = gentype.FromPointerSlice(items)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
fake,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
type OSUpgradeExpansion interface{}
|
||||||
|
|
||||||
|
type OSUpgradeProgressExpansion interface{}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
http "net/http"
|
||||||
|
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||||
|
rest "k8s.io/client-go/rest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Monok8sV1alpha1Interface interface {
|
||||||
|
RESTClient() rest.Interface
|
||||||
|
OSUpgradesGetter
|
||||||
|
OSUpgradeProgressesGetter
|
||||||
|
}
|
||||||
|
|
||||||
|
// Monok8sV1alpha1Client is used to interact with features provided by the monok8s group.
|
||||||
|
type Monok8sV1alpha1Client struct {
|
||||||
|
restClient rest.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Monok8sV1alpha1Client) OSUpgrades(namespace string) OSUpgradeInterface {
|
||||||
|
return newOSUpgrades(c, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Monok8sV1alpha1Client) OSUpgradeProgresses(namespace string) OSUpgradeProgressInterface {
|
||||||
|
return newOSUpgradeProgresses(c, namespace)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfig creates a new Monok8sV1alpha1Client for the given config.
|
||||||
|
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||||
|
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||||
|
func NewForConfig(c *rest.Config) (*Monok8sV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
setConfigDefaults(&config)
|
||||||
|
httpClient, err := rest.HTTPClientFor(&config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return NewForConfigAndClient(&config, httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigAndClient creates a new Monok8sV1alpha1Client for the given config and http client.
|
||||||
|
// Note the http client provided takes precedence over the configured transport values.
|
||||||
|
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*Monok8sV1alpha1Client, error) {
|
||||||
|
config := *c
|
||||||
|
setConfigDefaults(&config)
|
||||||
|
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &Monok8sV1alpha1Client{client}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewForConfigOrDie creates a new Monok8sV1alpha1Client for the given config and
|
||||||
|
// panics if there is an error in the config.
|
||||||
|
func NewForConfigOrDie(c *rest.Config) *Monok8sV1alpha1Client {
|
||||||
|
client, err := NewForConfig(c)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// New creates a new Monok8sV1alpha1Client for the given RESTClient.
|
||||||
|
func New(c rest.Interface) *Monok8sV1alpha1Client {
|
||||||
|
return &Monok8sV1alpha1Client{c}
|
||||||
|
}
|
||||||
|
|
||||||
|
func setConfigDefaults(config *rest.Config) {
|
||||||
|
gv := monok8sv1alpha1.SchemeGroupVersion
|
||||||
|
config.GroupVersion = &gv
|
||||||
|
config.APIPath = "/apis"
|
||||||
|
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
|
||||||
|
|
||||||
|
if config.UserAgent == "" {
|
||||||
|
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RESTClient returns a RESTClient that is used to communicate
|
||||||
|
// with API server by this client implementation.
|
||||||
|
func (c *Monok8sV1alpha1Client) RESTClient() rest.Interface {
|
||||||
|
if c == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.restClient
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradesGetter has a method to return a OSUpgradeInterface.
|
||||||
|
// A group's client should implement this interface.
|
||||||
|
type OSUpgradesGetter interface {
|
||||||
|
OSUpgrades(namespace string) OSUpgradeInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeInterface has methods to work with OSUpgrade resources.
|
||||||
|
type OSUpgradeInterface interface {
|
||||||
|
Create(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.CreateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||||
|
Update(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||||
|
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||||
|
UpdateStatus(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||||
|
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||||
|
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||||
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||||
|
List(ctx context.Context, opts v1.ListOptions) (*monok8sv1alpha1.OSUpgradeList, error)
|
||||||
|
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||||
|
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *monok8sv1alpha1.OSUpgrade, err error)
|
||||||
|
OSUpgradeExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgrades implements OSUpgradeInterface
|
||||||
|
type oSUpgrades struct {
|
||||||
|
*gentype.ClientWithList[*monok8sv1alpha1.OSUpgrade, *monok8sv1alpha1.OSUpgradeList]
|
||||||
|
}
|
||||||
|
|
||||||
|
// newOSUpgrades returns a OSUpgrades
|
||||||
|
func newOSUpgrades(c *Monok8sV1alpha1Client, namespace string) *oSUpgrades {
|
||||||
|
return &oSUpgrades{
|
||||||
|
gentype.NewClientWithList[*monok8sv1alpha1.OSUpgrade, *monok8sv1alpha1.OSUpgradeList](
|
||||||
|
"osupgrades",
|
||||||
|
c.RESTClient(),
|
||||||
|
scheme.ParameterCodec,
|
||||||
|
namespace,
|
||||||
|
func() *monok8sv1alpha1.OSUpgrade { return &monok8sv1alpha1.OSUpgrade{} },
|
||||||
|
func() *monok8sv1alpha1.OSUpgradeList { return &monok8sv1alpha1.OSUpgradeList{} },
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by client-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
types "k8s.io/apimachinery/pkg/types"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
gentype "k8s.io/client-go/gentype"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradeProgressesGetter has a method to return a OSUpgradeProgressInterface.
|
||||||
|
// A group's client should implement this interface.
|
||||||
|
type OSUpgradeProgressesGetter interface {
|
||||||
|
OSUpgradeProgresses(namespace string) OSUpgradeProgressInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeProgressInterface has methods to work with OSUpgradeProgress resources.
|
||||||
|
type OSUpgradeProgressInterface interface {
|
||||||
|
Create(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.CreateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||||
|
Update(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||||
|
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||||
|
UpdateStatus(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||||
|
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||||
|
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||||
|
Get(ctx context.Context, name string, opts v1.GetOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||||
|
List(ctx context.Context, opts v1.ListOptions) (*monok8sv1alpha1.OSUpgradeProgressList, error)
|
||||||
|
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||||
|
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||||
|
OSUpgradeProgressExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgradeProgresses implements OSUpgradeProgressInterface
|
||||||
|
type oSUpgradeProgresses struct {
|
||||||
|
*gentype.ClientWithList[*monok8sv1alpha1.OSUpgradeProgress, *monok8sv1alpha1.OSUpgradeProgressList]
|
||||||
|
}
|
||||||
|
|
||||||
|
// newOSUpgradeProgresses returns a OSUpgradeProgresses
|
||||||
|
func newOSUpgradeProgresses(c *Monok8sV1alpha1Client, namespace string) *oSUpgradeProgresses {
|
||||||
|
return &oSUpgradeProgresses{
|
||||||
|
gentype.NewClientWithList[*monok8sv1alpha1.OSUpgradeProgress, *monok8sv1alpha1.OSUpgradeProgressList](
|
||||||
|
"osupgradeprogresses",
|
||||||
|
c.RESTClient(),
|
||||||
|
scheme.ParameterCodec,
|
||||||
|
namespace,
|
||||||
|
func() *monok8sv1alpha1.OSUpgradeProgress { return &monok8sv1alpha1.OSUpgradeProgress{} },
|
||||||
|
func() *monok8sv1alpha1.OSUpgradeProgressList { return &monok8sv1alpha1.OSUpgradeProgressList{} },
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
249
clitools/pkg/generated/informers/externalversions/factory.go
Normal file
249
clitools/pkg/generated/informers/externalversions/factory.go
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package externalversions
|
||||||
|
|
||||||
|
import (
|
||||||
|
reflect "reflect"
|
||||||
|
sync "sync"
|
||||||
|
time "time"
|
||||||
|
|
||||||
|
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
|
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||||
|
monok8s "example.com/monok8s/pkg/generated/informers/externalversions/monok8s"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||||
|
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||||
|
|
||||||
|
type sharedInformerFactory struct {
|
||||||
|
client versioned.Interface
|
||||||
|
namespace string
|
||||||
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
|
lock sync.Mutex
|
||||||
|
defaultResync time.Duration
|
||||||
|
customResync map[reflect.Type]time.Duration
|
||||||
|
transform cache.TransformFunc
|
||||||
|
|
||||||
|
informers map[reflect.Type]cache.SharedIndexInformer
|
||||||
|
// startedInformers is used for tracking which informers have been started.
|
||||||
|
// This allows Start() to be called multiple times safely.
|
||||||
|
startedInformers map[reflect.Type]bool
|
||||||
|
// wg tracks how many goroutines were started.
|
||||||
|
wg sync.WaitGroup
|
||||||
|
// shuttingDown is true when Shutdown has been called. It may still be running
|
||||||
|
// because it needs to wait for goroutines.
|
||||||
|
shuttingDown bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||||
|
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
for k, v := range resyncConfig {
|
||||||
|
factory.customResync[reflect.TypeOf(k)] = v
|
||||||
|
}
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||||
|
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
factory.tweakListOptions = tweakListOptions
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||||
|
func WithNamespace(namespace string) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
factory.namespace = namespace
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithTransform sets a transform on all informers.
|
||||||
|
func WithTransform(transform cache.TransformFunc) SharedInformerOption {
|
||||||
|
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||||
|
factory.transform = transform
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||||
|
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||||
|
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||||
|
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||||
|
// as specified here.
|
||||||
|
//
|
||||||
|
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||||
|
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||||
|
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||||
|
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||||
|
factory := &sharedInformerFactory{
|
||||||
|
client: client,
|
||||||
|
namespace: v1.NamespaceAll,
|
||||||
|
defaultResync: defaultResync,
|
||||||
|
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||||
|
startedInformers: make(map[reflect.Type]bool),
|
||||||
|
customResync: make(map[reflect.Type]time.Duration),
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply all options
|
||||||
|
for _, opt := range options {
|
||||||
|
factory = opt(factory)
|
||||||
|
}
|
||||||
|
|
||||||
|
return factory
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||||
|
f.lock.Lock()
|
||||||
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
|
if f.shuttingDown {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for informerType, informer := range f.informers {
|
||||||
|
if !f.startedInformers[informerType] {
|
||||||
|
f.wg.Add(1)
|
||||||
|
// We need a new variable in each loop iteration,
|
||||||
|
// otherwise the goroutine would use the loop variable
|
||||||
|
// and that keeps changing.
|
||||||
|
informer := informer
|
||||||
|
go func() {
|
||||||
|
defer f.wg.Done()
|
||||||
|
informer.Run(stopCh)
|
||||||
|
}()
|
||||||
|
f.startedInformers[informerType] = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sharedInformerFactory) Shutdown() {
|
||||||
|
f.lock.Lock()
|
||||||
|
f.shuttingDown = true
|
||||||
|
f.lock.Unlock()
|
||||||
|
|
||||||
|
// Will return immediately if there is nothing to wait for.
|
||||||
|
f.wg.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||||
|
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||||
|
f.lock.Lock()
|
||||||
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
|
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||||
|
for informerType, informer := range f.informers {
|
||||||
|
if f.startedInformers[informerType] {
|
||||||
|
informers[informerType] = informer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return informers
|
||||||
|
}()
|
||||||
|
|
||||||
|
res := map[reflect.Type]bool{}
|
||||||
|
for informType, informer := range informers {
|
||||||
|
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||||
|
// client.
|
||||||
|
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||||
|
f.lock.Lock()
|
||||||
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
|
informerType := reflect.TypeOf(obj)
|
||||||
|
informer, exists := f.informers[informerType]
|
||||||
|
if exists {
|
||||||
|
return informer
|
||||||
|
}
|
||||||
|
|
||||||
|
resyncPeriod, exists := f.customResync[informerType]
|
||||||
|
if !exists {
|
||||||
|
resyncPeriod = f.defaultResync
|
||||||
|
}
|
||||||
|
|
||||||
|
informer = newFunc(f.client, resyncPeriod)
|
||||||
|
informer.SetTransform(f.transform)
|
||||||
|
f.informers[informerType] = informer
|
||||||
|
|
||||||
|
return informer
|
||||||
|
}
|
||||||
|
|
||||||
|
// SharedInformerFactory provides shared informers for resources in all known
|
||||||
|
// API group versions.
|
||||||
|
//
|
||||||
|
// It is typically used like this:
|
||||||
|
//
|
||||||
|
// ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
// defer cancel()
|
||||||
|
// factory := NewSharedInformerFactory(client, resyncPeriod)
|
||||||
|
// defer factory.WaitForStop() // Returns immediately if nothing was started.
|
||||||
|
// genericInformer := factory.ForResource(resource)
|
||||||
|
// typedInformer := factory.SomeAPIGroup().V1().SomeType()
|
||||||
|
// factory.Start(ctx.Done()) // Start processing these informers.
|
||||||
|
// synced := factory.WaitForCacheSync(ctx.Done())
|
||||||
|
// for v, ok := range synced {
|
||||||
|
// if !ok {
|
||||||
|
// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v)
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // Creating informers can also be created after Start, but then
|
||||||
|
// // Start must be called again:
|
||||||
|
// anotherGenericInformer := factory.ForResource(resource)
|
||||||
|
// factory.Start(ctx.Done())
|
||||||
|
type SharedInformerFactory interface {
|
||||||
|
internalinterfaces.SharedInformerFactory
|
||||||
|
|
||||||
|
// Start initializes all requested informers. They are handled in goroutines
|
||||||
|
// which run until the stop channel gets closed.
|
||||||
|
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
|
||||||
|
Start(stopCh <-chan struct{})
|
||||||
|
|
||||||
|
// Shutdown marks a factory as shutting down. At that point no new
|
||||||
|
// informers can be started anymore and Start will return without
|
||||||
|
// doing anything.
|
||||||
|
//
|
||||||
|
// In addition, Shutdown blocks until all goroutines have terminated. For that
|
||||||
|
// to happen, the close channel(s) that they were started with must be closed,
|
||||||
|
// either before Shutdown gets called or while it is waiting.
|
||||||
|
//
|
||||||
|
// Shutdown may be called multiple times, even concurrently. All such calls will
|
||||||
|
// block until all goroutines have terminated.
|
||||||
|
Shutdown()
|
||||||
|
|
||||||
|
// WaitForCacheSync blocks until all started informers' caches were synced
|
||||||
|
// or the stop channel gets closed.
|
||||||
|
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||||
|
|
||||||
|
// ForResource gives generic access to a shared informer of the matching type.
|
||||||
|
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||||
|
|
||||||
|
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||||
|
// client.
|
||||||
|
InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
|
||||||
|
|
||||||
|
Monok8s() monok8s.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *sharedInformerFactory) Monok8s() monok8s.Interface {
|
||||||
|
return monok8s.New(f, f.namespace, f.tweakListOptions)
|
||||||
|
}
|
||||||
50
clitools/pkg/generated/informers/externalversions/generic.go
Normal file
50
clitools/pkg/generated/informers/externalversions/generic.go
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package externalversions
|
||||||
|
|
||||||
|
import (
|
||||||
|
fmt "fmt"
|
||||||
|
|
||||||
|
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||||
|
// sharedInformers based on type
|
||||||
|
type GenericInformer interface {
|
||||||
|
Informer() cache.SharedIndexInformer
|
||||||
|
Lister() cache.GenericLister
|
||||||
|
}
|
||||||
|
|
||||||
|
type genericInformer struct {
|
||||||
|
informer cache.SharedIndexInformer
|
||||||
|
resource schema.GroupResource
|
||||||
|
}
|
||||||
|
|
||||||
|
// Informer returns the SharedIndexInformer.
|
||||||
|
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||||
|
return f.informer
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lister returns the GenericLister.
|
||||||
|
func (f *genericInformer) Lister() cache.GenericLister {
|
||||||
|
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ForResource gives generic access to a shared informer of the matching type
|
||||||
|
// TODO extend this to unknown resources with a client pool
|
||||||
|
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||||
|
switch resource {
|
||||||
|
// Group=monok8s, Version=v1alpha1
|
||||||
|
case v1alpha1.SchemeGroupVersion.WithResource("osupgrades"):
|
||||||
|
return &genericInformer{resource: resource.GroupResource(), informer: f.Monok8s().V1alpha1().OSUpgrades().Informer()}, nil
|
||||||
|
case v1alpha1.SchemeGroupVersion.WithResource("osupgradeprogresses"):
|
||||||
|
return &genericInformer{resource: resource.GroupResource(), informer: f.Monok8s().V1alpha1().OSUpgradeProgresses().Informer()}, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package internalinterfaces
|
||||||
|
|
||||||
|
import (
|
||||||
|
time "time"
|
||||||
|
|
||||||
|
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
|
||||||
|
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||||
|
|
||||||
|
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||||
|
type SharedInformerFactory interface {
|
||||||
|
Start(stopCh <-chan struct{})
|
||||||
|
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||||
|
}
|
||||||
|
|
||||||
|
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
|
||||||
|
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package monok8s
|
||||||
|
|
||||||
|
import (
|
||||||
|
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||||
|
v1alpha1 "example.com/monok8s/pkg/generated/informers/externalversions/monok8s/v1alpha1"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface provides access to each of this group's versions.
|
||||||
|
type Interface interface {
|
||||||
|
// V1alpha1 provides access to shared informers for resources in V1alpha1.
|
||||||
|
V1alpha1() v1alpha1.Interface
|
||||||
|
}
|
||||||
|
|
||||||
|
type group struct {
|
||||||
|
factory internalinterfaces.SharedInformerFactory
|
||||||
|
namespace string
|
||||||
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Interface.
|
||||||
|
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||||
|
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||||
|
}
|
||||||
|
|
||||||
|
// V1alpha1 returns a new v1alpha1.Interface.
|
||||||
|
func (g *group) V1alpha1() v1alpha1.Interface {
|
||||||
|
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Interface provides access to all the informers in this group version.
|
||||||
|
type Interface interface {
|
||||||
|
// OSUpgrades returns a OSUpgradeInformer.
|
||||||
|
OSUpgrades() OSUpgradeInformer
|
||||||
|
// OSUpgradeProgresses returns a OSUpgradeProgressInformer.
|
||||||
|
OSUpgradeProgresses() OSUpgradeProgressInformer
|
||||||
|
}
|
||||||
|
|
||||||
|
type version struct {
|
||||||
|
factory internalinterfaces.SharedInformerFactory
|
||||||
|
namespace string
|
||||||
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Interface.
|
||||||
|
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||||
|
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgrades returns a OSUpgradeInformer.
|
||||||
|
func (v *version) OSUpgrades() OSUpgradeInformer {
|
||||||
|
return &oSUpgradeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeProgresses returns a OSUpgradeProgressInformer.
|
||||||
|
func (v *version) OSUpgradeProgresses() OSUpgradeProgressInformer {
|
||||||
|
return &oSUpgradeProgressInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
time "time"
|
||||||
|
|
||||||
|
apismonok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
|
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/listers/monok8s/v1alpha1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradeInformer provides access to a shared informer and lister for
|
||||||
|
// OSUpgrades.
|
||||||
|
type OSUpgradeInformer interface {
|
||||||
|
Informer() cache.SharedIndexInformer
|
||||||
|
Lister() monok8sv1alpha1.OSUpgradeLister
|
||||||
|
}
|
||||||
|
|
||||||
|
type oSUpgradeInformer struct {
|
||||||
|
factory internalinterfaces.SharedInformerFactory
|
||||||
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
|
namespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOSUpgradeInformer constructs a new informer for OSUpgrade type.
|
||||||
|
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||||
|
// one. This reduces memory footprint and number of connections to the server.
|
||||||
|
func NewOSUpgradeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||||
|
return NewFilteredOSUpgradeInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilteredOSUpgradeInformer constructs a new informer for OSUpgrade type.
|
||||||
|
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||||
|
// one. This reduces memory footprint and number of connections to the server.
|
||||||
|
func NewFilteredOSUpgradeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||||
|
return cache.NewSharedIndexInformer(
|
||||||
|
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
|
||||||
|
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgrades(namespace).List(context.Background(), options)
|
||||||
|
},
|
||||||
|
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgrades(namespace).Watch(context.Background(), options)
|
||||||
|
},
|
||||||
|
ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgrades(namespace).List(ctx, options)
|
||||||
|
},
|
||||||
|
WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgrades(namespace).Watch(ctx, options)
|
||||||
|
},
|
||||||
|
}, client),
|
||||||
|
&apismonok8sv1alpha1.OSUpgrade{},
|
||||||
|
resyncPeriod,
|
||||||
|
indexers,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||||
|
return NewFilteredOSUpgradeInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeInformer) Informer() cache.SharedIndexInformer {
|
||||||
|
return f.factory.InformerFor(&apismonok8sv1alpha1.OSUpgrade{}, f.defaultInformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeInformer) Lister() monok8sv1alpha1.OSUpgradeLister {
|
||||||
|
return monok8sv1alpha1.NewOSUpgradeLister(f.Informer().GetIndexer())
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by informer-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
time "time"
|
||||||
|
|
||||||
|
apismonok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
|
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/generated/listers/monok8s/v1alpha1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
|
watch "k8s.io/apimachinery/pkg/watch"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradeProgressInformer provides access to a shared informer and lister for
|
||||||
|
// OSUpgradeProgresses.
|
||||||
|
type OSUpgradeProgressInformer interface {
|
||||||
|
Informer() cache.SharedIndexInformer
|
||||||
|
Lister() monok8sv1alpha1.OSUpgradeProgressLister
|
||||||
|
}
|
||||||
|
|
||||||
|
type oSUpgradeProgressInformer struct {
|
||||||
|
factory internalinterfaces.SharedInformerFactory
|
||||||
|
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||||
|
namespace string
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOSUpgradeProgressInformer constructs a new informer for OSUpgradeProgress type.
|
||||||
|
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||||
|
// one. This reduces memory footprint and number of connections to the server.
|
||||||
|
func NewOSUpgradeProgressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||||
|
return NewFilteredOSUpgradeProgressInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewFilteredOSUpgradeProgressInformer constructs a new informer for OSUpgradeProgress type.
|
||||||
|
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||||
|
// one. This reduces memory footprint and number of connections to the server.
|
||||||
|
func NewFilteredOSUpgradeProgressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||||
|
return cache.NewSharedIndexInformer(
|
||||||
|
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
|
||||||
|
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).List(context.Background(), options)
|
||||||
|
},
|
||||||
|
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).Watch(context.Background(), options)
|
||||||
|
},
|
||||||
|
ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).List(ctx, options)
|
||||||
|
},
|
||||||
|
WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) {
|
||||||
|
if tweakListOptions != nil {
|
||||||
|
tweakListOptions(&options)
|
||||||
|
}
|
||||||
|
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).Watch(ctx, options)
|
||||||
|
},
|
||||||
|
}, client),
|
||||||
|
&apismonok8sv1alpha1.OSUpgradeProgress{},
|
||||||
|
resyncPeriod,
|
||||||
|
indexers,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeProgressInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||||
|
return NewFilteredOSUpgradeProgressInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeProgressInformer) Informer() cache.SharedIndexInformer {
|
||||||
|
return f.factory.InformerFor(&apismonok8sv1alpha1.OSUpgradeProgress{}, f.defaultInformer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *oSUpgradeProgressInformer) Lister() monok8sv1alpha1.OSUpgradeProgressLister {
|
||||||
|
return monok8sv1alpha1.NewOSUpgradeProgressLister(f.Informer().GetIndexer())
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by lister-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
// OSUpgradeListerExpansion allows custom methods to be added to
|
||||||
|
// OSUpgradeLister.
|
||||||
|
type OSUpgradeListerExpansion interface{}
|
||||||
|
|
||||||
|
// OSUpgradeNamespaceListerExpansion allows custom methods to be added to
|
||||||
|
// OSUpgradeNamespaceLister.
|
||||||
|
type OSUpgradeNamespaceListerExpansion interface{}
|
||||||
|
|
||||||
|
// OSUpgradeProgressListerExpansion allows custom methods to be added to
|
||||||
|
// OSUpgradeProgressLister.
|
||||||
|
type OSUpgradeProgressListerExpansion interface{}
|
||||||
|
|
||||||
|
// OSUpgradeProgressNamespaceListerExpansion allows custom methods to be added to
|
||||||
|
// OSUpgradeProgressNamespaceLister.
|
||||||
|
type OSUpgradeProgressNamespaceListerExpansion interface{}
|
||||||
56
clitools/pkg/generated/listers/monok8s/v1alpha1/osupgrade.go
Normal file
56
clitools/pkg/generated/listers/monok8s/v1alpha1/osupgrade.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by lister-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
|
listers "k8s.io/client-go/listers"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradeLister helps list OSUpgrades.
|
||||||
|
// All objects returned here must be treated as read-only.
|
||||||
|
type OSUpgradeLister interface {
|
||||||
|
// List lists all OSUpgrades in the indexer.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgrade, err error)
|
||||||
|
// OSUpgrades returns an object that can list and get OSUpgrades.
|
||||||
|
OSUpgrades(namespace string) OSUpgradeNamespaceLister
|
||||||
|
OSUpgradeListerExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgradeLister implements the OSUpgradeLister interface.
|
||||||
|
type oSUpgradeLister struct {
|
||||||
|
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgrade]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOSUpgradeLister returns a new OSUpgradeLister.
|
||||||
|
func NewOSUpgradeLister(indexer cache.Indexer) OSUpgradeLister {
|
||||||
|
return &oSUpgradeLister{listers.New[*monok8sv1alpha1.OSUpgrade](indexer, monok8sv1alpha1.Resource("osupgrade"))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgrades returns an object that can list and get OSUpgrades.
|
||||||
|
func (s *oSUpgradeLister) OSUpgrades(namespace string) OSUpgradeNamespaceLister {
|
||||||
|
return oSUpgradeNamespaceLister{listers.NewNamespaced[*monok8sv1alpha1.OSUpgrade](s.ResourceIndexer, namespace)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeNamespaceLister helps list and get OSUpgrades.
|
||||||
|
// All objects returned here must be treated as read-only.
|
||||||
|
type OSUpgradeNamespaceLister interface {
|
||||||
|
// List lists all OSUpgrades in the indexer for a given namespace.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgrade, err error)
|
||||||
|
// Get retrieves the OSUpgrade from the indexer for a given namespace and name.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
Get(name string) (*monok8sv1alpha1.OSUpgrade, error)
|
||||||
|
OSUpgradeNamespaceListerExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgradeNamespaceLister implements the OSUpgradeNamespaceLister
|
||||||
|
// interface.
|
||||||
|
type oSUpgradeNamespaceLister struct {
|
||||||
|
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgrade]
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/* MIT License */
|
||||||
|
|
||||||
|
// Code generated by lister-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1alpha1
|
||||||
|
|
||||||
|
import (
|
||||||
|
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
labels "k8s.io/apimachinery/pkg/labels"
|
||||||
|
listers "k8s.io/client-go/listers"
|
||||||
|
cache "k8s.io/client-go/tools/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
// OSUpgradeProgressLister helps list OSUpgradeProgresses.
|
||||||
|
// All objects returned here must be treated as read-only.
|
||||||
|
type OSUpgradeProgressLister interface {
|
||||||
|
// List lists all OSUpgradeProgresses in the indexer.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||||
|
// OSUpgradeProgresses returns an object that can list and get OSUpgradeProgresses.
|
||||||
|
OSUpgradeProgresses(namespace string) OSUpgradeProgressNamespaceLister
|
||||||
|
OSUpgradeProgressListerExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgradeProgressLister implements the OSUpgradeProgressLister interface.
|
||||||
|
type oSUpgradeProgressLister struct {
|
||||||
|
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgradeProgress]
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewOSUpgradeProgressLister returns a new OSUpgradeProgressLister.
|
||||||
|
func NewOSUpgradeProgressLister(indexer cache.Indexer) OSUpgradeProgressLister {
|
||||||
|
return &oSUpgradeProgressLister{listers.New[*monok8sv1alpha1.OSUpgradeProgress](indexer, monok8sv1alpha1.Resource("osupgradeprogress"))}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeProgresses returns an object that can list and get OSUpgradeProgresses.
|
||||||
|
func (s *oSUpgradeProgressLister) OSUpgradeProgresses(namespace string) OSUpgradeProgressNamespaceLister {
|
||||||
|
return oSUpgradeProgressNamespaceLister{listers.NewNamespaced[*monok8sv1alpha1.OSUpgradeProgress](s.ResourceIndexer, namespace)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// OSUpgradeProgressNamespaceLister helps list and get OSUpgradeProgresses.
|
||||||
|
// All objects returned here must be treated as read-only.
|
||||||
|
type OSUpgradeProgressNamespaceLister interface {
|
||||||
|
// List lists all OSUpgradeProgresses in the indexer for a given namespace.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||||
|
// Get retrieves the OSUpgradeProgress from the indexer for a given namespace and name.
|
||||||
|
// Objects returned here must be treated as read-only.
|
||||||
|
Get(name string) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||||
|
OSUpgradeProgressNamespaceListerExpansion
|
||||||
|
}
|
||||||
|
|
||||||
|
// oSUpgradeProgressNamespaceLister implements the OSUpgradeProgressNamespaceLister
|
||||||
|
// interface.
|
||||||
|
type oSUpgradeProgressNamespaceLister struct {
|
||||||
|
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgradeProgress]
|
||||||
|
}
|
||||||
@@ -3,11 +3,12 @@ package kube
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
monoclientset "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||||
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
kubernetes "k8s.io/client-go/kubernetes"
|
kubernetes "k8s.io/client-go/kubernetes"
|
||||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
@@ -21,6 +22,7 @@ type Clients struct {
|
|||||||
Dynamic dynamic.Interface
|
Dynamic dynamic.Interface
|
||||||
APIExtensions apiextensionsclientset.Interface
|
APIExtensions apiextensionsclientset.Interface
|
||||||
RESTClientGetter genericclioptions.RESTClientGetter
|
RESTClientGetter genericclioptions.RESTClientGetter
|
||||||
|
MonoKS monoclientset.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClients(flags *genericclioptions.ConfigFlags) (*Clients, error) {
|
func NewClients(flags *genericclioptions.ConfigFlags) (*Clients, error) {
|
||||||
@@ -40,7 +42,19 @@ func NewClients(flags *genericclioptions.ConfigFlags) (*Clients, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("build apiextensions client: %w", err)
|
return nil, fmt.Errorf("build apiextensions client: %w", err)
|
||||||
}
|
}
|
||||||
return &Clients{Config: cfg, Kubernetes: kubeClient, Dynamic: dyn, APIExtensions: ext, RESTClientGetter: flags}, nil
|
mono, err := monoclientset.NewForConfig(cfg)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("build monok8s client: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Clients{
|
||||||
|
Config: cfg,
|
||||||
|
Kubernetes: kubeClient,
|
||||||
|
Dynamic: dyn,
|
||||||
|
APIExtensions: ext,
|
||||||
|
RESTClientGetter: flags,
|
||||||
|
MonoKS: mono,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewClientsFromKubeconfig(kubeconfigPath string) (*Clients, error) {
|
func NewClientsFromKubeconfig(kubeconfigPath string) (*Clients, error) {
|
||||||
|
|||||||
@@ -20,17 +20,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
controlAgentName = "control-agent"
|
controlAgentImage = "localhost/monok8s/node-control:dev"
|
||||||
controlAgentNodeSelectorValue = "true"
|
|
||||||
controlAgentImage = "localhost/monok8s/control-agent:dev"
|
|
||||||
kubeconfig = "/etc/kubernetes/admin.conf"
|
kubeconfig = "/etc/kubernetes/admin.conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ApplyControlAgentDaemonSetResources(ctx context.Context, n *NodeContext) error {
|
func ApplyNodeControlDaemonSetResources(ctx context.Context, n *NodeContext) error {
|
||||||
// Only the control-plane should bootstrap this DaemonSet definition.
|
// Only the control-plane should bootstrap this DaemonSet definition.
|
||||||
// And only when the feature is enabled.
|
// And only when the feature is enabled.
|
||||||
if strings.TrimSpace(n.Config.Spec.ClusterRole) != "control-plane" || !n.Config.Spec.EnableControlAgent {
|
if strings.TrimSpace(n.Config.Spec.ClusterRole) != "control-plane" || !n.Config.Spec.EnableNodeControl {
|
||||||
klog.InfoS("skipped for", "clusterRole", n.Config.Spec.ClusterRole, "enableControlAgent", n.Config.Spec.EnableControlAgent)
|
klog.InfoS("skipped for", "clusterRole", n.Config.Spec.ClusterRole, "enableNodeAgent", n.Config.Spec.EnableNodeControl)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,40 +48,83 @@ func ApplyControlAgentDaemonSetResources(ctx context.Context, n *NodeContext) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"app.kubernetes.io/name": controlAgentName,
|
"app.kubernetes.io/name": monov1alpha1.NodeAgentName,
|
||||||
"app.kubernetes.io/component": "agent",
|
"app.kubernetes.io/component": "agent",
|
||||||
"app.kubernetes.io/part-of": "monok8s",
|
"app.kubernetes.io/part-of": "monok8s",
|
||||||
"app.kubernetes.io/managed-by": "ctl",
|
"app.kubernetes.io/managed-by": monov1alpha1.NodeControlName,
|
||||||
}
|
}
|
||||||
|
|
||||||
kubeClient := clients.Kubernetes
|
kubeClient := clients.Kubernetes
|
||||||
|
|
||||||
if err := applyControlAgentServiceAccount(ctx, kubeClient, namespace, labels); err != nil {
|
if err := ensureNamespace(ctx, kubeClient, namespace, labels); err != nil {
|
||||||
|
return fmt.Errorf("ensure namespace %q: %w", namespace, err)
|
||||||
|
}
|
||||||
|
if err := applyNodeAgentServiceAccount(ctx, kubeClient, namespace, labels); err != nil {
|
||||||
return fmt.Errorf("apply serviceaccount: %w", err)
|
return fmt.Errorf("apply serviceaccount: %w", err)
|
||||||
}
|
}
|
||||||
if err := applyControlAgentClusterRole(ctx, kubeClient, labels); err != nil {
|
if err := applyNodeAgentClusterRole(ctx, kubeClient, labels); err != nil {
|
||||||
return fmt.Errorf("apply clusterrole: %w", err)
|
return fmt.Errorf("apply clusterrole: %w", err)
|
||||||
}
|
}
|
||||||
if err := applyControlAgentClusterRoleBinding(ctx, kubeClient, namespace, labels); err != nil {
|
if err := applyNodeAgentClusterRoleBinding(ctx, kubeClient, namespace, labels); err != nil {
|
||||||
return fmt.Errorf("apply clusterrolebinding: %w", err)
|
return fmt.Errorf("apply clusterrolebinding: %w", err)
|
||||||
}
|
}
|
||||||
if err := applyControlAgentDaemonSet(ctx, kubeClient, namespace, labels); err != nil {
|
if err := applyNodeAgentDaemonSet(ctx, kubeClient, namespace, labels); err != nil {
|
||||||
return fmt.Errorf("apply daemonset: %w", err)
|
return fmt.Errorf("apply daemonset: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyControlAgentServiceAccount(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
func ensureNamespace(
|
||||||
|
ctx context.Context,
|
||||||
|
kubeClient kubernetes.Interface,
|
||||||
|
namespace string,
|
||||||
|
labels map[string]string,
|
||||||
|
) error {
|
||||||
|
_, err := kubeClient.CoreV1().Namespaces().Get(ctx, namespace, metav1.GetOptions{})
|
||||||
|
if err == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !apierrors.IsNotFound(err) {
|
||||||
|
return fmt.Errorf("get namespace: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ns := &corev1.Namespace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: namespace,
|
||||||
|
Labels: copyStringMap(labels),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = kubeClient.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
|
||||||
|
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||||
|
return fmt.Errorf("create namespace: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyStringMap(in map[string]string) map[string]string {
|
||||||
|
if len(in) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
out := make(map[string]string, len(in))
|
||||||
|
for k, v := range in {
|
||||||
|
out[k] = v
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyNodeAgentServiceAccount(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||||
want := &corev1.ServiceAccount{
|
want := &corev1.ServiceAccount{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(ctx, controlAgentName, metav1.GetOptions{})
|
existing, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(ctx, monov1alpha1.NodeAgentName, metav1.GetOptions{})
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
_, err = kubeClient.CoreV1().ServiceAccounts(namespace).Create(ctx, want, metav1.CreateOptions{})
|
_, err = kubeClient.CoreV1().ServiceAccounts(namespace).Create(ctx, want, metav1.CreateOptions{})
|
||||||
return err
|
return err
|
||||||
@@ -106,17 +147,12 @@ func applyControlAgentServiceAccount(ctx context.Context, kubeClient kubernetes.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyControlAgentClusterRole(ctx context.Context, kubeClient kubernetes.Interface, labels map[string]string) error {
|
func applyNodeAgentClusterRole(ctx context.Context, kubeClient kubernetes.Interface, labels map[string]string) error {
|
||||||
wantRules := []rbacv1.PolicyRule{
|
wantRules := []rbacv1.PolicyRule{
|
||||||
{
|
{
|
||||||
APIGroups: []string{monov1alpha1.Group},
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
Resources: []string{"osupgrades"},
|
Resources: []string{"osupgrades"},
|
||||||
Verbs: []string{"get", "list", "watch"},
|
Verbs: []string{"get"},
|
||||||
},
|
|
||||||
{
|
|
||||||
APIGroups: []string{monov1alpha1.Group},
|
|
||||||
Resources: []string{"osupgrades/status"},
|
|
||||||
Verbs: []string{"get", "patch", "update"},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
APIGroups: []string{monov1alpha1.Group},
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
@@ -137,13 +173,13 @@ func applyControlAgentClusterRole(ctx context.Context, kubeClient kubernetes.Int
|
|||||||
|
|
||||||
want := &rbacv1.ClusterRole{
|
want := &rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Rules: wantRules,
|
Rules: wantRules,
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, err := kubeClient.RbacV1().ClusterRoles().Get(ctx, controlAgentName, metav1.GetOptions{})
|
existing, err := kubeClient.RbacV1().ClusterRoles().Get(ctx, monov1alpha1.NodeAgentName, metav1.GetOptions{})
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
_, err = kubeClient.RbacV1().ClusterRoles().Create(ctx, want, metav1.CreateOptions{})
|
_, err = kubeClient.RbacV1().ClusterRoles().Create(ctx, want, metav1.CreateOptions{})
|
||||||
return err
|
return err
|
||||||
@@ -170,30 +206,30 @@ func applyControlAgentClusterRole(ctx context.Context, kubeClient kubernetes.Int
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyControlAgentClusterRoleBinding(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
func applyNodeAgentClusterRoleBinding(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||||
wantRoleRef := rbacv1.RoleRef{
|
wantRoleRef := rbacv1.RoleRef{
|
||||||
APIGroup: rbacv1.GroupName,
|
APIGroup: rbacv1.GroupName,
|
||||||
Kind: "ClusterRole",
|
Kind: "ClusterRole",
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
}
|
}
|
||||||
wantSubjects := []rbacv1.Subject{
|
wantSubjects := []rbacv1.Subject{
|
||||||
{
|
{
|
||||||
Kind: "ServiceAccount",
|
Kind: "ServiceAccount",
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
want := &rbacv1.ClusterRoleBinding{
|
want := &rbacv1.ClusterRoleBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
RoleRef: wantRoleRef,
|
RoleRef: wantRoleRef,
|
||||||
Subjects: wantSubjects,
|
Subjects: wantSubjects,
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, err := kubeClient.RbacV1().ClusterRoleBindings().Get(ctx, controlAgentName, metav1.GetOptions{})
|
existing, err := kubeClient.RbacV1().ClusterRoleBindings().Get(ctx, monov1alpha1.NodeAgentName, metav1.GetOptions{})
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
_, err = kubeClient.RbacV1().ClusterRoleBindings().Create(ctx, want, metav1.CreateOptions{})
|
_, err = kubeClient.RbacV1().ClusterRoleBindings().Create(ctx, want, metav1.CreateOptions{})
|
||||||
return err
|
return err
|
||||||
@@ -204,7 +240,7 @@ func applyControlAgentClusterRoleBinding(ctx context.Context, kubeClient kuberne
|
|||||||
|
|
||||||
// roleRef is immutable. If it differs, fail loudly instead of pretending we can patch it.
|
// roleRef is immutable. If it differs, fail loudly instead of pretending we can patch it.
|
||||||
if !reflect.DeepEqual(existing.RoleRef, want.RoleRef) {
|
if !reflect.DeepEqual(existing.RoleRef, want.RoleRef) {
|
||||||
return fmt.Errorf("existing ClusterRoleBinding %q has different roleRef and must be recreated", controlAgentName)
|
return fmt.Errorf("existing ClusterRoleBinding %q has different roleRef and must be recreated", monov1alpha1.NodeAgentName)
|
||||||
}
|
}
|
||||||
|
|
||||||
changed := false
|
changed := false
|
||||||
@@ -225,26 +261,21 @@ func applyControlAgentClusterRoleBinding(ctx context.Context, kubeClient kuberne
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func applyControlAgentDaemonSet(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
func applyNodeAgentDaemonSet(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||||
privileged := true
|
privileged := true
|
||||||
|
|
||||||
dsLabels := map[string]string{
|
dsLabels := monov1alpha1.NodeAgentLabels()
|
||||||
"app.kubernetes.io/name": controlAgentName,
|
|
||||||
"app.kubernetes.io/component": "agent",
|
|
||||||
"app.kubernetes.io/part-of": "monok8s",
|
|
||||||
"app.kubernetes.io/managed-by": "ctl",
|
|
||||||
}
|
|
||||||
|
|
||||||
want := &appsv1.DaemonSet{
|
want := &appsv1.DaemonSet{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: controlAgentName,
|
Name: monov1alpha1.NodeAgentName,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
},
|
},
|
||||||
Spec: appsv1.DaemonSetSpec{
|
Spec: appsv1.DaemonSetSpec{
|
||||||
Selector: &metav1.LabelSelector{
|
Selector: &metav1.LabelSelector{
|
||||||
MatchLabels: map[string]string{
|
MatchLabels: map[string]string{
|
||||||
"app.kubernetes.io/name": controlAgentName,
|
"app.kubernetes.io/name": monov1alpha1.NodeAgentName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Template: corev1.PodTemplateSpec{
|
Template: corev1.PodTemplateSpec{
|
||||||
@@ -252,12 +283,12 @@ func applyControlAgentDaemonSet(ctx context.Context, kubeClient kubernetes.Inter
|
|||||||
Labels: dsLabels,
|
Labels: dsLabels,
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
ServiceAccountName: controlAgentName,
|
ServiceAccountName: monov1alpha1.NodeAgentName,
|
||||||
HostNetwork: true,
|
HostNetwork: true,
|
||||||
HostPID: true,
|
HostPID: true,
|
||||||
DNSPolicy: corev1.DNSClusterFirstWithHostNet,
|
DNSPolicy: corev1.DNSClusterFirstWithHostNet,
|
||||||
NodeSelector: map[string]string{
|
NodeSelector: map[string]string{
|
||||||
monov1alpha1.ControlAgentKey: controlAgentNodeSelectorValue,
|
monov1alpha1.NodeControlKey: "true",
|
||||||
},
|
},
|
||||||
Tolerations: []corev1.Toleration{
|
Tolerations: []corev1.Toleration{
|
||||||
{Operator: corev1.TolerationOpExists},
|
{Operator: corev1.TolerationOpExists},
|
||||||
@@ -342,7 +373,7 @@ func applyControlAgentDaemonSet(ctx context.Context, kubeClient kubernetes.Inter
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
existing, err := kubeClient.AppsV1().DaemonSets(namespace).Get(ctx, controlAgentName, metav1.GetOptions{})
|
existing, err := kubeClient.AppsV1().DaemonSets(namespace).Get(ctx, monov1alpha1.NodeAgentName, metav1.GetOptions{})
|
||||||
if apierrors.IsNotFound(err) {
|
if apierrors.IsNotFound(err) {
|
||||||
_, err = kubeClient.AppsV1().DaemonSets(namespace).Create(ctx, want, metav1.CreateOptions{})
|
_, err = kubeClient.AppsV1().DaemonSets(namespace).Create(ctx, want, metav1.CreateOptions{})
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -464,9 +465,57 @@ func buildNodeRegistration(spec monov1alpha1.MonoKSConfigSpec) NodeRegistrationO
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
labels := effectiveNodeLabels(spec)
|
||||||
|
if nodeLabels := buildNodeLabelsArg(labels); nodeLabels != "" {
|
||||||
|
nr.KubeletExtraArgs = append(nr.KubeletExtraArgs,
|
||||||
|
KubeadmArg{Name: "node-labels", Value: nodeLabels},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return nr
|
return nr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func effectiveNodeLabels(spec monov1alpha1.MonoKSConfigSpec) map[string]string {
|
||||||
|
if len(spec.NodeLabels) == 0 && !spec.EnableNodeControl {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
labels := make(map[string]string, len(spec.NodeLabels)+1)
|
||||||
|
for k, v := range spec.NodeLabels {
|
||||||
|
labels[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.EnableNodeControl {
|
||||||
|
labels[monov1alpha1.NodeControlKey] = "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
return labels
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildNodeLabelsArg(labels map[string]string) string {
|
||||||
|
if len(labels) == 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
keys := make([]string, 0, len(labels))
|
||||||
|
for k := range labels {
|
||||||
|
k = strings.TrimSpace(k)
|
||||||
|
if k == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
keys = append(keys, k)
|
||||||
|
}
|
||||||
|
sort.Strings(keys)
|
||||||
|
|
||||||
|
parts := make([]string, 0, len(keys))
|
||||||
|
for _, k := range keys {
|
||||||
|
v := strings.TrimSpace(labels[k])
|
||||||
|
parts = append(parts, k+"="+v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.Join(parts, ",")
|
||||||
|
}
|
||||||
|
|
||||||
func maybeAddBootstrapTaint(nr *NodeRegistrationOptions, role string) {
|
func maybeAddBootstrapTaint(nr *NodeRegistrationOptions, role string) {
|
||||||
if strings.TrimSpace(role) != "worker" {
|
if strings.TrimSpace(role) != "worker" {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
"example.com/monok8s/pkg/kube"
|
"example.com/monok8s/pkg/kube"
|
||||||
"example.com/monok8s/pkg/system"
|
"example.com/monok8s/pkg/system"
|
||||||
)
|
)
|
||||||
@@ -113,7 +114,7 @@ func runUpgradeSelfHealthCheck(ctx context.Context, kubeClient kubernetes.Interf
|
|||||||
Namespace: healthCheckNamespace,
|
Namespace: healthCheckNamespace,
|
||||||
Labels: map[string]string{
|
Labels: map[string]string{
|
||||||
"app.kubernetes.io/name": "preupgrade-health-check",
|
"app.kubernetes.io/name": "preupgrade-health-check",
|
||||||
"app.kubernetes.io/managed-by": "monok8s",
|
"app.kubernetes.io/managed-by": monov1alpha1.NodeControlName,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.PodSpec{
|
Spec: corev1.PodSpec{
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import (
|
|||||||
func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) error {
|
func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) error {
|
||||||
spec := nctx.Config.Spec
|
spec := nctx.Config.Spec
|
||||||
|
|
||||||
if len(spec.NodeAnnotations) == 0 && len(spec.NodeLabels) == 0 {
|
if len(spec.NodeLabels) == 0 {
|
||||||
klog.V(4).Infof("No annotations or labels was defined")
|
klog.V(4).Infof("No labels was defined")
|
||||||
return nil // nothing to do
|
return nil // nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,9 +53,6 @@ func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) er
|
|||||||
if node.Labels == nil {
|
if node.Labels == nil {
|
||||||
node.Labels = make(map[string]string)
|
node.Labels = make(map[string]string)
|
||||||
}
|
}
|
||||||
if node.Annotations == nil {
|
|
||||||
node.Annotations = make(map[string]string)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply labels
|
// Apply labels
|
||||||
for k, v := range spec.NodeLabels {
|
for k, v := range spec.NodeLabels {
|
||||||
@@ -63,13 +60,8 @@ func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Additional Labels
|
// Additional Labels
|
||||||
if spec.EnableControlAgent {
|
if spec.EnableNodeControl {
|
||||||
node.Labels[monov1alpah1.ControlAgentKey] = controlAgentNodeSelectorValue
|
node.Labels[monov1alpah1.NodeControlKey] = "true"
|
||||||
}
|
|
||||||
|
|
||||||
// Apply annotations
|
|
||||||
for k, v := range spec.NodeAnnotations {
|
|
||||||
node.Annotations[k] = v
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = client.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
|
_, err = client.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
|
||||||
@@ -77,6 +69,6 @@ func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) er
|
|||||||
return fmt.Errorf("update node metadata: %w", err)
|
return fmt.Errorf("update node metadata: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.Infof("applied labels/annotations to node %q", nodeName)
|
klog.Infof("applied labels to node %q", nodeName)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
344
clitools/pkg/render/controller.go
Normal file
344
clitools/pkg/render/controller.go
Normal file
@@ -0,0 +1,344 @@
|
|||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
buildinfo "example.com/monok8s/pkg/buildinfo"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ControllerConf struct {
|
||||||
|
Namespace string
|
||||||
|
Image string
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func RenderControllerDeployments(conf ControllerConf) (string, error) {
|
||||||
|
if conf.Namespace == "" {
|
||||||
|
return "", fmt.Errorf("namespace is required")
|
||||||
|
}
|
||||||
|
|
||||||
|
conf.Labels = map[string]string{
|
||||||
|
"app.kubernetes.io/name": monov1alpha1.ControllerName,
|
||||||
|
"app.kubernetes.io/component": "controller",
|
||||||
|
"app.kubernetes.io/part-of": "monok8s",
|
||||||
|
"app.kubernetes.io/managed-by": monov1alpha1.NodeControlName,
|
||||||
|
}
|
||||||
|
|
||||||
|
objs := []runtime.Object{
|
||||||
|
buildControllerServiceAccount(conf),
|
||||||
|
buildControllerClusterRole(conf),
|
||||||
|
buildControllerClusterRoleBinding(conf),
|
||||||
|
buildControllerDeployment(conf),
|
||||||
|
}
|
||||||
|
|
||||||
|
s := runtime.NewScheme()
|
||||||
|
_ = corev1.AddToScheme(s)
|
||||||
|
_ = rbacv1.AddToScheme(s)
|
||||||
|
_ = appsv1.AddToScheme(s)
|
||||||
|
|
||||||
|
serializer := json.NewYAMLSerializer(json.DefaultMetaFactory, s, s)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
for i, obj := range objs {
|
||||||
|
if i > 0 {
|
||||||
|
if _, err := fmt.Fprintln(&buf, "---"); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := serializer.Encode(obj, &buf); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildControllerServiceAccount(conf ControllerConf) *corev1.ServiceAccount {
|
||||||
|
|
||||||
|
automount := true
|
||||||
|
|
||||||
|
return &corev1.ServiceAccount{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "v1",
|
||||||
|
Kind: "ServiceAccount",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
Namespace: conf.Namespace,
|
||||||
|
Labels: conf.Labels,
|
||||||
|
},
|
||||||
|
AutomountServiceAccountToken: &automount,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildControllerClusterRole(conf ControllerConf) *rbacv1.ClusterRole {
|
||||||
|
wantRules := []rbacv1.PolicyRule{
|
||||||
|
{
|
||||||
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
|
Resources: []string{"osupgrades"},
|
||||||
|
Verbs: []string{"get", "list", "watch"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
|
Resources: []string{"osupgrades/status"},
|
||||||
|
Verbs: []string{"get", "patch", "update"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
|
Resources: []string{"osupgradeprogresses"},
|
||||||
|
Verbs: []string{"get", "create"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
APIGroups: []string{monov1alpha1.Group},
|
||||||
|
Resources: []string{"osupgradeprogresses/status"},
|
||||||
|
Verbs: []string{"update"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
APIGroups: []string{""},
|
||||||
|
Resources: []string{"nodes"},
|
||||||
|
Verbs: []string{"get", "list"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rbacv1.ClusterRole{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "rbac.authorization.k8s.io/v1",
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
Labels: conf.Labels,
|
||||||
|
},
|
||||||
|
Rules: wantRules,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildControllerClusterRoleBinding(conf ControllerConf) *rbacv1.ClusterRoleBinding {
|
||||||
|
|
||||||
|
wantSubjects := []rbacv1.Subject{
|
||||||
|
{
|
||||||
|
Kind: "ServiceAccount",
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
Namespace: conf.Namespace,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
wantRoleRef := rbacv1.RoleRef{
|
||||||
|
APIGroup: rbacv1.GroupName,
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &rbacv1.ClusterRoleBinding{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "rbac.authorization.k8s.io/v1",
|
||||||
|
Kind: "ClusterRoleBinding",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
Labels: conf.Labels,
|
||||||
|
},
|
||||||
|
Subjects: wantSubjects,
|
||||||
|
RoleRef: wantRoleRef,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildControllerDeployment(conf ControllerConf) *appsv1.Deployment {
|
||||||
|
replicas := int32(1)
|
||||||
|
|
||||||
|
selectorLabels := map[string]string{
|
||||||
|
"app.kubernetes.io/name": monov1alpha1.ControllerName,
|
||||||
|
"app.kubernetes.io/component": "controller",
|
||||||
|
}
|
||||||
|
|
||||||
|
podLabels := mergeStringMaps(conf.Labels, selectorLabels)
|
||||||
|
|
||||||
|
runAsNonRoot := true
|
||||||
|
allowPrivilegeEscalation := false
|
||||||
|
userGroup := int64(65532)
|
||||||
|
|
||||||
|
image, pullPolicy := controllerImage(conf)
|
||||||
|
|
||||||
|
return &appsv1.Deployment{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "apps/v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: monov1alpha1.ControllerName,
|
||||||
|
Namespace: conf.Namespace,
|
||||||
|
Labels: conf.Labels,
|
||||||
|
},
|
||||||
|
Spec: appsv1.DeploymentSpec{
|
||||||
|
Replicas: &replicas,
|
||||||
|
Selector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: selectorLabels,
|
||||||
|
},
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: podLabels,
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
ServiceAccountName: monov1alpha1.ControllerName,
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: "controller",
|
||||||
|
Image: image,
|
||||||
|
ImagePullPolicy: pullPolicy,
|
||||||
|
Args: []string{
|
||||||
|
"controller",
|
||||||
|
"--namespace",
|
||||||
|
conf.Namespace,
|
||||||
|
},
|
||||||
|
Env: []corev1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "POD_NAME",
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
FieldRef: &corev1.ObjectFieldSelector{
|
||||||
|
APIVersion: "v1",
|
||||||
|
FieldPath: "metadata.name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "POD_NAMESPACE",
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
FieldRef: &corev1.ObjectFieldSelector{
|
||||||
|
APIVersion: "v1",
|
||||||
|
FieldPath: "metadata.namespace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "NODE_NAME",
|
||||||
|
ValueFrom: &corev1.EnvVarSource{
|
||||||
|
FieldRef: &corev1.ObjectFieldSelector{
|
||||||
|
APIVersion: "v1",
|
||||||
|
FieldPath: "spec.nodeName",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Ports: []corev1.ContainerPort{
|
||||||
|
{
|
||||||
|
Name: "http",
|
||||||
|
ContainerPort: 8080,
|
||||||
|
Protocol: corev1.ProtocolTCP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "https",
|
||||||
|
ContainerPort: 8443,
|
||||||
|
Protocol: corev1.ProtocolTCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
LivenessProbe: &corev1.Probe{
|
||||||
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
|
Path: "/healthz",
|
||||||
|
Port: intstr.FromString("http"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InitialDelaySeconds: 5,
|
||||||
|
PeriodSeconds: 60,
|
||||||
|
TimeoutSeconds: 2,
|
||||||
|
FailureThreshold: 3,
|
||||||
|
},
|
||||||
|
ReadinessProbe: &corev1.Probe{
|
||||||
|
ProbeHandler: corev1.ProbeHandler{
|
||||||
|
HTTPGet: &corev1.HTTPGetAction{
|
||||||
|
Path: "/readyz",
|
||||||
|
Port: intstr.FromString("http"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
InitialDelaySeconds: 2,
|
||||||
|
PeriodSeconds: 5,
|
||||||
|
TimeoutSeconds: 2,
|
||||||
|
FailureThreshold: 3,
|
||||||
|
},
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
RunAsNonRoot: &runAsNonRoot,
|
||||||
|
RunAsUser: &userGroup,
|
||||||
|
RunAsGroup: &userGroup,
|
||||||
|
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
NodeSelector: controllerNodeSelector(conf),
|
||||||
|
Affinity: controllerAffinity(conf),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func controllerImage(conf ControllerConf) (string, corev1.PullPolicy) {
|
||||||
|
if conf.Image != "" {
|
||||||
|
return conf.Image, corev1.PullIfNotPresent
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("localhost/monok8s/node-control:%s", buildinfo.Version), corev1.PullNever
|
||||||
|
}
|
||||||
|
|
||||||
|
func controllerNodeSelector(conf ControllerConf) map[string]string {
|
||||||
|
if conf.Image != "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local image exists on managed nodes only.
|
||||||
|
return map[string]string{
|
||||||
|
monov1alpha1.NodeControlKey: "true",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func controllerAffinity(conf ControllerConf) *corev1.Affinity {
|
||||||
|
// Local image exists only on managed nodes, so in that mode we already use
|
||||||
|
// NodeSelector and should not fight placement with anti-affinity.
|
||||||
|
if conf.Image == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return &corev1.Affinity{
|
||||||
|
PodAntiAffinity: &corev1.PodAntiAffinity{
|
||||||
|
PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{
|
||||||
|
{
|
||||||
|
Weight: 100,
|
||||||
|
PodAffinityTerm: corev1.PodAffinityTerm{
|
||||||
|
TopologyKey: corev1.LabelHostname,
|
||||||
|
LabelSelector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: monov1alpha1.NodeAgentLabels(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeStringMaps(maps ...map[string]string) map[string]string {
|
||||||
|
var total int
|
||||||
|
for _, m := range maps {
|
||||||
|
total += len(m)
|
||||||
|
}
|
||||||
|
if total == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
out := make(map[string]string, total)
|
||||||
|
for _, m := range maps {
|
||||||
|
for k, v := range m {
|
||||||
|
out[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package templates
|
package render
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -31,10 +31,12 @@ func RenderMonoKSConfig() (string, error) {
|
|||||||
return buf.String(), nil
|
return buf.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RenderOSUpgrade() (string, error) {
|
func RenderOSUpgrade(namespace string) (string, error) {
|
||||||
vals := templates.LoadTemplateValuesFromEnv()
|
vals := templates.LoadTemplateValuesFromEnv()
|
||||||
cfg := templates.DefaultOSUpgrade(vals)
|
cfg := templates.DefaultOSUpgrade(vals)
|
||||||
|
|
||||||
|
cfg.Namespace = namespace
|
||||||
|
|
||||||
s := runtime.NewScheme()
|
s := runtime.NewScheme()
|
||||||
if err := monov1alpha1.AddToScheme(s); err != nil {
|
if err := monov1alpha1.AddToScheme(s); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|||||||
329
clitools/pkg/render/sshd.go
Normal file
329
clitools/pkg/render/sshd.go
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
package render
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||||
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
|
|
||||||
|
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||||
|
"example.com/monok8s/pkg/templates"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
sshdName = "sshd"
|
||||||
|
sshdConfigName = "sshd-authorized-keys"
|
||||||
|
sshdNodePort = int32(30022)
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenderSSHDDeployments(namespace, authKeys string) (string, error) {
|
||||||
|
vals := templates.LoadTemplateValuesFromEnv()
|
||||||
|
|
||||||
|
labels := map[string]string{
|
||||||
|
"app.kubernetes.io/name": sshdName,
|
||||||
|
"app.kubernetes.io/component": "host-access",
|
||||||
|
"app.kubernetes.io/part-of": "monok8s",
|
||||||
|
"app.kubernetes.io/managed-by": monov1alpha1.NodeControlName,
|
||||||
|
}
|
||||||
|
|
||||||
|
objs := []runtime.Object{
|
||||||
|
buildSSHDConfigMap(authKeys, namespace, labels),
|
||||||
|
buildSSHDService(vals, namespace, labels),
|
||||||
|
buildSSHDDeployment(vals, namespace, labels),
|
||||||
|
}
|
||||||
|
|
||||||
|
s := runtime.NewScheme()
|
||||||
|
_ = corev1.AddToScheme(s)
|
||||||
|
_ = rbacv1.AddToScheme(s)
|
||||||
|
_ = appsv1.AddToScheme(s)
|
||||||
|
|
||||||
|
serializer := json.NewYAMLSerializer(json.DefaultMetaFactory, s, s)
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
|
||||||
|
for i, obj := range objs {
|
||||||
|
if i > 0 {
|
||||||
|
if _, err := fmt.Fprintln(&buf, "---"); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := serializer.Encode(obj, &buf); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.String(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSSHDConfigMap(
|
||||||
|
authorizedKeys string,
|
||||||
|
namespace string,
|
||||||
|
labels map[string]string,
|
||||||
|
) *corev1.ConfigMap {
|
||||||
|
|
||||||
|
return &corev1.ConfigMap{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "v1",
|
||||||
|
Kind: "ConfigMap",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: sshdConfigName,
|
||||||
|
Namespace: namespace,
|
||||||
|
Labels: labels,
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"authorized_keys": authorizedKeys,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSSHDService(
|
||||||
|
tVals templates.TemplateValues,
|
||||||
|
namespace string,
|
||||||
|
labels map[string]string,
|
||||||
|
) *corev1.Service {
|
||||||
|
selectorLabels := map[string]string{
|
||||||
|
monov1alpha1.NodeControlKey: "true",
|
||||||
|
"kubernetes.io/hostname": tVals.NodeName,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &corev1.Service{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "v1",
|
||||||
|
Kind: "Service",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: sshdName,
|
||||||
|
Namespace: namespace,
|
||||||
|
Labels: labels,
|
||||||
|
},
|
||||||
|
Spec: corev1.ServiceSpec{
|
||||||
|
Type: corev1.ServiceTypeNodePort,
|
||||||
|
Selector: selectorLabels,
|
||||||
|
Ports: []corev1.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "ssh",
|
||||||
|
Protocol: corev1.ProtocolTCP,
|
||||||
|
Port: 22,
|
||||||
|
TargetPort: intstr.FromInt32(22),
|
||||||
|
NodePort: sshdNodePort,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildSSHDDeployment(
|
||||||
|
tVals templates.TemplateValues,
|
||||||
|
namespace string,
|
||||||
|
labels map[string]string,
|
||||||
|
) *appsv1.Deployment {
|
||||||
|
replicas := int32(1)
|
||||||
|
|
||||||
|
selectorLabels := map[string]string{
|
||||||
|
monov1alpha1.NodeControlKey: "true",
|
||||||
|
"kubernetes.io/hostname": tVals.NodeName,
|
||||||
|
}
|
||||||
|
|
||||||
|
podLabels := mergeStringMaps(labels, selectorLabels)
|
||||||
|
|
||||||
|
runAsUser := int64(0)
|
||||||
|
runAsNonRoot := false
|
||||||
|
privileged := true
|
||||||
|
allowPrivilegeEscalation := true
|
||||||
|
readOnlyRootFilesystem := false
|
||||||
|
|
||||||
|
return &appsv1.Deployment{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "apps/v1",
|
||||||
|
Kind: "Deployment",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: sshdName,
|
||||||
|
Namespace: namespace,
|
||||||
|
Labels: labels,
|
||||||
|
},
|
||||||
|
Spec: appsv1.DeploymentSpec{
|
||||||
|
Replicas: &replicas,
|
||||||
|
Selector: &metav1.LabelSelector{
|
||||||
|
MatchLabels: selectorLabels,
|
||||||
|
},
|
||||||
|
Template: corev1.PodTemplateSpec{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Labels: podLabels,
|
||||||
|
},
|
||||||
|
Spec: corev1.PodSpec{
|
||||||
|
HostPID: true,
|
||||||
|
NodeSelector: selectorLabels,
|
||||||
|
Containers: []corev1.Container{
|
||||||
|
{
|
||||||
|
Name: sshdName,
|
||||||
|
Image: "alpine:latest",
|
||||||
|
Command: []string{
|
||||||
|
"/bin/sh",
|
||||||
|
"-ceu",
|
||||||
|
`
|
||||||
|
apk add --no-cache openssh-server
|
||||||
|
|
||||||
|
mkdir -p /run/sshd
|
||||||
|
mkdir -p /root/.ssh
|
||||||
|
|
||||||
|
cp /authorized-keys/authorized_keys /root/.ssh/authorized_keys
|
||||||
|
chmod 700 /root/.ssh
|
||||||
|
chmod 600 /root/.ssh/authorized_keys
|
||||||
|
|
||||||
|
ssh-keygen -A
|
||||||
|
|
||||||
|
exec /usr/sbin/sshd \
|
||||||
|
-D \
|
||||||
|
-e \
|
||||||
|
-p 22 \
|
||||||
|
-o PermitRootLogin=prohibit-password \
|
||||||
|
-o PasswordAuthentication=no \
|
||||||
|
-o KbdInteractiveAuthentication=no \
|
||||||
|
-o PubkeyAuthentication=yes \
|
||||||
|
-o AuthorizedKeysFile=/root/.ssh/authorized_keys
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
Ports: []corev1.ContainerPort{
|
||||||
|
{
|
||||||
|
Name: "ssh",
|
||||||
|
ContainerPort: 22,
|
||||||
|
Protocol: corev1.ProtocolTCP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
SecurityContext: &corev1.SecurityContext{
|
||||||
|
RunAsUser: &runAsUser,
|
||||||
|
RunAsNonRoot: &runAsNonRoot,
|
||||||
|
Privileged: &privileged,
|
||||||
|
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
||||||
|
ReadOnlyRootFilesystem: &readOnlyRootFilesystem,
|
||||||
|
},
|
||||||
|
Resources: corev1.ResourceRequirements{
|
||||||
|
Requests: corev1.ResourceList{
|
||||||
|
corev1.ResourceCPU: resource.MustParse("10m"),
|
||||||
|
corev1.ResourceMemory: resource.MustParse("32Mi"),
|
||||||
|
},
|
||||||
|
Limits: corev1.ResourceList{
|
||||||
|
corev1.ResourceCPU: resource.MustParse("200m"),
|
||||||
|
corev1.ResourceMemory: resource.MustParse("128Mi"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMounts: append(
|
||||||
|
[]corev1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: "authorized-keys",
|
||||||
|
MountPath: "/authorized-keys",
|
||||||
|
ReadOnly: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
buildHostRootVolumeMounts()...,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Volumes: append(
|
||||||
|
[]corev1.Volume{
|
||||||
|
{
|
||||||
|
Name: "authorized-keys",
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
ConfigMap: &corev1.ConfigMapVolumeSource{
|
||||||
|
LocalObjectReference: corev1.LocalObjectReference{
|
||||||
|
Name: sshdConfigName,
|
||||||
|
},
|
||||||
|
DefaultMode: ptrInt32(0600),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
buildHostRootVolumes()...,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRootVolumeMounts() []corev1.VolumeMount {
|
||||||
|
paths := []struct {
|
||||||
|
name string
|
||||||
|
mountPath string
|
||||||
|
readOnly bool
|
||||||
|
}{
|
||||||
|
{"host-bin", "/host/bin", true},
|
||||||
|
{"host-sbin", "/host/sbin", true},
|
||||||
|
{"host-lib", "/host/lib", true},
|
||||||
|
{"host-usr", "/host/usr", true},
|
||||||
|
{"host-etc", "/host/etc", false},
|
||||||
|
{"host-run", "/host/run", false},
|
||||||
|
{"host-proc", "/host/proc", false},
|
||||||
|
{"host-sys", "/host/sys", false},
|
||||||
|
{"host-dev", "/host/dev", false},
|
||||||
|
{"host-var", "/host/var", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts := make([]corev1.VolumeMount, 0, len(paths))
|
||||||
|
|
||||||
|
for _, p := range paths {
|
||||||
|
mounts = append(mounts, corev1.VolumeMount{
|
||||||
|
Name: p.name,
|
||||||
|
MountPath: p.mountPath,
|
||||||
|
ReadOnly: p.readOnly,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return mounts
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildHostRootVolumes() []corev1.Volume {
|
||||||
|
hostPathDir := corev1.HostPathDirectory
|
||||||
|
|
||||||
|
paths := []struct {
|
||||||
|
name string
|
||||||
|
path string
|
||||||
|
}{
|
||||||
|
{"host-bin", "/bin"},
|
||||||
|
{"host-sbin", "/sbin"},
|
||||||
|
{"host-lib", "/lib"},
|
||||||
|
{"host-usr", "/usr"},
|
||||||
|
{"host-etc", "/etc"},
|
||||||
|
{"host-run", "/run"},
|
||||||
|
{"host-proc", "/proc"},
|
||||||
|
{"host-sys", "/sys"},
|
||||||
|
{"host-dev", "/dev"},
|
||||||
|
|
||||||
|
// /var is an rbind mount in monok8s and may be private.
|
||||||
|
// Mount the real backing path instead.
|
||||||
|
{"host-var", "/data/var"},
|
||||||
|
}
|
||||||
|
|
||||||
|
volumes := make([]corev1.Volume, 0, len(paths))
|
||||||
|
|
||||||
|
for _, p := range paths {
|
||||||
|
volumes = append(volumes, corev1.Volume{
|
||||||
|
Name: p.name,
|
||||||
|
VolumeSource: corev1.VolumeSource{
|
||||||
|
HostPath: &corev1.HostPathVolumeSource{
|
||||||
|
Path: p.path,
|
||||||
|
Type: &hostPathDir,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return volumes
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptrInt32(v int32) *int32 {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
|
|
||||||
|
func ptrHostPathType(v corev1.HostPathType) *corev1.HostPathType {
|
||||||
|
return &v
|
||||||
|
}
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultNamespace = "kube-system"
|
const DefaultNamespace = "mono-system"
|
||||||
|
|
||||||
func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
||||||
return monov1alpha1.MonoKSConfig{
|
return monov1alpha1.MonoKSConfig{
|
||||||
@@ -25,7 +25,7 @@ func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
|||||||
|
|
||||||
ClusterRole: v.ClusterRole,
|
ClusterRole: v.ClusterRole,
|
||||||
InitControlPlane: v.InitControlPlane,
|
InitControlPlane: v.InitControlPlane,
|
||||||
EnableControlAgent: v.EnableControlAgent,
|
EnableNodeControl: v.EnableNodeControl,
|
||||||
|
|
||||||
ClusterName: v.ClusterName,
|
ClusterName: v.ClusterName,
|
||||||
ClusterDomain: v.ClusterDomain,
|
ClusterDomain: v.ClusterDomain,
|
||||||
@@ -51,7 +51,6 @@ func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
|||||||
|
|
||||||
SubjectAltNames: copyStringSlice(v.SubjectAltNames),
|
SubjectAltNames: copyStringSlice(v.SubjectAltNames),
|
||||||
NodeLabels: copyStringMap(v.NodeLabels),
|
NodeLabels: copyStringMap(v.NodeLabels),
|
||||||
NodeAnnotations: copyStringMap(v.NodeAnnotations),
|
|
||||||
|
|
||||||
Network: monov1alpha1.NetworkSpec{
|
Network: monov1alpha1.NetworkSpec{
|
||||||
Hostname: firstNonEmpty(v.Hostname, v.NodeName),
|
Hostname: firstNonEmpty(v.Hostname, v.NodeName),
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ type TemplateValues struct {
|
|||||||
|
|
||||||
ClusterRole string // worker, control-plane
|
ClusterRole string // worker, control-plane
|
||||||
InitControlPlane bool
|
InitControlPlane bool
|
||||||
EnableControlAgent bool
|
EnableNodeControl bool
|
||||||
|
|
||||||
AllowSchedulingOnControlPlane bool
|
AllowSchedulingOnControlPlane bool
|
||||||
SkipImageCheck bool
|
SkipImageCheck bool
|
||||||
@@ -39,7 +39,6 @@ type TemplateValues struct {
|
|||||||
|
|
||||||
SubjectAltNames []string
|
SubjectAltNames []string
|
||||||
NodeLabels map[string]string
|
NodeLabels map[string]string
|
||||||
NodeAnnotations map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultTemplateValues() TemplateValues {
|
func defaultTemplateValues() TemplateValues {
|
||||||
@@ -61,7 +60,7 @@ func defaultTemplateValues() TemplateValues {
|
|||||||
|
|
||||||
ClusterRole: "control-plane",
|
ClusterRole: "control-plane",
|
||||||
InitControlPlane: true,
|
InitControlPlane: true,
|
||||||
EnableControlAgent: true,
|
EnableNodeControl: true,
|
||||||
|
|
||||||
AllowSchedulingOnControlPlane: true,
|
AllowSchedulingOnControlPlane: true,
|
||||||
SkipImageCheck: false,
|
SkipImageCheck: false,
|
||||||
@@ -78,9 +77,6 @@ func defaultTemplateValues() TemplateValues {
|
|||||||
NodeLabels: map[string]string{
|
NodeLabels: map[string]string{
|
||||||
monov1alpha1.Label: "value",
|
monov1alpha1.Label: "value",
|
||||||
},
|
},
|
||||||
NodeAnnotations: map[string]string{
|
|
||||||
monov1alpha1.Annotation: "value",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +84,7 @@ func LoadTemplateValuesFromEnv() TemplateValues {
|
|||||||
v := defaultTemplateValues()
|
v := defaultTemplateValues()
|
||||||
|
|
||||||
v.Hostname = getenvDefault("MKS_HOSTNAME", v.Hostname)
|
v.Hostname = getenvDefault("MKS_HOSTNAME", v.Hostname)
|
||||||
v.NodeName = getenvDefault("MKS_NODE_NAME", v.Hostname)
|
v.NodeName = getenvDefault("MKS_NODE_NAME", getenvDefault("NODE_NAME", v.Hostname))
|
||||||
|
|
||||||
v.KubernetesVersion = getenvDefault("MKS_KUBERNETES_VERSION", v.KubernetesVersion)
|
v.KubernetesVersion = getenvDefault("MKS_KUBERNETES_VERSION", v.KubernetesVersion)
|
||||||
v.ClusterName = getenvDefault("MKS_CLUSTER_NAME", v.ClusterName)
|
v.ClusterName = getenvDefault("MKS_CLUSTER_NAME", v.ClusterName)
|
||||||
@@ -108,7 +104,7 @@ func LoadTemplateValuesFromEnv() TemplateValues {
|
|||||||
|
|
||||||
v.ClusterRole = getenvDefault("MKS_CLUSTER_ROLE", v.ClusterRole)
|
v.ClusterRole = getenvDefault("MKS_CLUSTER_ROLE", v.ClusterRole)
|
||||||
v.InitControlPlane = getenvBoolDefault("MKS_INIT_CONTROL_PLANE", v.InitControlPlane)
|
v.InitControlPlane = getenvBoolDefault("MKS_INIT_CONTROL_PLANE", v.InitControlPlane)
|
||||||
v.EnableControlAgent = getenvBoolDefault("MKS_ENABLE_CONTROL_AGENT", v.EnableControlAgent)
|
v.EnableNodeControl = getenvBoolDefault("MKS_ENABLE_NODE_CONTROL", v.EnableNodeControl)
|
||||||
|
|
||||||
v.AllowSchedulingOnControlPlane = getenvBoolDefault("MKS_ALLOW_SCHEDULING_ON_CONTROL_PLANE", v.AllowSchedulingOnControlPlane)
|
v.AllowSchedulingOnControlPlane = getenvBoolDefault("MKS_ALLOW_SCHEDULING_ON_CONTROL_PLANE", v.AllowSchedulingOnControlPlane)
|
||||||
v.SkipImageCheck = getenvBoolDefault("MKS_SKIP_IMAGE_CHECK", v.SkipImageCheck)
|
v.SkipImageCheck = getenvBoolDefault("MKS_SKIP_IMAGE_CHECK", v.SkipImageCheck)
|
||||||
@@ -129,9 +125,6 @@ func LoadTemplateValuesFromEnv() TemplateValues {
|
|||||||
if m := parseKeyValueMap(os.Getenv("MKS_NODE_LABELS")); len(m) > 0 {
|
if m := parseKeyValueMap(os.Getenv("MKS_NODE_LABELS")); len(m) > 0 {
|
||||||
v.NodeLabels = m
|
v.NodeLabels = m
|
||||||
}
|
}
|
||||||
if m := parseKeyValueMap(os.Getenv("MKS_NODE_ANNOTATIONS")); len(m) > 0 {
|
|
||||||
v.NodeAnnotations = m
|
|
||||||
}
|
|
||||||
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ MKS_CLUSTER_DOMAIN=cluster.local
|
|||||||
MKS_CLUSTER_ROLE=control-plane
|
MKS_CLUSTER_ROLE=control-plane
|
||||||
MKS_INIT_CONTROL_PLANE=yes
|
MKS_INIT_CONTROL_PLANE=yes
|
||||||
|
|
||||||
# OSUpgrade agent
|
# Enable if you want OTA OSUpgrade
|
||||||
MKS_ENABLE_CONTROL_AGENT=yes
|
MKS_ENABLE_NODE_CONTROL=yes
|
||||||
|
|
||||||
# Boot configs
|
# Boot configs
|
||||||
# usb, emmc
|
# usb, emmc
|
||||||
@@ -56,8 +56,7 @@ MKS_CNI_PLUGIN=default
|
|||||||
|
|
||||||
# Node registration metadata
|
# Node registration metadata
|
||||||
# Comma-separated key=value pairs
|
# Comma-separated key=value pairs
|
||||||
MKS_NODE_LABELS=topology.kubernetes.io/zone=lab,node.kubernetes.io/instance-type=mono-gateway
|
MKS_NODE_LABELS=topology.kubernetes.io/zone=lab,node.kubernetes.io/instance-type=mono-gateway,mono.si/board=ls1046a
|
||||||
MKS_NODE_ANNOTATIONS=mono.si/board=ls1046a,monok8s.io/image-version=dev
|
|
||||||
|
|
||||||
# Optional
|
# Optional
|
||||||
# Extra API server SANs, comma-separated
|
# Extra API server SANs, comma-separated
|
||||||
|
|||||||
248
devtools/build-all.sh
Executable file
248
devtools/build-all.sh
Executable file
@@ -0,0 +1,248 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
OUT_DIR="$(realpath "$SCRIPT_DIR/../out/")"
|
||||||
|
|
||||||
|
cd "$SCRIPT_DIR/../"
|
||||||
|
|
||||||
|
# ===== CONFIG TABLE =====
|
||||||
|
# Add supported concrete builds here.
|
||||||
|
# format: kube=crio
|
||||||
|
CONFIGS=(
|
||||||
|
"v1.33.3=cri-o.arm64.v1.33.3"
|
||||||
|
"v1.34.1=cri-o.arm64.v1.34.1"
|
||||||
|
"v1.35.3=cri-o.arm64.v1.35.2"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ===== HELPERS =====
|
||||||
|
|
||||||
|
strip_v() {
|
||||||
|
echo "${1#v}"
|
||||||
|
}
|
||||||
|
|
||||||
|
minor_of_version() {
|
||||||
|
# input: 1.35.3 or v1.35.3
|
||||||
|
local v="${1#v}"
|
||||||
|
IFS='.' read -r major minor patch <<< "$v"
|
||||||
|
echo "$major.$minor"
|
||||||
|
}
|
||||||
|
|
||||||
|
version_sort() {
|
||||||
|
sort -t. -k1,1n -k2,2n -k3,3n
|
||||||
|
}
|
||||||
|
|
||||||
|
list_configs() {
|
||||||
|
echo "Available build targets:"
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
local kube="${c%%=*}"
|
||||||
|
local crio="${c##*=}"
|
||||||
|
echo " ${kube#v} (CRI-O: $crio)"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
list_minors() {
|
||||||
|
echo "Latest supported target per minor:"
|
||||||
|
latest_per_minor | while read -r kube crio; do
|
||||||
|
echo " ${kube#v} (CRI-O: $crio)"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
latest_per_minor() {
|
||||||
|
# Output lines: <kube> <crio>
|
||||||
|
local minors
|
||||||
|
minors="$(
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
kube="${c%%=*}"
|
||||||
|
minor_of_version "$kube"
|
||||||
|
done | sort -uV
|
||||||
|
)"
|
||||||
|
|
||||||
|
while read -r minor; do
|
||||||
|
[ -n "$minor" ] || continue
|
||||||
|
resolve_minor "$minor"
|
||||||
|
done <<< "$minors"
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_exact() {
|
||||||
|
local target="$1"
|
||||||
|
local target_v="v${target#v}"
|
||||||
|
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
local kube="${c%%=*}"
|
||||||
|
local crio="${c##*=}"
|
||||||
|
if [[ "$kube" == "$target_v" ]]; then
|
||||||
|
echo "$kube $crio"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve_minor() {
|
||||||
|
# input: 1.35 or v1.35
|
||||||
|
local want_minor
|
||||||
|
want_minor="$(minor_of_version "${1#v}.0")"
|
||||||
|
|
||||||
|
local matches=()
|
||||||
|
local c kube crio
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
kube="${c%%=*}"
|
||||||
|
crio="${c##*=}"
|
||||||
|
if [[ "$(minor_of_version "$kube")" == "$want_minor" ]]; then
|
||||||
|
matches+=("${kube}=${crio}")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${#matches[@]} -eq 0 ]]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local latest_kube
|
||||||
|
latest_kube="$(
|
||||||
|
for c in "${matches[@]}"; do
|
||||||
|
echo "${c%%=*#}" | sed 's/^v//'
|
||||||
|
done | version_sort | tail -n1
|
||||||
|
)"
|
||||||
|
|
||||||
|
resolve_exact "$latest_kube"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_exact() {
|
||||||
|
local target="$1"
|
||||||
|
local resolved
|
||||||
|
if ! resolved="$(resolve_exact "$target")"; then
|
||||||
|
echo "❌ Unknown exact target: $target" >&2
|
||||||
|
echo >&2
|
||||||
|
list_configs >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local kube crio
|
||||||
|
read -r kube crio <<< "$resolved"
|
||||||
|
|
||||||
|
echo ">>> Building Kubernetes $kube with $crio"
|
||||||
|
make release CRIO_VERSION="$crio" KUBE_VERSION="$kube"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_minor() {
|
||||||
|
local minor="$1"
|
||||||
|
local resolved
|
||||||
|
if ! resolved="$(resolve_minor "$minor")"; then
|
||||||
|
echo "❌ No supported target found for minor: $minor" >&2
|
||||||
|
echo >&2
|
||||||
|
list_minors >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
local kube crio
|
||||||
|
read -r kube crio <<< "$resolved"
|
||||||
|
|
||||||
|
echo ">>> Minor $minor resolved to latest supported target ${kube#v}"
|
||||||
|
echo ">>> Building Kubernetes $kube with $crio"
|
||||||
|
make release CRIO_VERSION="$crio" KUBE_VERSION="$kube"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_range() {
|
||||||
|
# input like 1.33-1.35
|
||||||
|
local range="$1"
|
||||||
|
local start="${range%-*}"
|
||||||
|
local end="${range#*-}"
|
||||||
|
|
||||||
|
local start_minor="${start#v}"
|
||||||
|
local end_minor="${end#v}"
|
||||||
|
|
||||||
|
local any=0
|
||||||
|
while read -r minor; do
|
||||||
|
[ -n "$minor" ] || continue
|
||||||
|
|
||||||
|
# simple lexical-safe because format is N.N and sort -V was used
|
||||||
|
if [[ "$(printf '%s\n%s\n' "$start_minor" "$minor" | sort -V | head -n1)" != "$start_minor" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [[ "$(printf '%s\n%s\n' "$minor" "$end_minor" | sort -V | head -n1)" != "$minor" ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
any=1
|
||||||
|
build_minor "$minor"
|
||||||
|
done < <(
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
kube="${c%%=*}"
|
||||||
|
minor_of_version "$kube"
|
||||||
|
done | sort -uV
|
||||||
|
)
|
||||||
|
|
||||||
|
if [[ $any -eq 0 ]]; then
|
||||||
|
echo "❌ No supported minors found in range: $range" >&2
|
||||||
|
echo >&2
|
||||||
|
list_minors >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
build_all() {
|
||||||
|
local c kube crio
|
||||||
|
for c in "${CONFIGS[@]}"; do
|
||||||
|
kube="${c%%=*}"
|
||||||
|
crio="${c##*=}"
|
||||||
|
echo ">>> Building Kubernetes $kube with $crio"
|
||||||
|
make release CRIO_VERSION="$crio" KUBE_VERSION="$kube"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
Usage:
|
||||||
|
./devtools/build-all.sh
|
||||||
|
./devtools/build-all.sh list
|
||||||
|
./devtools/build-all.sh list-minors
|
||||||
|
./devtools/build-all.sh 1.35.3
|
||||||
|
./devtools/build-all.sh 1.35
|
||||||
|
./devtools/build-all.sh 1.33-1.35
|
||||||
|
|
||||||
|
Behavior:
|
||||||
|
no args Build all configured targets
|
||||||
|
list List all exact configured targets
|
||||||
|
list-minors List latest supported target per minor
|
||||||
|
X.Y.Z Build exact version
|
||||||
|
X.Y Build latest supported patch in that minor
|
||||||
|
X.Y-A.B Build latest supported patch for each minor in range
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===== ENTRY =====
|
||||||
|
|
||||||
|
if [[ $# -eq 0 ]]; then
|
||||||
|
echo "No target specified -> building all configured targets"
|
||||||
|
build_all
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
list)
|
||||||
|
list_configs
|
||||||
|
;;
|
||||||
|
list-minors)
|
||||||
|
list_minors
|
||||||
|
;;
|
||||||
|
-*|--help|help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*-*)
|
||||||
|
build_range "$1"
|
||||||
|
;;
|
||||||
|
*.*.*)
|
||||||
|
build_exact "$1"
|
||||||
|
;;
|
||||||
|
*.*)
|
||||||
|
build_minor "$1"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "❌ Unrecognized target: $1" >&2
|
||||||
|
echo >&2
|
||||||
|
usage >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
6
devtools/serve-images.sh
Executable file
6
devtools/serve-images.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
OUT_DIR="$(realpath "$SCRIPT_DIR"/../out/)"
|
||||||
|
|
||||||
|
python3 -m http.server 8000 --bind 0.0.0.0 --directory "$OUT_DIR"
|
||||||
54
devtools/test-upgrade.sh
Executable file
54
devtools/test-upgrade.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
OUT_DIR="$(realpath "$SCRIPT_DIR"/../out/)"
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DEFAULT_BASE_URL="http://localhost:8000"
|
||||||
|
DEFAULT_TARGET_VERSION="v1.34.1"
|
||||||
|
STABLE_VERSION="v1.34.1"
|
||||||
|
NAME="my-upgrade-1"
|
||||||
|
|
||||||
|
if [ -r /dev/tty ]; then
|
||||||
|
printf "Enter the base url (%s): " "$DEFAULT_BASE_URL" > /dev/tty
|
||||||
|
read -r BASE_URL < /dev/tty
|
||||||
|
|
||||||
|
printf "Enter the target version (%s): " "$DEFAULT_TARGET_VERSION" > /dev/tty
|
||||||
|
read -r TARGET_VERSION < /dev/tty
|
||||||
|
else
|
||||||
|
echo "No TTY available for interactive input" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
BASE_URL="${BASE_URL:-$DEFAULT_BASE_URL}"
|
||||||
|
TARGET_VERSION="${TARGET_VERSION:-$DEFAULT_TARGET_VERSION}"
|
||||||
|
|
||||||
|
echo "apiVersion: monok8s.io/v1alpha1"
|
||||||
|
echo "kind: OSUpgrade"
|
||||||
|
echo "metadata:"
|
||||||
|
echo " name: \"$NAME\""
|
||||||
|
echo "spec:"
|
||||||
|
echo " desiredVersion: \"$TARGET_VERSION\""
|
||||||
|
echo " nodeSelector: {}"
|
||||||
|
echo " catalog:"
|
||||||
|
echo " inline: |"
|
||||||
|
echo " stable: $STABLE_VERSION"
|
||||||
|
echo " images:"
|
||||||
|
|
||||||
|
for c in "$OUT_DIR"/catalog-*.txt; do
|
||||||
|
version=$(grep 'version:' "$c" | awk '{print $3}')
|
||||||
|
url=$(grep 'url:' "$c" | sed 's/.*"\(.*\)"/\1/')
|
||||||
|
checksum=$(grep 'checksum:' "$c" | awk '{print $2}')
|
||||||
|
size=$(grep 'size:' "$c" | awk '{print $2}')
|
||||||
|
|
||||||
|
filename=$(basename "$url")
|
||||||
|
|
||||||
|
echo " - version: $version"
|
||||||
|
echo " url: $BASE_URL/$filename"
|
||||||
|
echo " checksum: sha256:$checksum"
|
||||||
|
echo " size: $size"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo " blocked:"
|
||||||
|
echo " - v1.34.0"
|
||||||
204
docs/installing-ssh-pod.md
Normal file
204
docs/installing-ssh-pod.md
Normal file
@@ -0,0 +1,204 @@
|
|||||||
|
# Installing the recovery SSHD pod
|
||||||
|
|
||||||
|
This page explains how to install a temporary SSH server pod for break-glass recovery.
|
||||||
|
|
||||||
|
Use this when normal Kubernetes access is degraded, for example after the API server certificate expires or rotates and you need to retrieve updated host-side credentials.
|
||||||
|
|
||||||
|
The SSHD pod is intended for recovery and debugging only. Remove it when you are done.
|
||||||
|
|
||||||
|
## What this does
|
||||||
|
|
||||||
|
The recovery pod starts an SSH server on the selected node and authorizes your local SSH public key.
|
||||||
|
|
||||||
|
The pod also mounts selected host paths under `/host`, so you can inspect the host filesystem and run some host-side recovery commands through `chroot`.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chroot /host /bin/sh -lc 'rc-status'
|
||||||
|
chroot /host /bin/sh -lc 'rc-service crio status'
|
||||||
|
chroot /host /bin/sh -lc 'rc-service kubelet status'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
You need:
|
||||||
|
|
||||||
|
- A working `kubectl` connection to the cluster.
|
||||||
|
- Access to the `node-agent` DaemonSet in the `mono-system` namespace.
|
||||||
|
- A local SSH public key, usually `~/.ssh/id_rsa.pub` or `~/.ssh/id_ed25519.pub`.
|
||||||
|
|
||||||
|
Use a public key file only. Do not pass your private key.
|
||||||
|
|
||||||
|
## Generate the SSHD manifest
|
||||||
|
|
||||||
|
To print the recovery SSHD manifest:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_rsa.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
This reads your local public key and places it into the generated pod's `authorized_keys`.
|
||||||
|
|
||||||
|
If you use Ed25519 keys, use:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_ed25519.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generate and apply the manifest
|
||||||
|
|
||||||
|
To create the recovery SSHD resources in one step:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_rsa.pub \
|
||||||
|
| kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
For Ed25519:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_ed25519.pub \
|
||||||
|
| kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why `-i` is used instead of `-it`
|
||||||
|
|
||||||
|
Use `-i`, not `-it`, when piping the SSH public key.
|
||||||
|
|
||||||
|
The `-t` option allocates a pseudo-TTY. A pseudo-TTY can modify piped input, which is not what you want when passing an SSH public key through stdin.
|
||||||
|
|
||||||
|
Correct:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_rsa.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
Avoid:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -it -n mono-system ds/node-agent -- \
|
||||||
|
ctl create sshd --authkeys /dev/stdin < ~/.ssh/id_rsa.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
## Check that the pod is running
|
||||||
|
|
||||||
|
After applying the manifest, check the pod:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pods -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
Check the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get svc -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
If the pod does not start, inspect it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl describe pod -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
## Connect through SSH
|
||||||
|
|
||||||
|
The exact SSH command depends on how the generated service exposes the pod.
|
||||||
|
|
||||||
|
If the service uses a NodePort such as `30022`, connect with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh -p 30022 root@<node-ip>
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `<node-ip>` with the node's reachable IP address.
|
||||||
|
|
||||||
|
## Access the host environment
|
||||||
|
|
||||||
|
Inside the SSH session, the host filesystem is available under `/host`.
|
||||||
|
|
||||||
|
Useful checks:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ls -la /host
|
||||||
|
chroot /host /bin/sh -lc 'rc-status'
|
||||||
|
chroot /host /bin/sh -lc 'rc-service crio status'
|
||||||
|
chroot /host /bin/sh -lc 'rc-service kubelet status'
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart CRI-O:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chroot /host /bin/sh -lc 'rc-service crio restart'
|
||||||
|
```
|
||||||
|
|
||||||
|
Restart kubelet:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
chroot /host /bin/sh -lc 'rc-service kubelet restart'
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also inspect host processes from the pod because the recovery pod uses the host PID namespace:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ps aux | grep -E 'kubelet|crio'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes for monok8s host mounts
|
||||||
|
|
||||||
|
The recovery pod does not mount host `/` directly.
|
||||||
|
|
||||||
|
On monok8s, `/` and `/var` may be private mounts. Mounting them directly as host paths can fail with errors such as:
|
||||||
|
|
||||||
|
```text
|
||||||
|
path "/" is mounted on "/" but it is not a shared or slave mount
|
||||||
|
```
|
||||||
|
|
||||||
|
or:
|
||||||
|
|
||||||
|
```text
|
||||||
|
path "/var" is mounted on "/var" but it is not a shared or slave mount
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead, the recovery pod assembles a minimal host root under `/host` from individual host paths.
|
||||||
|
|
||||||
|
For `/var`, it uses the backing path:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/data/var -> /host/var
|
||||||
|
```
|
||||||
|
|
||||||
|
This avoids the private bind-mount issue.
|
||||||
|
|
||||||
|
## Remove the recovery pod
|
||||||
|
|
||||||
|
When recovery is complete, remove the generated resources.
|
||||||
|
|
||||||
|
If the resources use the default SSHD labels:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete deployment -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
kubectl delete service -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
kubectl delete configmap -n mono-system -l app.kubernetes.io/name=sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
If your generated manifest uses a fixed resource name, you can also remove them by name:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete deployment -n mono-system sshd
|
||||||
|
kubectl delete service -n mono-system sshd
|
||||||
|
kubectl delete configmap -n mono-system sshd-authorized-keys
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security warning
|
||||||
|
|
||||||
|
This pod is powerful.
|
||||||
|
|
||||||
|
It runs with root-level recovery access and can inspect or modify host files through `/host`. Treat it as a temporary break-glass tool, not a normal service.
|
||||||
|
|
||||||
|
Do not leave it running after recovery.
|
||||||
198
docs/ota.md
198
docs/ota.md
@@ -1,19 +1,54 @@
|
|||||||
## Upgrade process
|
# OS OTA Upgrades
|
||||||
|
|
||||||
We use an agent to watch the OSUpgrade CRD to handle this. Our image versions follows upstream.
|
MonoK8s upgrades are driven through two custom resources:
|
||||||
|
|
||||||
To issue an upgrade. Simply use
|
- `OSUpgrade`: the user-facing upgrade request.
|
||||||
|
- `OSUpgradeProgress`: the per-node upgrade state watched and executed by the node agent.
|
||||||
|
|
||||||
|
The node agent does the actual upgrade work. It watches `OSUpgradeProgress` resources assigned to its node, downloads the selected image, writes it to the inactive rootfs partition, updates status, and reboots when ready.
|
||||||
|
|
||||||
|
The controller is optional but strongly recommended. It watches `OSUpgrade` resources and creates the matching `OSUpgradeProgress` resources for the target nodes.
|
||||||
|
|
||||||
|
## Install the controller
|
||||||
|
|
||||||
|
By default, each managed node only runs the node agent. The node agent does **not** watch `OSUpgrade` directly; it only watches `OSUpgradeProgress`.
|
||||||
|
|
||||||
|
You can create `OSUpgradeProgress` resources by hand, but normal users should not need to. Install the controller instead, then create `OSUpgrade` resources.
|
||||||
|
|
||||||
|
Install the controller from the existing node-agent image:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl exec -i -n mono-system ds/node-agent -- \
|
||||||
|
ctl create controller --image REPO/IMAGE:TAG | kubectl apply -f -
|
||||||
|
```
|
||||||
|
|
||||||
|
### `--image`
|
||||||
|
|
||||||
|
`--image` is optional.
|
||||||
|
|
||||||
|
If omitted, the generated Deployment uses the local controller image that is already shipped with managed nodes. In that mode, the controller Deployment is scheduled only onto managed nodes because the image is expected to exist locally.
|
||||||
|
|
||||||
|
If provided, the generated Deployment uses that image directly. This is useful when you host the controller image in your own registry.
|
||||||
|
|
||||||
|
There is no official public image repository yet, so external controller images must currently be managed by the operator.
|
||||||
|
|
||||||
|
## Create an upgrade
|
||||||
|
|
||||||
|
Create an `OSUpgrade` resource to request an upgrade:
|
||||||
|
|
||||||
|
```bash
|
||||||
kubectl apply -f upgrade.yaml
|
kubectl apply -f upgrade.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
Example yaml
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: monok8s.io/v1alpha1
|
apiVersion: monok8s.io/v1alpha1
|
||||||
kind: OSUpgrade
|
kind: OSUpgrade
|
||||||
metadata:
|
metadata:
|
||||||
name: "my-ugrade-2"
|
name: my-upgrade-2
|
||||||
spec:
|
spec:
|
||||||
version: "v1.35.3"
|
version: v1.35.3
|
||||||
nodeSelector: {}
|
nodeSelector: {}
|
||||||
catalog:
|
catalog:
|
||||||
inline: |
|
inline: |
|
||||||
@@ -34,24 +69,61 @@ spec:
|
|||||||
- version: v1.35.1
|
- version: v1.35.1
|
||||||
url: http://localhost:8000/rootfs.ext4.zst
|
url: http://localhost:8000/rootfs.ext4.zst
|
||||||
checksum: sha256:99af82a263deca44ad91d21d684f0fa944d5d0456a1da540f1c644f8aa59b14b
|
checksum: sha256:99af82a263deca44ad91d21d684f0fa944d5d0456a1da540f1c644f8aa59b14b
|
||||||
size: 1858076672 # expanded image size in bytes, use "zstd -lv image.zst to check"
|
size: 1858076672 # expanded image size in bytes; check with: zstd -lv image.zst
|
||||||
blocked:
|
blocked:
|
||||||
- v1.34.0
|
- v1.34.0
|
||||||
```
|
```
|
||||||
|
|
||||||
catalog also accepts URL or ConfigMap※
|
### `spec.version`
|
||||||
|
|
||||||
|
`spec.version` is the requested target version.
|
||||||
|
|
||||||
|
It may be either:
|
||||||
|
|
||||||
|
- an explicit version, such as `v1.35.3`
|
||||||
|
- `stable`, if the catalog defines a `stable` version
|
||||||
|
|
||||||
|
### `spec.nodeSelector`
|
||||||
|
|
||||||
|
`spec.nodeSelector` selects the nodes that should receive the upgrade.
|
||||||
|
|
||||||
|
An empty selector means all eligible managed nodes.
|
||||||
|
|
||||||
|
### `spec.catalog`
|
||||||
|
|
||||||
|
The catalog tells the agent where to find available OS images.
|
||||||
|
|
||||||
|
The catalog can be provided inline:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
catalog:
|
catalog:
|
||||||
URL: https://example.com/images.yaml
|
inline: |
|
||||||
|
stable: v1.35.1
|
||||||
catalog:
|
images:
|
||||||
ConfigMap: images-cm
|
- version: v1.35.1
|
||||||
|
url: https://example.invalid/images/monok8s-v1.35.1.img.zst
|
||||||
|
checksum: sha256:abc
|
||||||
|
size: 1858076672
|
||||||
```
|
```
|
||||||
|
|
||||||
※ ConfigMap requires additional RBAC permissions which is not enabled by default. You can edit
|
It can also be loaded from a URL:
|
||||||
the control-agent's ClusterRole and add `configmaps: get` to allow this.
|
|
||||||
|
```yaml
|
||||||
|
catalog:
|
||||||
|
url: https://example.com/images.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
Or from a ConfigMap:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
catalog:
|
||||||
|
configMap: images-cm
|
||||||
|
```
|
||||||
|
|
||||||
|
ConfigMap catalogs require extra RBAC. This permission is not enabled by default. To use a ConfigMap catalog, edit the relevant ClusterRole and allow `get` on `configmaps`.
|
||||||
|
|
||||||
|
Catalog content should look like this:
|
||||||
|
|
||||||
Contents should look like this
|
|
||||||
```yaml
|
```yaml
|
||||||
stable: v1.35.1
|
stable: v1.35.1
|
||||||
images:
|
images:
|
||||||
@@ -70,64 +142,114 @@ images:
|
|||||||
- version: v1.35.1
|
- version: v1.35.1
|
||||||
url: http://localhost:8000/rootfs.ext4.zst
|
url: http://localhost:8000/rootfs.ext4.zst
|
||||||
checksum: sha256:99af82a263deca44ad91d21d684f0fa944d5d0456a1da540f1c644f8aa59b14b
|
checksum: sha256:99af82a263deca44ad91d21d684f0fa944d5d0456a1da540f1c644f8aa59b14b
|
||||||
size: 1858076672 # expanded image size in bytes, use "zstd -lv image.zst to check"
|
size: 1858076672 # expanded image size in bytes; check with: zstd -lv image.zst
|
||||||
blocked:
|
blocked:
|
||||||
- v1.34.0
|
- v1.34.0
|
||||||
```
|
```
|
||||||
|
|
||||||
### Monitoring the upgrades
|
## Monitor upgrades
|
||||||
|
|
||||||
kubectl get osugrades
|
List upgrade requests:
|
||||||
```
|
|
||||||
NAME DESIRED RESOLVED PHASE TARGETS OK FAIL AGE
|
```bash
|
||||||
my-upgrade-3 stable v1.35.4 RollingOut 3 1 0 1m
|
kubectl get osupgrades
|
||||||
my-upgrade-2 v1.35.3 v1.35.3 Accepted 2 0 0 1m
|
|
||||||
my-downgrade-1 v1.33.2 v1.33.2 Rejected 2 0 2 1m
|
|
||||||
```
|
```
|
||||||
|
|
||||||
kubectl get osupgradeprogress
|
Example output:
|
||||||
|
|
||||||
|
```text
|
||||||
|
NAME DESIRED RESOLVED PHASE
|
||||||
|
my-upgrade-3 stable v1.35.4 Pending
|
||||||
|
my-upgrade-2 v1.35.3 v1.35.3 Accepted
|
||||||
|
my-downgrade-1 v1.33.2 v1.33.2 Rejected
|
||||||
```
|
```
|
||||||
|
|
||||||
|
List per-node progress:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get osupgradeprogresses
|
||||||
|
```
|
||||||
|
|
||||||
|
Example output:
|
||||||
|
|
||||||
|
```text
|
||||||
NAME NODE SOURCE CURRENT TARGET STATUS
|
NAME NODE SOURCE CURRENT TARGET STATUS
|
||||||
osupgrade-abc123f node-1 my-upgrade-2 v1.34.1 v1.35.3 downloading
|
osupgrade-abc123f node-1 my-upgrade-2 v1.34.1 v1.35.3 Downloading
|
||||||
osupgrade-cde456g node-2 my-upgrade-2 v1.35.3 v1.35.3 completed
|
osupgrade-cde456g node-2 my-upgrade-2 v1.35.3 v1.35.3 Completed
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Inspect one node's progress:
|
||||||
|
|
||||||
|
```bash
|
||||||
kubectl describe osupgradeprogress osupgrade-abc123f
|
kubectl describe osupgradeprogress osupgrade-abc123f
|
||||||
|
```
|
||||||
|
|
||||||
|
Example resource:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: monok8s.io/v1alpha1
|
apiVersion: monok8s.io/v1alpha1
|
||||||
kind: OSUpgradeProgress
|
kind: OSUpgradeProgress
|
||||||
metadata:
|
metadata:
|
||||||
name: "osupgrade-abc123f"
|
name: osupgrade-abc123f
|
||||||
spec:
|
spec:
|
||||||
sourceRef:
|
sourceRef:
|
||||||
name: my-upgrade-2
|
name: my-upgrade-2
|
||||||
nodeName: node-1
|
nodeName: node-1
|
||||||
status:
|
status:
|
||||||
currentVersion: "v1.34.1"
|
currentVersion: v1.34.1
|
||||||
targetVersion: "v1.35.3"
|
targetVersion: v1.35.3
|
||||||
phase: Downloading
|
phase: Downloading
|
||||||
startedAt: null
|
startedAt: null
|
||||||
completedAt: null
|
completedAt: null
|
||||||
lastUpdatedAt: null
|
lastUpdatedAt: null
|
||||||
retryCount: 0
|
retryCount: 0
|
||||||
inactivePartition: "B"
|
inactivePartition: B
|
||||||
failureReason: ""
|
failureReason: ""
|
||||||
message: ""
|
message: ""
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Retry a failed upgrade
|
||||||
|
|
||||||
|
If an upgrade fails, for example because the image download failed, edit `spec.retryNonce` on the affected `OSUpgradeProgress` resource.
|
||||||
|
|
||||||
|
Any changed value is enough. The field is only used to tell the node agent that the user intentionally requested a retry.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl patch osupgradeprogress osupgrade-abc123f \
|
||||||
|
--type merge \
|
||||||
|
-p '{"spec":{"retryNonce":"retry-1"}}'
|
||||||
|
```
|
||||||
|
|
||||||
|
If the same node fails again and you want to retry again, change the nonce to a new value:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl patch osupgradeprogress osupgrade-abc123f \
|
||||||
|
--type merge \
|
||||||
|
-p '{"spec":{"retryNonce":"retry-2"}}'
|
||||||
|
```
|
||||||
|
|
||||||
## Development notes
|
## Development notes
|
||||||
|
|
||||||
### Flashing manually into partition B
|
### Flash an image manually into partition B
|
||||||
|
|
||||||
**Use nmap ncat**. Otherwise we'll have all kinds of fabulous issues sending it.
|
Use nmap's `ncat`. Other tools may work, but they are more likely to cause annoying stream or connection behavior.
|
||||||
|
|
||||||
Sending side
|
On the sending machine:
|
||||||
```
|
|
||||||
pv "out/rootfs.ext4.zst" | ncat 10.0.0.10 1234 --send-only
|
```bash
|
||||||
|
pv out/rootfs.ext4.zst | ncat 10.0.0.10 1234 --send-only
|
||||||
```
|
```
|
||||||
|
|
||||||
Receiving side
|
On the receiving machine:
|
||||||
```
|
|
||||||
ncat -l 1234 --recv-only | zstd -d -c | dd of=/dev/sda3 bs=4M status=progress && sync && echo "SUCCESS"
|
```bash
|
||||||
|
ncat -l 1234 --recv-only | \
|
||||||
|
zstd -d -c | \
|
||||||
|
dd of=/dev/sda3 bs=4M status=progress && \
|
||||||
|
sync && \
|
||||||
|
echo "SUCCESS"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Be careful with the target partition. The example writes to `/dev/sda3`, which is assumed to be rootfs B in that setup. Verify the partition layout before running this on real hardware.
|
||||||
|
|||||||
@@ -20,11 +20,11 @@ run bootusb
|
|||||||
|
|
||||||
## Run fw_printenv and fw_setenv from kubectl
|
## Run fw_printenv and fw_setenv from kubectl
|
||||||
```
|
```
|
||||||
# Avoid using daemonset/control-agent if you have multiple nodes
|
# Avoid using daemonset/node-agent if you have multiple nodes
|
||||||
kubectl exec -n kube-system control-agent-abcdef1 -- /ctl internal fw-setenv --key foo --value bar
|
kubectl exec -n kube-system node-agent-abcdef1 -- /ctl internal fw-setenv --key foo --value bar
|
||||||
|
|
||||||
# fw_printenv
|
# fw_printenv
|
||||||
kubectl exec -n kube-system ds/control-agent -- /ctl internal fw-printenv --key foo
|
kubectl exec -n kube-system ds/node-agent -- /ctl internal fw-printenv --key foo
|
||||||
```
|
```
|
||||||
|
|
||||||
## Original uboot env from mono
|
## Original uboot env from mono
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
### User-configurable vars
|
### User-configurable vars
|
||||||
IMG_DIR="./out"
|
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
|
||||||
|
OUT_DIR="$( realpath "$SCRIPT_DIR"/../out/ )"
|
||||||
|
IMG_DIR="$OUT_DIR"
|
||||||
CONFIG_PART_SUFFIX="s1" # config partition after flashing
|
CONFIG_PART_SUFFIX="s1" # config partition after flashing
|
||||||
ENV_SEARCH_DIR="./out" # optional; leave empty to use selected image dir
|
ENV_SEARCH_DIR="./out" # optional; leave empty to use selected image dir
|
||||||
|
|
||||||
|
|||||||
2
makefile
2
makefile
@@ -38,7 +38,7 @@ PART_IMAGE := $(OUT_DIR)/monok8s-$(KUBE_VERSION)-$(TAG).ext4.zst
|
|||||||
KERNEL_IMAGE := $(OUT_DIR)/Image.gz
|
KERNEL_IMAGE := $(OUT_DIR)/Image.gz
|
||||||
|
|
||||||
BUILD_BASE_STAMP := $(OUT_DIR)/.build-base-$(TAG).stamp
|
BUILD_BASE_STAMP := $(OUT_DIR)/.build-base-$(TAG).stamp
|
||||||
DOWNLOAD_PACKAGES_STAMP := $(PACKAGES_DIR)/.download-packages.stamp
|
DOWNLOAD_PACKAGES_STAMP := $(PACKAGES_DIR)/.stamp-$(KUBE_VERSION)-$(CRIO_VERSION)
|
||||||
|
|
||||||
ALPINE_SERIES := $(word 1,$(subst ., ,$(ALPINE_VER))).$(word 2,$(subst ., ,$(ALPINE_VER)))
|
ALPINE_SERIES := $(word 1,$(subst ., ,$(ALPINE_VER))).$(word 2,$(subst ., ,$(ALPINE_VER)))
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user