fix: running container state - MCP - dependencies upgrade (#171)
Build Check / build (push) Has been cancelled
* feat: implement caching for handler creation across various resources * fix: remove reader ceiling with Reader.ReadString * feat: add operator icons * fix: init container pod running state * chore: dependencies upgrade * ci: build fix * fix: ci updates
@@ -41,6 +41,12 @@ jobs:
|
||||
- name: Configure git for private Go modules
|
||||
run: git config --global url."https://x-access-token:${{ secrets.GORELEASER_TOKEN }}@github.com/".insteadOf "https://github.com/"
|
||||
|
||||
- name: Free disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet || true
|
||||
sudo rm -rf /usr/local/lib/android || true
|
||||
df -h
|
||||
|
||||
- name: Run GoReleaser build
|
||||
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
|
||||
with:
|
||||
@@ -49,5 +55,8 @@ jobs:
|
||||
args: build --snapshot --clean --single-target
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
||||
GORELEASER_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
||||
KUBEWALL_GO_BUILD_TAGS: podexec
|
||||
CI_BUILD: true
|
||||
GOPRIVATE: github.com/kubewall/addons
|
||||
GONOSUMDB: github.com/kubewall/addons
|
||||
GONOSUMDB: github.com/kubewall/addons
|
||||
@@ -88,6 +88,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
||||
SNAPCRAFT_STORE_CREDENTIALS: ${{ secrets.SNAPCRAFT_LOGIN }}
|
||||
KUBEWALL_GO_BUILD_TAGS: podexec
|
||||
CI_BUILD: true
|
||||
GOPRIVATE: github.com/kubewall/addons
|
||||
GONOSUMDB: github.com/kubewall/addons
|
||||
|
||||
@@ -116,11 +117,17 @@ jobs:
|
||||
VERSION="${{ github.ref_name }}"
|
||||
VERSION_WITHOUT_V="${VERSION#v}"
|
||||
helm package charts/kubewall --version "$VERSION_WITHOUT_V" --app-version "$VERSION_WITHOUT_V"
|
||||
helm push "kubewall-${VERSION_WITHOUT_V}.tgz" oci://ghcr.io/kubewall/charts > .digest 2>&1
|
||||
helm push "kubewall-${VERSION_WITHOUT_V}.tgz" oci://ghcr.io/kubewall/charts 2>&1 | tee .digest
|
||||
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
|
||||
echo "helm push failed:"
|
||||
cat .digest
|
||||
exit 1
|
||||
fi
|
||||
cat .digest
|
||||
DIGEST=$(awk -F "[, ]+" '/Digest/{print $NF}' .digest)
|
||||
if [[ -z "$DIGEST" ]]; then
|
||||
echo "Failed to extract digest from helm push output"
|
||||
cat .digest
|
||||
exit 1
|
||||
fi
|
||||
echo "digest=${DIGEST}" >> $GITHUB_OUTPUT
|
||||
|
||||
@@ -3,11 +3,11 @@ version: 2
|
||||
|
||||
before:
|
||||
hooks:
|
||||
- sh -c "git config --global url.\"https://x-access-token:${GORELEASER_TOKEN}@github.com/\".insteadOf \"https://github.com/\""
|
||||
- sh -c "cd client && git clone https://github.com/kubewall/enterprise-client enterprise-client && node enterprise-client/scripts/generate-capabilities.js --config enterprise-client/configs/free.json && cd .."
|
||||
- sh -c "yarn --cwd client install && yarn --cwd client run build && rm -rf client/node_modules && rm -rf backend/routes/static && mv client/dist backend/routes/static"
|
||||
- sh -c "cd backend && go mod edit -dropreplace github.com/kubewall/addons && GOPRIVATE=github.com/kubewall/addons GONOSUMDB=github.com/kubewall/addons go mod tidy && cd .."
|
||||
|
||||
- sh -c "[ -z \"${GORELEASER_TOKEN}\" ] || [ \"${CI_BUILD}\" != \"true\" ] && exit 0; git config --global url.\"https://x-access-token:${GORELEASER_TOKEN}@github.com/\".insteadOf \"https://github.com/\""
|
||||
- sh -c "[ -z \"${GORELEASER_TOKEN}\" ] || [ \"${CI_BUILD}\" != \"true\" ] && exit 0; cd client && git clone https://github.com/kubewall/enterprise-client enterprise-client && node enterprise-client/scripts/generate-capabilities.js --config enterprise-client/configs/free.json && cd .."
|
||||
- sh -c "[ -z \"${GORELEASER_TOKEN}\" ] && exit 0; yarn --cwd client install && yarn --cwd client run build && rm -rf client/node_modules && rm -rf backend/routes/static && mv client/dist backend/routes/static"
|
||||
- sh -c "[ -z \"${GORELEASER_TOKEN}\" ] || [ \"${CI_BUILD}\" != \"true\" ] && exit 0; cd backend && go mod edit -dropreplace github.com/kubewall/addons && go mod edit -droprequire github.com/kubewall/addons && GOPRIVATE=github.com/kubewall/addons GONOSUMDB=github.com/kubewall/addons go get github.com/kubewall/addons/pod-exec@main && GOPRIVATE=github.com/kubewall/addons GONOSUMDB=github.com/kubewall/addons go mod tidy && cd .."
|
||||
|
||||
builds:
|
||||
- main: .
|
||||
dir: ./backend
|
||||
@@ -16,7 +16,7 @@ builds:
|
||||
goarch: ["386", "amd64", "arm64"]
|
||||
flags:
|
||||
- -trimpath
|
||||
- -tags=podexec
|
||||
- -tags={{ envOrDefault "KUBEWALL_GO_BUILD_TAGS" "" }}
|
||||
ldflags:
|
||||
- -s
|
||||
- -w
|
||||
|
||||
@@ -6,7 +6,8 @@ require (
|
||||
github.com/charmbracelet/log v1.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674
|
||||
github.com/labstack/echo/v4 v4.15.1
|
||||
github.com/kubewall/addons v0.0.0-00010101000000-000000000000
|
||||
github.com/labstack/echo/v4 v4.15.4
|
||||
github.com/mark3labs/mcp-go v0.38.0
|
||||
github.com/maruel/natural v1.3.0
|
||||
github.com/maypok86/otter/v2 v2.3.0
|
||||
@@ -16,19 +17,19 @@ require (
|
||||
github.com/r3labs/sse/v2 v2.10.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
k8s.io/api v0.35.4
|
||||
k8s.io/apiextensions-apiserver v0.35.4
|
||||
k8s.io/apimachinery v0.35.4
|
||||
k8s.io/client-go v0.35.4
|
||||
k8s.io/api v0.36.2
|
||||
k8s.io/apiextensions-apiserver v0.36.2
|
||||
k8s.io/apimachinery v0.36.2
|
||||
k8s.io/client-go v0.36.2
|
||||
k8s.io/klog/v2 v2.140.0
|
||||
k8s.io/metrics v0.35.4
|
||||
k8s.io/metrics v0.36.2
|
||||
sigs.k8s.io/yaml v1.6.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
github.com/buger/jsonparser v1.2.0 // indirect
|
||||
github.com/charmbracelet/colorprofile v0.4.3 // indirect
|
||||
github.com/charmbracelet/lipgloss v1.1.0 // indirect
|
||||
github.com/charmbracelet/x/ansi v0.11.7 // indirect
|
||||
@@ -36,72 +37,70 @@ require (
|
||||
github.com/charmbracelet/x/term v0.2.2 // indirect
|
||||
github.com/clipperhouse/displaywidth v0.11.0 // indirect
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.1 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.1 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.23.1 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.5 // indirect
|
||||
github.com/go-openapi/swag v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/cmdutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/conv v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/loading v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.26.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v1.0.0 // indirect
|
||||
github.com/go-openapi/jsonreference v1.0.0 // indirect
|
||||
github.com/go-openapi/swag v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/cmdutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/conv v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/loading v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/netutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.27.0 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.27.0 // indirect
|
||||
github.com/google/gnostic-models v0.7.1 // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/invopop/jsonschema v0.13.0 // indirect
|
||||
github.com/invopop/jsonschema v0.14.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/labstack/gommon v0.5.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.21 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.23 // indirect
|
||||
github.com/mattn/go-colorable v0.1.15 // indirect
|
||||
github.com/mattn/go-isatty v0.0.22 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.24 // indirect
|
||||
github.com/moby/spdystream v0.5.1 // 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/muesli/termenv v0.16.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/pb33f/ordered-map/v2 v2.3.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/spf13/pflag v1.0.10 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.50.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f // indirect
|
||||
golang.org/x/net v0.53.0 // indirect
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2 // indirect
|
||||
golang.org/x/crypto v0.54.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597 // indirect
|
||||
golang.org/x/net v0.57.0 // indirect
|
||||
golang.org/x/oauth2 v0.36.0 // indirect
|
||||
golang.org/x/sys v0.43.0 // indirect
|
||||
golang.org/x/term v0.42.0 // indirect
|
||||
golang.org/x/text v0.36.0 // indirect
|
||||
golang.org/x/sys v0.47.0 // indirect
|
||||
golang.org/x/term v0.45.0 // indirect
|
||||
golang.org/x/text v0.40.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.36.11 // indirect
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f // indirect
|
||||
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260706235625-cdb1db5517a0 // indirect
|
||||
k8s.io/streaming v0.36.2 // indirect
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 // indirect
|
||||
)
|
||||
|
||||
replace github.com/r3labs/sse/v2 => github.com/kubewall/sse/v2 v2.11.2
|
||||
|
||||
@@ -4,8 +4,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/buger/jsonparser v1.2.0 h1:4EFcvK1kD4jyj6YqNK6skK6w+y7FHHBR+XBCtxwu/6g=
|
||||
github.com/buger/jsonparser v1.2.0/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/charmbracelet/colorprofile v0.4.3 h1:QPa1IWkYI+AOB+fE+mg/5/4HRMZcaXex9t5KX76i20Q=
|
||||
github.com/charmbracelet/colorprofile v0.4.3/go.mod h1:/zT4BhpD5aGFpqQQqw7a+VtHCzu+zrQtt1zhMt9mR4Q=
|
||||
github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY=
|
||||
@@ -24,52 +24,51 @@ github.com/clipperhouse/uax29/v2 v2.7.0 h1:+gs4oBZ2gPfVrKPthwbMzWZDaAFPGYK72F0NJ
|
||||
github.com/clipperhouse/uax29/v2 v2.7.0/go.mod h1:EFJ2TJMRUaplDxHKj1qAEhCtQPW2tJSwu5BF98AuoVM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
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.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0 h1:C4Bl2xDndpU6nJ4bc1jXd+uTmYPVUwkD6bFY/oTyCes=
|
||||
github.com/emicklei/go-restful/v3 v3.13.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.1 h1:2rWm8B193Ll4VdjsJY28jxs70IdDsHRWgQYAI80+rMQ=
|
||||
github.com/fxamacker/cbor/v2 v2.9.1/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/fxamacker/cbor/v2 v2.9.2 h1:X4Ksno9+x3cz0TZv69ec1hxP/+tymuR8PXQJyDwfh78=
|
||||
github.com/fxamacker/cbor/v2 v2.9.2/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-logfmt/logfmt v0.6.1 h1:4hvbpePJKnIzH1B+8OR/JPbTx37NktoI9LE2QZBBkvE=
|
||||
github.com/go-logfmt/logfmt v0.6.1/go.mod h1:EV2pOAQoZaT1ZXZbqDl5hrymndi4SY9ED9/z6CO0XAk=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-openapi/jsonpointer v0.23.1 h1:1HBACs7XIwR2RcmItfdSFlALhGbe6S92p0ry4d1GWg4=
|
||||
github.com/go-openapi/jsonpointer v0.23.1/go.mod h1:iWRmZTrGn7XwYhtPt/fvdSFj1OfNBngqRT2UG3BxSqY=
|
||||
github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe+pJyVWRdiE=
|
||||
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
|
||||
github.com/go-openapi/swag v0.26.0 h1:GVDXCmfvhfu1BxiHo8/FA+BbKmhecHnG3varjON5/RI=
|
||||
github.com/go-openapi/swag v0.26.0/go.mod h1:82g3193sZJRbocs7bNCqGfIgq8pkuwVwCfhKIRlEQF0=
|
||||
github.com/go-openapi/swag/cmdutils v0.26.0 h1:iowihOcvq7y4egO8cOq0dmfohz6wfeQ63U1EnuhO2TU=
|
||||
github.com/go-openapi/swag/cmdutils v0.26.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM=
|
||||
github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I=
|
||||
github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE=
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU=
|
||||
github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc=
|
||||
github.com/go-openapi/swag/jsonname v0.26.0 h1:gV1NFX9M8avo0YSpmWogqfQISigCmpaiNci8cGECU5w=
|
||||
github.com/go-openapi/swag/jsonname v0.26.0/go.mod h1:urBBR8bZNoDYGr653ynhIx+gTeIz0ARZxHkAPktJK2M=
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA=
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y=
|
||||
github.com/go-openapi/swag/loading v0.26.0 h1:Apg6zaKhCJurpJer0DCxq99qwmhFddBhaMX7kilDcko=
|
||||
github.com/go-openapi/swag/loading v0.26.0/go.mod h1:dBxQ/6V2uBaAQdevN18VELE6xSpJWZxLX4txe12JwDg=
|
||||
github.com/go-openapi/swag/mangling v0.26.0 h1:Du2YC4YLA/Y5m/YKQd7AnY5qq0wRKSFZTTt8ktFaXcQ=
|
||||
github.com/go-openapi/swag/mangling v0.26.0/go.mod h1:jifS7W9vbg+pw63bT+GI53otluMQL3CeemuyCHKwVx0=
|
||||
github.com/go-openapi/swag/netutils v0.26.0 h1:CmZp+ZT7HrmFwrC3GdGsXBq2+42T1bjKBapcqVpIs3c=
|
||||
github.com/go-openapi/swag/netutils v0.26.0/go.mod h1:5iK+Ok3ZohWWex1C50BFTPexi03UaPwjW4Oj8kgrpwo=
|
||||
github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg=
|
||||
github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE=
|
||||
github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4=
|
||||
github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE=
|
||||
github.com/go-openapi/swag/yamlutils v0.26.0 h1:H7O8l/8NJJQ/oiReEN+oMpnGMyt8G0hl460nRZxhLMQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.26.0/go.mod h1:1evKEGAtP37Pkwcc7EWMF0hedX0/x3Rkvei2wtG/TbU=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE=
|
||||
github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4=
|
||||
github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/jsonpointer v1.0.0 h1:kR9tHqY0CtZaOPVFm622dPVNhrvYpwr4uCxgL3h1H8s=
|
||||
github.com/go-openapi/jsonpointer v1.0.0/go.mod h1:Z3rw7dWu1p9IgitXCFamSlA5lmDiklEB6vkaxcNZW5Y=
|
||||
github.com/go-openapi/jsonreference v1.0.0 h1:jlmTr6torcd1YgDQvSfNmRtKzYDO4FGBkrAdlAVWnpY=
|
||||
github.com/go-openapi/jsonreference v1.0.0/go.mod h1:jtwdyGbJk0Xhe5Y+rwtglQP6Sb1WZST4rT32LWB+sv0=
|
||||
github.com/go-openapi/swag v0.27.0 h1:8ecSuZlh4NXc3GsmAOqECIYqDTApCWaMe3gO4gjJNEE=
|
||||
github.com/go-openapi/swag v0.27.0/go.mod h1:Kkgz9Ht0+ul9/aVdFmc9xSyPzUwf/aFF5KiFPBXfSY0=
|
||||
github.com/go-openapi/swag/cmdutils v0.27.0 h1:aIKiqhB29AaP+7xm8/CPg3uOpeHx2SUp6TvMpu/a31Y=
|
||||
github.com/go-openapi/swag/cmdutils v0.27.0/go.mod h1:Sm1MVFMkF6guJJ+pQqHnQA3N0j9qALV3NxzDSv6bETM=
|
||||
github.com/go-openapi/swag/conv v0.27.0 h1:EKOH4feXrvdo8DbSsXSAqRT8fz1epEnS5O2IfXUOzE8=
|
||||
github.com/go-openapi/swag/conv v0.27.0/go.mod h1:pfiv0uKQTbaGApk8Zs/lZV3uSjmSpa2FO1y183YngN8=
|
||||
github.com/go-openapi/swag/fileutils v0.27.0 h1:ib5jMUqGq5tY1EyO4inlrabsaeDAleFU+XD1FXQcgp8=
|
||||
github.com/go-openapi/swag/fileutils v0.27.0/go.mod h1:VvJFZLTZS0AI854gEQz5tk7dBESdLjiNUMSZ/th2ry8=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.0 h1:VYtd9jEQYeU4j8q5vdn5KWotF4vKywhGdMBrALtAsfE=
|
||||
github.com/go-openapi/swag/jsonutils v0.27.0/go.mod h1:U7pb8AGuwhok3RDicHeHwSG4L3PXSq6PAL98Aon632g=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0 h1:+d7C7Ur/SsGg/UZ9G0JEovnfRqtMNZCJQGKc2h/ojoE=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.27.0/go.mod h1:mofwUWx70wvskwESqRJ//k/9kURmCgyJl5m5Ppoh5kY=
|
||||
github.com/go-openapi/swag/loading v0.27.0 h1:s8DA9aPEdFH6OluHUYUn3DnIuoTdyWs9RwffXBUfyeI=
|
||||
github.com/go-openapi/swag/loading v0.27.0/go.mod h1:VOz+Jg6UGGywcmRvYsI4fvtp+bd7NfioseGEPleYdA4=
|
||||
github.com/go-openapi/swag/mangling v0.27.0 h1:rpPJuqQHa6z2pDiP3iIpXOyNXlSs9cQCxnJSAxzdfOc=
|
||||
github.com/go-openapi/swag/mangling v0.27.0/go.mod h1:jtBE2+V+3pILxOR7Vgce+Cwp6A2PgZbvVqfNntbVs0w=
|
||||
github.com/go-openapi/swag/netutils v0.27.0 h1:lEUG+hHvPvLggB3A8snFk0IRKNf9uC0YKc+7WYqvAF8=
|
||||
github.com/go-openapi/swag/netutils v0.27.0/go.mod h1:J+WYyFMLtvtCGqa6jLv+YNUmIKI3ZRQRrvfNDMoQoEQ=
|
||||
github.com/go-openapi/swag/stringutils v0.27.0 h1:Of7w/HljWsNZvuxsUAnw3n+hCOyI6HLJOxW2kQRAxio=
|
||||
github.com/go-openapi/swag/stringutils v0.27.0/go.mod h1:lzRN95CxXmA03XcDWHLOb6nOMcxCqR5rGY0lOgsfRoM=
|
||||
github.com/go-openapi/swag/typeutils v0.27.0 h1:aCf4MSGo8NLwZP8Q6t32DWLJSvl/WwNqgmEG+xJ6v2o=
|
||||
github.com/go-openapi/swag/typeutils v0.27.0/go.mod h1:Srm0xFNRZ1Y+vCxJclo5qzx8aj+1pAKda/YfFPrG0dQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.0 h1:bQ6eAMil5X9tdcf7dMn4t15alzG6jddnrKPuKa/zxKM=
|
||||
github.com/go-openapi/swag/yamlutils v0.27.0/go.mod h1:yRfIo7qqVkmJRQjX8exjA3AfcI8rH1KDNPsTparoCv4=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0 h1:gGHwAJ0R/5jU8BEGDbfRNR3hL68dAVi84WuOApp29B0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.6.0/go.mod h1:tY+St1SGq4NFl0QIqdTY4aEdbChAHxhyB77XQi9iJCo=
|
||||
github.com/go-openapi/testify/v2 v2.6.0 h1:5PKH2HE7YJ/LuRPQGvSxBRlFXNQhSetBLlGAgUEu3ug=
|
||||
github.com/go-openapi/testify/v2 v2.6.0/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/google/gnostic-models v0.7.1 h1:SisTfuFKJSKM5CPZkffwi6coztzzeYUhc3v4yxLWH8c=
|
||||
github.com/google/gnostic-models v0.7.1/go.mod h1:whL5G0m6dmc5cPxKc5bdKdEN3UjI7OUGxBlw57miDrQ=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
@@ -81,37 +80,32 @@ github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674 h1:JeSE6pjso5T
|
||||
github.com/gorilla/websocket v1.5.4-0.20250319132907-e064f32e3674/go.mod h1:r4w70xmWCQKmi1ONH4KIaBptdivuRPyosB9RmPlGEwA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/invopop/jsonschema v0.14.0 h1:MHQqLhvpNUZfw+hM3AZDYK7jxO8FZoQeQM77g8iyZjg=
|
||||
github.com/invopop/jsonschema v0.14.0/go.mod h1:ygm6C2EaVNMBDPpaPlnOA2pFAxBnxGjFlMZABxm9n2I=
|
||||
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/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kubewall/addons v0.0.0-20260514064515-c6b78727d65d h1:PXzyovYABSsIRF+fByOnz485GeM76s/kwOqmmI+khXI=
|
||||
github.com/kubewall/addons v0.0.0-20260514064515-c6b78727d65d/go.mod h1:PUnYo79Hj0hK+UH9VjeDbSgsdLJ/INnirAAFBo4LmT4=
|
||||
github.com/kubewall/sse/v2 v2.11.2 h1:SbMgQV9iv4StvxwR2gR5v5W1+tuQEN9A/t357A81FbE=
|
||||
github.com/kubewall/sse/v2 v2.11.2/go.mod h1:SpOGASIFpMNmO6quaVUTvXfZ9AXrbHfaOb6ehuk+n5g=
|
||||
github.com/labstack/echo/v4 v4.15.1 h1:S9keusg26gZpjMmPqB5hOEvNKnmd1lNmcHrbbH2lnFs=
|
||||
github.com/labstack/echo/v4 v4.15.1/go.mod h1:xmw1clThob0BSVRX1CRQkGQ/vjwcpOMjQZSZa9fKA/c=
|
||||
github.com/labstack/echo/v4 v4.15.4 h1:DL45vVYa+BWE+XuW+zZNd9H0YEdZ80UAWJGcTVW4EVs=
|
||||
github.com/labstack/echo/v4 v4.15.4/go.mod h1:CuMetKIRwsuO/qlAgMq+KTAalwGoB/h4tC+yPdrTj1g=
|
||||
github.com/labstack/gommon v0.5.0 h1:6VSQ2NOzsnEJ5W6+84E0RbcaDDmgB6NIAzWCczTEe6c=
|
||||
github.com/labstack/gommon v0.5.0/go.mod h1:Rzlg7HHy1maLfzBYGg9NZcVuz1sA68HHhLjhcEllYE0=
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0 h1:UtrWVfLdarDgc44HcS7pYloGHJUjHV/4FwW4TvVgFr4=
|
||||
github.com/lucasb-eyer/go-colorful v1.4.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mark3labs/mcp-go v0.38.0 h1:E5tmJiIXkhwlV0pLAwAT0O5ZjUZSISE/2Jxg+6vpq4I=
|
||||
github.com/mark3labs/mcp-go v0.38.0/go.mod h1:T7tUa2jO6MavG+3P25Oy/jR7iCeJPHImCZHRymCn39g=
|
||||
github.com/maruel/natural v1.3.0 h1:VsmCsBmEyrR46RomtgHs5hbKADGRVtliHTyCOLFBpsg=
|
||||
github.com/maruel/natural v1.3.0/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.21 h1:xYae+lCNBP7QuW4PUnNG61ffM4hVIfm+zUzDuSzYLGs=
|
||||
github.com/mattn/go-isatty v0.0.21/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-runewidth v0.0.23 h1:7ykA0T0jkPpzSvMS5i9uoNn2Xy3R383f9HDx3RybWcw=
|
||||
github.com/mattn/go-runewidth v0.0.23/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
|
||||
github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
|
||||
github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
|
||||
github.com/mattn/go-runewidth v0.0.24 h1:cpokDiIn0MGnhdHwuWnJBITySJ20QyNGnY2kR/ay2DU=
|
||||
github.com/mattn/go-runewidth v0.0.24/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
|
||||
github.com/maypok86/otter/v2 v2.3.0 h1:8H8AVVFUSzJwIegKwv1uF5aGitTY+AIrtktg7OcLs8w=
|
||||
github.com/maypok86/otter/v2 v2.3.0/go.mod h1:XgIdlpmL6jYz882/CAx1E4C1ukfgDKSaw4mWq59+7l8=
|
||||
github.com/moby/spdystream v0.5.1 h1:9sNYeYZUcci9R6/w7KDaFWEWeV4LStVG78Mpyq/Zm/Y=
|
||||
@@ -126,14 +120,15 @@ github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc
|
||||
github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk=
|
||||
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/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/pb33f/ordered-map/v2 v2.3.1 h1:5319HDO0aw4DA4gzi+zv4FXU9UlSs3xGZ40wcP1nBjY=
|
||||
github.com/pb33f/ordered-map/v2 v2.3.1/go.mod h1:qxFQgd0PkVUtOMCkTapqotNgzRhMPL7VvaHKbd1HnmQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pytimer/k8sutil v0.0.0-20221114090626-86d6279d8e52 h1:h8HfcvAcMpqcFUbM0+lTJ9jA7SJuaKf+DCqRcuRFWXE=
|
||||
github.com/pytimer/k8sutil v0.0.0-20221114090626-86d6279d8e52/go.mod h1:j/rKDw4hviPgRAnp90skEx/bX2s6t83vlJKC4UMqT6k=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
@@ -158,8 +153,6 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/fJgbpc=
|
||||
github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw=
|
||||
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/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
@@ -172,25 +165,27 @@ go.yaml.in/yaml/v2 v2.4.4 h1:tuyd0P+2Ont/d6e2rl3be67goVK4R6deVxCUX5vyPaQ=
|
||||
go.yaml.in/yaml/v2 v2.4.4/go.mod h1:gMZqIpDtDqOfM0uNfy0SkpRhvUryYH0Z6wdMYcacYXQ=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI=
|
||||
golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f h1:W3F4c+6OLc6H2lb//N1q4WpJkhzJCK5J6kUi1NTVXfM=
|
||||
golang.org/x/exp v0.0.0-20260410095643-746e56fc9e2f/go.mod h1:J1xhfL/vlindoeF/aINzNzt2Bket5bjo9sdOYzOsU80=
|
||||
golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA=
|
||||
golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2 h1:/FrI8D64VSr4HtGIlUtlFMGsm7H7pWTbj6vOLVZcA6s=
|
||||
go.yaml.in/yaml/v4 v4.0.0-rc.2/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0=
|
||||
golang.org/x/crypto v0.54.0 h1:YLIA59K4fiNzHzjnZt2tUJQjQtUWfWbeHBqKtk3eScw=
|
||||
golang.org/x/crypto v0.54.0/go.mod h1:KWL8ny2AZdGR2cWmzeHrp2azQPGogOv+HeQaVEXC2dk=
|
||||
golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597 h1:qLvzZeaANDgyVOA8pyHCOStGlXn0rseXma+GQjeuv2g=
|
||||
golang.org/x/exp v0.0.0-20260709172345-9ea1abe57597/go.mod h1:EdfpwwqSu+0Li0mzskwHU6FWDV3t9Q+RZDo3QMUtL3Q=
|
||||
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
|
||||
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
|
||||
golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.42.0 h1:UiKe+zDFmJobeJ5ggPwOshJIVt6/Ft0rcfrXZDLWAWY=
|
||||
golang.org/x/term v0.42.0/go.mod h1:Dq/D+snpsbazcBG5+F9Q1n2rXV8Ma+71xEjTRufARgY=
|
||||
golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
|
||||
golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
|
||||
golang.org/x/sys v0.47.0 h1:o7XGOvZQCADBQQ4Y7VNq2dRWQR7JmOUW8Kxx4ZsNgWs=
|
||||
golang.org/x/sys v0.47.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.45.0 h1:NwWyBmoJCbfTHpxrWoZ9C6/VxOf7ic219I8xZZFdrf0=
|
||||
golang.org/x/term v0.45.0/go.mod h1:9aqxs0blBcrm/n0L9QW0aRVD+ktan8ssZromtqJC43w=
|
||||
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
|
||||
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
|
||||
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -202,27 +197,29 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.35.4 h1:P7nFYKl5vo9AGUp1Z+Pmd3p2tA7bX2wbFWCvDeRv988=
|
||||
k8s.io/api v0.35.4/go.mod h1:yl4lqySWOgYJJf9RERXKUwE9g2y+CkuwG+xmcOK8wXU=
|
||||
k8s.io/apiextensions-apiserver v0.35.4 h1:HeP+Upp7ItdvnyGmub0yoix+2z5+ev4M5cE5TCgtOUU=
|
||||
k8s.io/apiextensions-apiserver v0.35.4/go.mod h1:ogQlk+stIE8mnoRthSYCwlOS12fVqgWFiErMwPaXA7c=
|
||||
k8s.io/apimachinery v0.35.4 h1:xtdom9RG7e+yDp71uoXoJDWEE2eOiHgeO4GdBzwWpds=
|
||||
k8s.io/apimachinery v0.35.4/go.mod h1:NNi1taPOpep0jOj+oRha3mBJPqvi0hGdaV8TCqGQ+cc=
|
||||
k8s.io/client-go v0.35.4 h1:DN6fyaGuzK64UvnKO5fOA6ymSjvfGAnCAHAR0C66kD8=
|
||||
k8s.io/client-go v0.35.4/go.mod h1:2Pg9WpsS4NeOpoYTfHHfMxBG8zFMSAUi4O/qoiJC3nY=
|
||||
k8s.io/api v0.36.2 h1:TF6YDLIzKfccK7cq9YpTcGX8TJmEkHVRv78DM51fRYY=
|
||||
k8s.io/api v0.36.2/go.mod h1:F4LbMO4brjZYh7yFkXWhynSvtB7YauxV4c+HHkNRGNg=
|
||||
k8s.io/apiextensions-apiserver v0.36.2 h1:3O5gqOj/dt2XWWbpMe+TXWpE9yU6pjM/tXxtHHJT/K4=
|
||||
k8s.io/apiextensions-apiserver v0.36.2/go.mod h1:cL1tBWe8XSaP1H30iWKGo7hf6iAUUUJPEU70dskmAnA=
|
||||
k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
|
||||
k8s.io/apimachinery v0.36.2/go.mod h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
|
||||
k8s.io/client-go v0.36.2 h1:bfgxmFKc9CgqsgX4xKLAAdmTQlWee7Ob/HlDOrJ5TBI=
|
||||
k8s.io/client-go v0.36.2/go.mod h1:1vgO4OAlfPnoLcb+Rze2GF5rAr14w8qjrYMoyXJzQj0=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f h1:4Qiq0YAoQATdgmHALJWz9rJ4fj20pB3xebpB4CFNhYM=
|
||||
k8s.io/kube-openapi v0.0.0-20260414162039-ec9c827d403f/go.mod h1:uGBT7iTA6c6MvqUvSXIaYZo9ukscABYi2btjhvgKGZ0=
|
||||
k8s.io/metrics v0.35.4 h1:KFo3xFe5rzLDarHLNjZB0J1g1c5fvl6A5Kk/8KzIwOA=
|
||||
k8s.io/metrics v0.35.4/go.mod h1:5DO36o9esGC1VXylSpqJWmwhoopS/erADQcACz1tN3s=
|
||||
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5 h1:kBawHLSnx/mYHmRnNUf9d4CpjREbeZuxoSGOX/J+aYM=
|
||||
k8s.io/utils v0.0.0-20260319190234-28399d86e0b5/go.mod h1:xDxuJ0whA3d0I4mf/C4ppKHxXynQ+fxnkmQH0vTHnuk=
|
||||
k8s.io/kube-openapi v0.0.0-20260706235625-cdb1db5517a0 h1:CVjOUCTXINUThEmDs25FNSna0+vnGSoTleN+wiJu6hE=
|
||||
k8s.io/kube-openapi v0.0.0-20260706235625-cdb1db5517a0/go.mod h1:rcZ+P5cEvHQB+m154WBOatIGBgOEPjzmLkXjkHfg3ms=
|
||||
k8s.io/metrics v0.36.2 h1:yfUIe2Vwx2cQAIpVYcin1JXdabrRz98oTxP2HJTxHj8=
|
||||
k8s.io/metrics v0.36.2/go.mod h1:Q/dNyLLzgSxPu0/e+996Du4pjutfEyyHOKgK0lkncp0=
|
||||
k8s.io/streaming v0.36.2 h1:NSKthPPg9UFSKsRauVJUVGH2Dvn8fhKmY4qrMkw/p98=
|
||||
k8s.io/streaming v0.36.2/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM=
|
||||
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/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0 h1:qmp2e3ZfFi1/jJbDGpD4mt3wyp6PE1NfKHCYLqgNQJo=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.0/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2 h1:qdOxHwrl2Kaag1aQEarlYcOA9vSyGCp3CIki3aW8c4Q=
|
||||
sigs.k8s.io/structured-merge-diff/v6 v6.4.2/go.mod h1:M3W8sfWvn2HhQDIbGWj3S099YozAsymCo/wrT5ohRUE=
|
||||
sigs.k8s.io/yaml v1.6.0 h1:G8fkbMSAFqgEFgh4b1wmtzDnioxFCUgTZhlbj5P9QYs=
|
||||
sigs.k8s.io/yaml v1.6.0/go.mod h1:796bPqUfzR/0jLAl6XjHl3Ck7MiyVv8dbTdyT3/pMf4=
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewClusterRoleRouteHandler(container container.Container, routeType base.Ro
|
||||
}
|
||||
|
||||
func NewRolesHandler(ctx context.Context, config, cluster string, container container.Container) *RolesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/accesscontrol/clusterroles.NewRolesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *RolesHandler {
|
||||
return newRolesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newRolesHandler(ctx context.Context, config, cluster string, container container.Container) *RolesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Rbac().V1().ClusterRoles().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewClusterRoleBindingsRouteHandler(container container.Container, routeType
|
||||
}
|
||||
|
||||
func NewClusterRoleBindingHandler(ctx context.Context, config, cluster string, container container.Container) *ClusterRoleBindingHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/accesscontrol/clusterrolesbindings.NewClusterRoleBindingHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ClusterRoleBindingHandler {
|
||||
return newClusterRoleBindingHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newClusterRoleBindingHandler(ctx context.Context, config, cluster string, container container.Container) *ClusterRoleBindingHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Rbac().V1().ClusterRoleBindings().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewRoleRouteHandler(container container.Container, routeType base.RouteType
|
||||
}
|
||||
|
||||
func NewRolesHandler(ctx context.Context, config, cluster string, container container.Container) *RolesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/accesscontrol/roles.NewRolesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *RolesHandler {
|
||||
return newRolesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newRolesHandler(ctx context.Context, config, cluster string, container container.Container) *RolesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Rbac().V1().Roles().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewRoleBindingsRouteHandler(container container.Container, routeType base.R
|
||||
}
|
||||
|
||||
func NewRoleBindingHandler(ctx context.Context, config, cluster string, container container.Container) *RoleBindingHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/accesscontrol/rolesbindings.NewRoleBindingHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *RoleBindingHandler {
|
||||
return newRoleBindingHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newRoleBindingHandler(ctx context.Context, config, cluster string, container container.Container) *RoleBindingHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Rbac().V1().RoleBindings().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewServiceAccountsRouteHandler(container container.Container, routeType bas
|
||||
}
|
||||
|
||||
func NewServiceAccountsHandler(ctx context.Context, config, cluster string, container container.Container) *ServiceAccountsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/accesscontrol/serviceaccounts.NewServiceAccountsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ServiceAccountsHandler {
|
||||
return newServiceAccountsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newServiceAccountsHandler(ctx context.Context, config, cluster string, container container.Container) *ServiceAccountsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().ServiceAccounts().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -38,6 +38,9 @@ type BaseHandler struct {
|
||||
|
||||
func (h *BaseHandler) GetList(c echo.Context) error {
|
||||
streamID := fmt.Sprintf("%s-%s-%s", h.QueryConfig, h.QueryCluster, h.Kind)
|
||||
// Handlers are cached across requests, so publish the current list for
|
||||
// this new subscriber instead of relying on construction-time sync.
|
||||
h.Container.EventProcessor().AddEvent(streamID, h.processListEvents(""))
|
||||
h.Container.SSE().ServeHTTP(streamID, c.Response(), c.Request())
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ func ResourceEventHandler[T Resource](handler *BaseHandler, additionalEvents ...
|
||||
return
|
||||
}
|
||||
// GetList
|
||||
go handler.Container.EventProcessor().AddEvent(handler.Kind, handler.processListEvents(resource.GetName()))
|
||||
handler.Container.EventProcessor().AddEvent(handler.Kind, handler.processListEvents(resource.GetName()))
|
||||
|
||||
var streamName string
|
||||
if resource.GetNamespace() == "" {
|
||||
@@ -35,14 +35,14 @@ func ResourceEventHandler[T Resource](handler *BaseHandler, additionalEvents ...
|
||||
streamName = fmt.Sprintf("%s-%s-%s-%s-%s", handler.QueryConfig, handler.QueryCluster, handler.Kind, resource.GetNamespace(), resource.GetName())
|
||||
}
|
||||
// GetDetails
|
||||
go handler.Container.EventProcessor().AddEvent(streamName, handler.processDetailsEvents(handler.Kind, resource.GetNamespace(), resource.GetName()))
|
||||
handler.Container.EventProcessor().AddEvent(streamName, handler.processDetailsEvents(handler.Kind, resource.GetNamespace(), resource.GetName()))
|
||||
|
||||
// GetYAML
|
||||
go handler.Container.EventProcessor().AddEvent(streamName+"-yaml", handler.processYAMLEvents(handler.Kind, resource.GetNamespace(), resource.GetName()))
|
||||
handler.Container.EventProcessor().AddEvent(streamName+"-yaml", handler.processYAMLEvents(handler.Kind, resource.GetNamespace(), resource.GetName()))
|
||||
|
||||
for _, event := range additionalEvents {
|
||||
for key, e := range event {
|
||||
go handler.Container.EventProcessor().AddEvent(key, e)
|
||||
handler.Container.EventProcessor().AddEvent(key, e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package base
|
||||
|
||||
import "sync"
|
||||
|
||||
// handlerRegistry caches handler instances per (config, cluster) so each HTTP
|
||||
// request reuses the wrapper around the shared informer instead of rebuilding
|
||||
// it (and re-running WaitForSync) on every call.
|
||||
var handlerRegistry sync.Map
|
||||
|
||||
// GetOrCreateHandler returns the cached handler for key, constructing it via
|
||||
// create on first use. Concurrent first calls may both run create; only one
|
||||
// instance is stored and returned, which is safe because informer event
|
||||
// handler registration is guarded separately by informerInitOnce.
|
||||
func GetOrCreateHandler[T any](key string, create func() T) T {
|
||||
if v, ok := handlerRegistry.Load(key); ok {
|
||||
return v.(T)
|
||||
}
|
||||
v, _ := handlerRegistry.LoadOrStore(key, create())
|
||||
return v.(T)
|
||||
}
|
||||
@@ -39,6 +39,13 @@ func NewConfigMapsRouteHandler(container container.Container, routeType base.Rou
|
||||
}
|
||||
|
||||
func NewConfigMapsHandler(ctx context.Context, config, cluster string, container container.Container) *ConfigMapsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/configMaps.NewConfigMapsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ConfigMapsHandler {
|
||||
return newConfigMapsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newConfigMapsHandler(ctx context.Context, config, cluster string, container container.Container) *ConfigMapsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().ConfigMaps().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewHorizontalPodAutoscalersRouteHandler(container container.Container, rout
|
||||
}
|
||||
|
||||
func NewHorizontalPodAutoScalerHandler(ctx context.Context, config, cluster string, container container.Container) *HorizontalPodAutoScalerHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/horizontalPodAutoscalers.NewHorizontalPodAutoScalerHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *HorizontalPodAutoScalerHandler {
|
||||
return newHorizontalPodAutoScalerHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newHorizontalPodAutoScalerHandler(ctx context.Context, config, cluster string, container container.Container) *HorizontalPodAutoScalerHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Autoscaling().V2().HorizontalPodAutoscalers().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewLeaseRouteHandler(container container.Container, routeType base.RouteTyp
|
||||
}
|
||||
|
||||
func NewLeasesHandler(ctx context.Context, config, cluster string, container container.Container) *LeasesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/leases.NewLeasesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *LeasesHandler {
|
||||
return newLeasesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newLeasesHandler(ctx context.Context, config, cluster string, container container.Container) *LeasesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Coordination().V1().Leases().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewLimitRangesRouteHandler(container container.Container, routeType base.Ro
|
||||
}
|
||||
|
||||
func NewLimitRangesHandler(ctx context.Context, config, cluster string, container container.Container) *LimitRangesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/limitRanges.NewLimitRangesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *LimitRangesHandler {
|
||||
return newLimitRangesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newLimitRangesHandler(ctx context.Context, config, cluster string, container container.Container) *LimitRangesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().LimitRanges().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewPodDisruptionBudgetRouteHandler(container container.Container, routeType
|
||||
}
|
||||
|
||||
func NewPodDisruptionBudgetHandler(ctx context.Context, config, cluster string, container container.Container) *PodDisruptionBudgetHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/podDisruptionBudgets.NewPodDisruptionBudgetHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *PodDisruptionBudgetHandler {
|
||||
return newPodDisruptionBudgetHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newPodDisruptionBudgetHandler(ctx context.Context, config, cluster string, container container.Container) *PodDisruptionBudgetHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Policy().V1().PodDisruptionBudgets().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewPriorityClassRouteHandler(container container.Container, routeType base.
|
||||
}
|
||||
|
||||
func NewPriorityClassHandler(ctx context.Context, config, cluster string, container container.Container) *PriorityClassesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/priorityClasses.NewPriorityClassHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *PriorityClassesHandler {
|
||||
return newPriorityClassHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newPriorityClassHandler(ctx context.Context, config, cluster string, container container.Container) *PriorityClassesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Scheduling().V1().PriorityClasses().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewResourceQuotaRouteHandler(container container.Container, routeType base.
|
||||
}
|
||||
|
||||
func NewResourceQuotaHandler(ctx context.Context, config, cluster string, container container.Container) *ResourceQuotaHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/resourceQuotas.NewResourceQuotaHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ResourceQuotaHandler {
|
||||
return newResourceQuotaHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newResourceQuotaHandler(ctx context.Context, config, cluster string, container container.Container) *ResourceQuotaHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().ResourceQuotas().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewRunTimeClassRouteHandler(container container.Container, routeType base.R
|
||||
}
|
||||
|
||||
func NewRunTimeClassHandler(ctx context.Context, config, cluster string, container container.Container) *RunTimeClassesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/runtimeClasses.NewRunTimeClassHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *RunTimeClassesHandler {
|
||||
return newRunTimeClassHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newRunTimeClassHandler(ctx context.Context, config, cluster string, container container.Container) *RunTimeClassesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Node().V1().RuntimeClasses().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewSecretsRouteHandler(container container.Container, routeType base.RouteT
|
||||
}
|
||||
|
||||
func NewSecretsHandler(ctx context.Context, config, cluster string, container container.Container) *SecretsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/config/secrets.NewSecretsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *SecretsHandler {
|
||||
return newSecretsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newSecretsHandler(ctx context.Context, config, cluster string, container container.Container) *SecretsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Secrets().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewCRDRouteHandler(container container.Container, routeType base.RouteType)
|
||||
}
|
||||
|
||||
func NewCRDHandler(ctx context.Context, config, cluster string, container container.Container) *CRDHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/crds/crds.NewCRDHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *CRDHandler {
|
||||
return newCRDHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newCRDHandler(ctx context.Context, config, cluster string, container container.Container) *CRDHandler {
|
||||
informer := container.ExtensionSharedFactoryInformer(config, cluster).Apiextensions().V1().CustomResourceDefinitions().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -6,88 +6,104 @@ import (
|
||||
)
|
||||
|
||||
var iconsList = map[string][]string{
|
||||
"aiven.io": {"aiven.io"},
|
||||
"amazonaws.com": {"amazonaws.com"},
|
||||
"ansible.com": {"ansible.com"},
|
||||
"apache.org": {"apache.org"},
|
||||
"argoproj.io": {"argoproj.io"},
|
||||
"banzaicloud.com": {"banzaicloud.com"},
|
||||
"bitnami.com": {"bitnami.com"},
|
||||
"cert-manager.io": {"cert-manager.io"},
|
||||
"cilium.io": {"cilium.io"},
|
||||
"cloudflare-operator.io": {"cloudflare-operator.io"},
|
||||
"cloudflare.com": {"cloudflare.com"},
|
||||
"cncf.io": {"cncf.io"},
|
||||
"confluent.io": {"confluent.io"},
|
||||
"coreos.com": {"coreos.com"},
|
||||
"crossplane.io": {"crossplane.io"},
|
||||
"dapr.io": {"dapr.io"},
|
||||
"datadoghq.com": {"datadoghq.com"},
|
||||
"doppler.com": {"doppler.com"},
|
||||
"dragonflydb.io": {"dragonflydb.io"},
|
||||
"dynatrace.com": {"dynatrace.com"},
|
||||
"elastic.co": {"elastic.co"},
|
||||
"emqx.io": {"emqx.io"},
|
||||
"envoyproxy.io": {"envoyproxy.io"},
|
||||
"external-secrets.io": {"external-secrets.io"},
|
||||
"f5.com": {"f5.com"},
|
||||
"flagger.app": {"flagger.app"},
|
||||
"fluent.io": {"fluent.io"},
|
||||
"fluxcd.io": {"fluxcd.io"},
|
||||
"getambassador.io": {"getambassador.io"},
|
||||
"github.com": {"github.com"},
|
||||
"github.io": {"github.io"},
|
||||
"gitlab.com": {"gitlab.com"},
|
||||
"gke.io": {"gke.io"},
|
||||
"google.com": {"google.com"},
|
||||
"grafana.com": {"grafana.com"},
|
||||
"hashicorp.com": {"hashicorp.com"},
|
||||
"hivemq.com": {"hivemq.com"},
|
||||
"istio.io": {"istio.io"},
|
||||
"jaegertracing.io": {"jaegertracing.io"},
|
||||
"jfrog.com": {"jfrog.com"},
|
||||
"k0sproject.io": {"k0sproject.io"},
|
||||
"k6.io": {"k6.io"},
|
||||
"k8s.aws": {"k8s.aws"},
|
||||
"k8s.io": {"k8s.io"},
|
||||
"k8up.io": {"k8up.io"},
|
||||
"karpenter.sh": {"karpenter.sh"},
|
||||
"keda.sh": {"keda.sh"},
|
||||
"keycloak.org": {"keycloak.org"},
|
||||
"konghq.com": {"konghq.com"},
|
||||
"kserve.io": {"kserve.io"},
|
||||
"kubeflow.org": {"kubeflow.org"},
|
||||
"kyverno.io": {"kyverno.io"},
|
||||
"linkerd.io": {"linkerd.io"},
|
||||
"longhorn.io": {"longhorn.io"},
|
||||
"mariadb.com": {"mariadb.com"},
|
||||
"metallb.io": {"metallb.io"},
|
||||
"min.io": {"min.io"},
|
||||
"mongodb.com": {"mongodb.com"},
|
||||
"nats.io": {"nats.io"},
|
||||
"nginx.org": {"nginx.org"},
|
||||
"onepassword.com": {"onepassword.com"},
|
||||
"openshift.io": {"openshift.io"},
|
||||
"openshift": {"openshift"},
|
||||
"opentelemetry.io": {"opentelemetry.io"},
|
||||
"oracle.com": {"oracle.com"},
|
||||
"oraclecloud.com": {"oraclecloud.com"},
|
||||
"pingcap.com": {"pingcap.com"},
|
||||
"projectcontour.io": {"projectcontour.io"},
|
||||
"rabbitmq.com": {"rabbitmq.com"},
|
||||
"redislabs.com": {"redislabs.com"},
|
||||
"rook.io": {"rook.io"},
|
||||
"scylladb.com": {"scylladb.com"},
|
||||
"solo.io": {"solo.io"},
|
||||
"strimzi.io": {"strimzi.io"},
|
||||
"teleport.dev": {"teleport.dev"},
|
||||
"temporal.io": {"temporal.io"},
|
||||
"tinkerbell.org": {"tinkerbell.org"},
|
||||
"traefik.io": {"traefik.io"},
|
||||
"velero.io": {"velero.io"},
|
||||
"x-k8s.io": {"x-k8s.io"},
|
||||
"zalan.do": {"zalan.do"},
|
||||
"kubevirt.io": {"kubevirt.io"},
|
||||
"aiven.io": {"aiven.io"},
|
||||
"amazonaws.com": {"amazonaws.com"},
|
||||
"ansible.com": {"ansible.com"},
|
||||
"apache.org": {"apache.org"},
|
||||
"argoproj.io": {"argoproj.io"},
|
||||
"banzaicloud.com": {"banzaicloud.com"},
|
||||
"bitnami.com": {"bitnami.com"},
|
||||
"cert-manager.io": {"cert-manager.io"},
|
||||
"chaos-mesh.org": {"chaos-mesh.org"},
|
||||
"cilium.io": {"cilium.io"},
|
||||
"clastix.io": {"clastix.io"},
|
||||
"cloudflare-operator.io": {"cloudflare-operator.io"},
|
||||
"cloudflare.com": {"cloudflare.com"},
|
||||
"cncf.io": {"cncf.io"},
|
||||
"cnpg.io": {"cnpg.io"},
|
||||
"confluent.io": {"confluent.io"},
|
||||
"coreos.com": {"coreos.com"},
|
||||
"crossplane.io": {"crossplane.io"},
|
||||
"dapr.io": {"dapr.io"},
|
||||
"datadoghq.com": {"datadoghq.com"},
|
||||
"doppler.com": {"doppler.com"},
|
||||
"dragonflydb.io": {"dragonflydb.io"},
|
||||
"dynatrace.com": {"dynatrace.com"},
|
||||
"elastic.co": {"elastic.co"},
|
||||
"emqx.io": {"emqx.io"},
|
||||
"envoyproxy.io": {"envoyproxy.io"},
|
||||
"external-secrets.io": {"external-secrets.io"},
|
||||
"f5.com": {"f5.com"},
|
||||
"falco.org": {"falco.org"},
|
||||
"flagger.app": {"flagger.app"},
|
||||
"fluent.io": {"fluent.io"},
|
||||
"fluxcd.io": {"fluxcd.io"},
|
||||
"getambassador.io": {"getambassador.io"},
|
||||
"github.com": {"github.com"},
|
||||
"github.io": {"github.io"},
|
||||
"gitlab.com": {"gitlab.com"},
|
||||
"gke.io": {"gke.io"},
|
||||
"goharbor.io": {"goharbor.io"},
|
||||
"google.com": {"google.com"},
|
||||
"grafana.com": {"grafana.com"},
|
||||
"hashicorp.com": {"hashicorp.com"},
|
||||
"hivemq.com": {"hivemq.com"},
|
||||
"istio.io": {"istio.io"},
|
||||
"jaegertracing.io": {"jaegertracing.io"},
|
||||
"jfrog.com": {"jfrog.com"},
|
||||
"k0sproject.io": {"k0sproject.io"},
|
||||
"k6.io": {"k6.io"},
|
||||
"k8s.aws": {"k8s.aws"},
|
||||
"k8s.io": {"k8s.io"},
|
||||
"k8up.io": {"k8up.io"},
|
||||
"karpenter.sh": {"karpenter.sh"},
|
||||
"keda.sh": {"keda.sh"},
|
||||
"keycloak.org": {"keycloak.org"},
|
||||
"knative.dev": {"knative.dev"},
|
||||
"konghq.com": {"konghq.com"},
|
||||
"kserve.io": {"kserve.io"},
|
||||
"kubeflow.org": {"kubeflow.org"},
|
||||
"kubevirt.io": {"kubevirt.io"},
|
||||
"kyverno.io": {"kyverno.io"},
|
||||
"linkerd.io": {"linkerd.io"},
|
||||
"litmuschaos.io": {"litmuschaos.io"},
|
||||
"longhorn.io": {"longhorn.io"},
|
||||
"mariadb.com": {"mariadb.com"},
|
||||
"metallb.io": {"metallb.io"},
|
||||
"microsoft.com": {"microsoft.com"},
|
||||
"min.io": {"min.io"},
|
||||
"mongodb.com": {"mongodb.com"},
|
||||
"nats.io": {"nats.io"},
|
||||
"nginx.org": {"nginx.org"},
|
||||
"nvidia.com": {"nvidia.com", "nvidia.io"},
|
||||
"onepassword.com": {"onepassword.com"},
|
||||
"open-cluster-management.io": {"open-cluster-management.io"},
|
||||
"openebs.io": {"openebs.io"},
|
||||
"openshift.io": {"openshift.io"},
|
||||
"openshift": {"openshift"},
|
||||
"opentelemetry.io": {"opentelemetry.io"},
|
||||
"oracle.com": {"oracle.com"},
|
||||
"oraclecloud.com": {"oraclecloud.com"},
|
||||
"pingcap.com": {"pingcap.com"},
|
||||
"projectcalico.org": {"projectcalico.org"},
|
||||
"projectcontour.io": {"projectcontour.io"},
|
||||
"rabbitmq.com": {"rabbitmq.com"},
|
||||
"ray.io": {"ray.io"},
|
||||
"redislabs.com": {"redislabs.com"},
|
||||
"rook.io": {"rook.io"},
|
||||
"scylladb.com": {"scylladb.com"},
|
||||
"solo.io": {"solo.io"},
|
||||
"strimzi.io": {"strimzi.io"},
|
||||
"tekton.dev": {"tekton.dev"},
|
||||
"teleport.dev": {"teleport.dev"},
|
||||
"temporal.io": {"temporal.io"},
|
||||
"tinkerbell.org": {"tinkerbell.org"},
|
||||
"traefik.io": {"traefik.io"},
|
||||
"velero.io": {"velero.io"},
|
||||
"victoriametrics.com": {"victoriametrics.com"},
|
||||
"volcano.sh": {"volcano.sh"},
|
||||
"x-k8s.io": {"x-k8s.io"},
|
||||
"zalan.do": {"zalan.do"},
|
||||
}
|
||||
|
||||
func resolveIcons(input string) string {
|
||||
|
||||
@@ -56,6 +56,13 @@ func NewUnstructuredRouteHandler(container container.Container, routeType base.R
|
||||
}
|
||||
|
||||
func NewUnstructuredHandler(ctx context.Context, config, cluster, kind, group, version, resource string, container container.Container) *UnstructuredHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-%s-%s-%s-%s-handlers/crds/resources.NewUnstructuredHandler", config, cluster, group, version, resource, kind)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *UnstructuredHandler {
|
||||
return newUnstructuredHandler(ctx, config, cluster, kind, group, version, resource, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newUnstructuredHandler(ctx context.Context, config, cluster, kind, group, version, resource string, container container.Container) *UnstructuredHandler {
|
||||
informer := container.DynamicSharedInformerFactory(config, cluster).ForResource(schema.GroupVersionResource{Group: group, Version: version, Resource: resource}).Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -33,6 +33,13 @@ func NewEventsRouteHandler(container container.Container, routeType base.RouteTy
|
||||
}
|
||||
|
||||
func NewEventsHandler(ctx context.Context, config, cluster string, container container.Container) *EventsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/events.NewEventsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *EventsHandler {
|
||||
return newEventsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newEventsHandler(ctx context.Context, config, cluster string, container container.Container) *EventsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Events().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@ package helpers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
@@ -32,11 +34,12 @@ func ReadFirstSSEMessage(url string) (string, error) {
|
||||
return "", fmt.Errorf("bad status code: %d", resp.StatusCode)
|
||||
}
|
||||
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
reader := bufio.NewReader(resp.Body)
|
||||
var data strings.Builder
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
line = strings.TrimRight(line, "\r\n")
|
||||
|
||||
if after, ok := strings.CutPrefix(line, "data:"); ok {
|
||||
data.WriteString(after)
|
||||
@@ -47,10 +50,13 @@ func ReadFirstSSEMessage(url string) (string, error) {
|
||||
if line == "" && data.Len() > 0 {
|
||||
return strings.TrimSpace(data.String()), nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
return "", fmt.Errorf("error reading SSE stream: %w", err)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
return "", fmt.Errorf("error reading SSE stream: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no SSE message received")
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// sseServer spins up a test server that writes a single SSE stream and closes.
|
||||
func sseServer(t *testing.T, body string) *httptest.Server {
|
||||
t.Helper()
|
||||
return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
}
|
||||
|
||||
func TestReadFirstSSEMessage(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
body string
|
||||
wantData string
|
||||
wantErr string
|
||||
}{
|
||||
{
|
||||
name: "small payload",
|
||||
body: "data: hello\n\n",
|
||||
wantData: "hello",
|
||||
},
|
||||
{
|
||||
name: "128 KiB payload — above old 64 KiB scanner limit",
|
||||
body: "data: " + strings.Repeat("x", 128*1024) + "\n\n",
|
||||
wantData: strings.Repeat("x", 128*1024),
|
||||
},
|
||||
{
|
||||
name: "1 MiB payload",
|
||||
body: "data: " + strings.Repeat("y", 1024*1024) + "\n\n",
|
||||
wantData: strings.Repeat("y", 1024*1024),
|
||||
},
|
||||
{
|
||||
name: "10 MiB payload — no ceiling with bufio.Reader",
|
||||
body: "data: " + strings.Repeat("z", 10*1024*1024) + "\n\n",
|
||||
wantData: strings.Repeat("z", 10*1024*1024),
|
||||
},
|
||||
{
|
||||
name: "only first event is returned",
|
||||
body: "data: first\n\ndata: second\n\n",
|
||||
wantData: "first",
|
||||
},
|
||||
{
|
||||
name: "multi-line event (multiple data: fields joined)",
|
||||
body: "data: line1\ndata: line2\n\n",
|
||||
// CutPrefix strips "data:" but keeps the space after the colon;
|
||||
// TrimSpace only trims the outer edges, so interior lines retain " line2".
|
||||
wantData: "line1\n line2",
|
||||
},
|
||||
{
|
||||
name: "no SSE message — keepalive only",
|
||||
body: ": keepalive\n\n",
|
||||
wantErr: "no SSE message received",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
srv := sseServer(t, tt.body)
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadFirstSSEMessage(srv.URL)
|
||||
|
||||
if tt.wantErr != "" {
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.wantErr)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, tt.wantData, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadFirstSSEMessage_BadStatus(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
_, err := ReadFirstSSEMessage(srv.URL)
|
||||
require.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "bad status code: 500")
|
||||
}
|
||||
|
||||
// TestReadFirstSSEMessage_OldLimitWouldFail proves that the test payload
|
||||
// genuinely trips the pre-fix bufio.Scanner default limit, confirming the
|
||||
// test is exercising the right code path.
|
||||
func TestReadFirstSSEMessage_OldLimitWouldFail(t *testing.T) {
|
||||
bigLine := "data: " + strings.Repeat("x", 128*1024)
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(bigLine + "\n\n"))
|
||||
// no Buffer() override — same as old code
|
||||
for scanner.Scan() {
|
||||
}
|
||||
require.Error(t, scanner.Err(), "expected old default scanner to fail on 128 KiB line")
|
||||
assert.ErrorIs(t, scanner.Err(), bufio.ErrTooLong)
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -99,32 +100,37 @@ func ReadLogsStream(sseURL string) ([]LogEntry, error) {
|
||||
|
||||
var collected []LogEntry
|
||||
|
||||
scanner := bufio.NewScanner(resp.Body)
|
||||
reader := bufio.NewReader(resp.Body)
|
||||
var currentData strings.Builder
|
||||
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
for {
|
||||
line, err := reader.ReadString('\n')
|
||||
line = strings.TrimRight(line, "\r\n")
|
||||
|
||||
if line == "" {
|
||||
// End of event.
|
||||
if currentData.Len() > 0 {
|
||||
var entry LogEntry
|
||||
if err := json.Unmarshal([]byte(currentData.String()), &entry); err != nil {
|
||||
return collected, err
|
||||
if jsonErr := json.Unmarshal([]byte(currentData.String()), &entry); jsonErr != nil {
|
||||
return collected, jsonErr
|
||||
}
|
||||
collected = append(collected, entry)
|
||||
currentData.Reset()
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
if after, ok := strings.CutPrefix(line, "data:"); ok {
|
||||
data := after
|
||||
} else if after, ok := strings.CutPrefix(line, "data:"); ok {
|
||||
if currentData.Len() > 0 {
|
||||
currentData.WriteString("\n")
|
||||
}
|
||||
currentData.WriteString(data)
|
||||
currentData.WriteString(after)
|
||||
}
|
||||
// Ignore other line types (e.g., id:, event:, :keepalive).
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) {
|
||||
break
|
||||
}
|
||||
return collected, err
|
||||
}
|
||||
}
|
||||
|
||||
// Process any remaining data after the loop.
|
||||
@@ -136,12 +142,5 @@ func ReadLogsStream(sseURL string) ([]LogEntry, error) {
|
||||
collected = append(collected, entry)
|
||||
}
|
||||
|
||||
if err := scanner.Err(); err != nil {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return collected, nil
|
||||
}
|
||||
return collected, err
|
||||
}
|
||||
|
||||
return collected, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func makeSSEEvent(entry LogEntry) string {
|
||||
b, _ := json.Marshal(entry)
|
||||
return fmt.Sprintf("data: %s\n\n", string(b))
|
||||
}
|
||||
|
||||
func TestReadLogsStream(t *testing.T) {
|
||||
entry1 := LogEntry{ContainerName: "main", Timestamp: "2024-01-01 00:00:00.000Z", Log: "hello"}
|
||||
entry2 := LogEntry{ContainerName: "sidecar", Timestamp: "2024-01-01 00:00:01.000Z", Log: "world"}
|
||||
|
||||
t.Run("normal multiple log entries", func(t *testing.T) {
|
||||
body := makeSSEEvent(entry1) + makeSSEEvent(entry2)
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadLogsStream(srv.URL)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got, 2)
|
||||
assert.Equal(t, entry1, got[0])
|
||||
assert.Equal(t, entry2, got[1])
|
||||
})
|
||||
|
||||
t.Run("128 KiB log line — above old 64 KiB scanner limit", func(t *testing.T) {
|
||||
bigLog := strings.Repeat("z", 128*1024)
|
||||
big := LogEntry{ContainerName: "app", Timestamp: "2024-01-01 00:00:00.000Z", Log: bigLog}
|
||||
body := makeSSEEvent(big)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadLogsStream(srv.URL)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got, 1)
|
||||
assert.Equal(t, bigLog, got[0].Log)
|
||||
})
|
||||
|
||||
t.Run("1 MiB log line", func(t *testing.T) {
|
||||
bigLog := strings.Repeat("m", 1024*1024)
|
||||
big := LogEntry{ContainerName: "app", Timestamp: "2024-01-01 00:00:00.000Z", Log: bigLog}
|
||||
body := makeSSEEvent(big)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadLogsStream(srv.URL)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got, 1)
|
||||
assert.Equal(t, bigLog, got[0].Log)
|
||||
})
|
||||
|
||||
t.Run("10 MiB log line — no ceiling with bufio.Reader", func(t *testing.T) {
|
||||
bigLog := strings.Repeat("n", 10*1024*1024)
|
||||
big := LogEntry{ContainerName: "app", Timestamp: "2024-01-01 00:00:00.000Z", Log: bigLog}
|
||||
body := makeSSEEvent(big)
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
fmt.Fprint(w, body)
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadLogsStream(srv.URL)
|
||||
require.NoError(t, err)
|
||||
require.Len(t, got, 1)
|
||||
assert.Equal(t, bigLog, got[0].Log)
|
||||
})
|
||||
|
||||
t.Run("empty stream returns no entries", func(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
got, err := ReadLogsStream(srv.URL)
|
||||
require.NoError(t, err)
|
||||
assert.Empty(t, got)
|
||||
})
|
||||
}
|
||||
|
||||
// TestReadLogsStream_OldLimitWouldFail confirms the 128 KiB JSON payload
|
||||
// genuinely trips the pre-fix bufio.Scanner default, proving the test cases
|
||||
// above exercise the right code path.
|
||||
func TestReadLogsStream_OldLimitWouldFail(t *testing.T) {
|
||||
bigLog := strings.Repeat("z", 128*1024)
|
||||
entry := LogEntry{ContainerName: "app", Timestamp: "2024-01-01 00:00:00.000Z", Log: bigLog}
|
||||
b, _ := json.Marshal(entry)
|
||||
line := "data: " + string(b)
|
||||
|
||||
scanner := bufio.NewScanner(strings.NewReader(line + "\n\n"))
|
||||
// no Buffer() override — same as old code
|
||||
for scanner.Scan() {
|
||||
}
|
||||
require.Error(t, scanner.Err(), "expected old default scanner to fail on 128 KiB line")
|
||||
assert.ErrorIs(t, scanner.Err(), bufio.ErrTooLong)
|
||||
}
|
||||
@@ -39,6 +39,13 @@ func NewNamespacesRouteHandler(container container.Container, routeType base.Rou
|
||||
}
|
||||
|
||||
func NewNamespacesHandler(ctx context.Context, config, cluster string, container container.Container) *NamespacesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/namespaces.NewNamespacesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *NamespacesHandler {
|
||||
return newNamespacesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newNamespacesHandler(ctx context.Context, config, cluster string, container container.Container) *NamespacesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Namespaces().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewEndpointsRouteHandler(container container.Container, routeType base.Rout
|
||||
}
|
||||
|
||||
func NewEndpointsHandler(ctx context.Context, config, cluster string, container container.Container) *EndpointsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/network/endpoints.NewEndpointsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *EndpointsHandler {
|
||||
return newEndpointsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newEndpointsHandler(ctx context.Context, config, cluster string, container container.Container) *EndpointsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Discovery().V1().EndpointSlices().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewIngressRouteHandler(container container.Container, routeType base.RouteT
|
||||
}
|
||||
|
||||
func NewIngressHandler(ctx context.Context, config, cluster string, container container.Container) *IngressHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/network/ingresses.NewIngressHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *IngressHandler {
|
||||
return newIngressHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newIngressHandler(ctx context.Context, config, cluster string, container container.Container) *IngressHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Networking().V1().Ingresses().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewServicesRouteHandler(container container.Container, routeType base.Route
|
||||
}
|
||||
|
||||
func NewServicesHandler(ctx context.Context, config, cluster string, container container.Container) *ServicesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/network/services.NewServicesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ServicesHandler {
|
||||
return newServicesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newServicesHandler(ctx context.Context, config, cluster string, container container.Container) *ServicesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Services().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -44,6 +44,13 @@ func NewNodeRouteHandler(container container.Container, routeType base.RouteType
|
||||
}
|
||||
|
||||
func NewNodeHandler(ctx context.Context, config, cluster string, container container.Container) *NodeHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/nodes.NewNodeHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *NodeHandler {
|
||||
return newNodeHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newNodeHandler(ctx context.Context, config, cluster string, container container.Container) *NodeHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Nodes().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewPersistentVolumeClaimsRouteHandler(container container.Container, routeT
|
||||
}
|
||||
|
||||
func NewPersistentVolumeClaimsHandler(ctx context.Context, config, cluster string, container container.Container) *PersistentVolumeClaimsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/storage/persistentvolumeclaims.NewPersistentVolumeClaimsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *PersistentVolumeClaimsHandler {
|
||||
return newPersistentVolumeClaimsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newPersistentVolumeClaimsHandler(ctx context.Context, config, cluster string, container container.Container) *PersistentVolumeClaimsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().PersistentVolumeClaims().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewPersistentVolumeRouteHandler(container container.Container, routeType ba
|
||||
}
|
||||
|
||||
func NewPersistentVolumeHandler(ctx context.Context, config, cluster string, container container.Container) *PersistentVolumeHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/storage/persistentvolumes.NewPersistentVolumeHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *PersistentVolumeHandler {
|
||||
return newPersistentVolumeHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newPersistentVolumeHandler(ctx context.Context, config, cluster string, container container.Container) *PersistentVolumeHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().PersistentVolumes().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewStorageClassRouteHandler(container container.Container, routeType base.R
|
||||
}
|
||||
|
||||
func NewStorageClassesHandler(ctx context.Context, config, cluster string, container container.Container) *StorageClassesHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/storage/storageclasses.NewStorageClassesHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *StorageClassesHandler {
|
||||
return newStorageClassesHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newStorageClassesHandler(ctx context.Context, config, cluster string, container container.Container) *StorageClassesHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Storage().V1().StorageClasses().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewCronJobsRouteHandler(container container.Container, routeType base.Route
|
||||
}
|
||||
|
||||
func NewCronJobsHandler(ctx context.Context, config, cluster string, container container.Container) *CronJobsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/cronJobs.NewCronJobsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *CronJobsHandler {
|
||||
return newCronJobsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newCronJobsHandler(ctx context.Context, config, cluster string, container container.Container) *CronJobsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Batch().V1().CronJobs().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewDaemonSetsRouteHandler(container container.Container, routeType base.Rou
|
||||
}
|
||||
|
||||
func NewDaemonSetsHandler(ctx context.Context, config, cluster string, container container.Container) *DaemonSetsHandlers {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/daemonsets.NewDaemonSetsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *DaemonSetsHandlers {
|
||||
return newDaemonSetsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newDaemonSetsHandler(ctx context.Context, config, cluster string, container container.Container) *DaemonSetsHandlers {
|
||||
informer := container.SharedInformerFactory(config, cluster).Apps().V1().DaemonSets().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -54,6 +54,13 @@ func NewDeploymentRouteHandler(container container.Container, routeType base.Rou
|
||||
}
|
||||
|
||||
func NewDeploymentsHandler(ctx context.Context, config, cluster string, container container.Container) *DeploymentsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/deployments.NewDeploymentsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *DeploymentsHandler {
|
||||
return newDeploymentsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newDeploymentsHandler(ctx context.Context, config, cluster string, container container.Container) *DeploymentsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Apps().V1().Deployments().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -39,6 +39,13 @@ func NewJobsRouteHandler(container container.Container, routeType base.RouteType
|
||||
}
|
||||
|
||||
func NewJobsHandler(ctx context.Context, config, cluster string, container container.Container) *JobsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/jobs.NewJobsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *JobsHandler {
|
||||
return newJobsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newJobsHandler(ctx context.Context, config, cluster string, container container.Container) *JobsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Batch().V1().Jobs().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -61,6 +61,13 @@ func NewPodsRouteHandler(container container.Container, routeType base.RouteType
|
||||
}
|
||||
|
||||
func NewPodsHandler(ctx context.Context, config, cluster string, container container.Container) *PodsHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/pods.NewPodsHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *PodsHandler {
|
||||
return newPodsHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newPodsHandler(ctx context.Context, config, cluster string, container container.Container) *PodsHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Core().V1().Pods().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
clientSet := container.ClientSet(config, cluster)
|
||||
|
||||
@@ -150,6 +150,11 @@ func GetPodStatusReason(pod *coreV1.Pod) (string, string) {
|
||||
case container.State.Waiting != nil && len(container.State.Waiting.Reason) > 0 && container.State.Waiting.Reason != "PodInitializing":
|
||||
reason = "Init:" + container.State.Waiting.Reason
|
||||
initializing = true
|
||||
case container.State.Running != nil &&
|
||||
i < len(pod.Spec.InitContainers) &&
|
||||
pod.Spec.InitContainers[i].RestartPolicy != nil &&
|
||||
*pod.Spec.InitContainers[i].RestartPolicy == coreV1.ContainerRestartPolicyAlways:
|
||||
continue
|
||||
default:
|
||||
if container.State.Running != nil {
|
||||
continue
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewReplicaSetRouteHandler(container container.Container, routeType base.Rou
|
||||
}
|
||||
|
||||
func NewReplicaSetHandler(ctx context.Context, config, cluster string, container container.Container) *ReplicaSetHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/replicaset.NewReplicaSetHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *ReplicaSetHandler {
|
||||
return newReplicaSetHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newReplicaSetHandler(ctx context.Context, config, cluster string, container container.Container) *ReplicaSetHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Apps().V1().ReplicaSets().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
@@ -40,6 +40,13 @@ func NewStatefulSetRouteHandler(container container.Container, routeType base.Ro
|
||||
}
|
||||
|
||||
func NewSatefulSetHandler(ctx context.Context, config, cluster string, container container.Container) *StatefulSetHandler {
|
||||
cacheKey := fmt.Sprintf("%s-%s-handlers/workloads/statefulsets.NewSatefulSetHandler", config, cluster)
|
||||
return base.GetOrCreateHandler(cacheKey, func() *StatefulSetHandler {
|
||||
return newSatefulSetHandler(ctx, config, cluster, container)
|
||||
})
|
||||
}
|
||||
|
||||
func newSatefulSetHandler(ctx context.Context, config, cluster string, container container.Container) *StatefulSetHandler {
|
||||
informer := container.SharedInformerFactory(config, cluster).Apps().V1().StatefulSets().Informer()
|
||||
informer.SetTransform(helpers.StripUnusedFields)
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 10 KiB |
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect width="100" height="100" rx="12" fill="#1A237E"/>
|
||||
<rect x="12" y="35" width="76" height="30" rx="15" fill="none" stroke="#00BCD4" stroke-width="6"/>
|
||||
<circle cx="35" cy="50" r="10" fill="#00BCD4"/>
|
||||
<circle cx="65" cy="50" r="10" fill="white"/>
|
||||
<path d="M35 40 L65 40 L65 60 L35 60 Z" fill="#1A237E"/>
|
||||
<circle cx="35" cy="50" r="10" fill="#00BCD4"/>
|
||||
<circle cx="65" cy="50" r="10" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 484 B |
@@ -0,0 +1,11 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect width="100" height="100" rx="12" fill="#1F6BA5"/>
|
||||
<ellipse cx="50" cy="36" rx="18" ry="10" fill="white"/>
|
||||
<path d="M32 36 L32 62 C32 72 68 72 68 62 L68 36" fill="white"/>
|
||||
<path d="M68 36 C68 46 80 46 80 36 C80 26 68 26 68 36Z" fill="white"/>
|
||||
<ellipse cx="50" cy="36" rx="18" ry="10" fill="#1F6BA5"/>
|
||||
<ellipse cx="50" cy="36" rx="14" ry="7" fill="white"/>
|
||||
<path d="M36 36 L36 60 C36 68 64 68 64 60 L64 36" fill="#1F6BA5"/>
|
||||
<path d="M64 40 C64 50 76 50 76 40 C76 30 64 30 64 40Z" fill="#1F6BA5"/>
|
||||
<circle cx="74" cy="38" r="4" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 634 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="48.91 -1.09 472.18 576.68"><defs><style>.cls-2{fill:#00b4c8}</style></defs><path fill="none" d="M196.604 498.09a89.682 89.682 0 0 0-13.023.965 40.633 40.633 0 0 0-11.9 3.536 21.616 21.616 0 0 0-8.521 7.237 20.21 20.21 0 0 0-3.215 11.737 31.384 31.384 0 0 0 1.219 9.165 17.022 17.022 0 0 0 7.46 9.96q8.682 5.31 23.477 5.307 18.004 0 27.333-1.93v-43.083a75.905 75.905 0 0 0-9.323-1.93 86.893 86.893 0 0 0-13.507-.965z"/><path d="M449.796 202.845q-59.153 58.926-118.375 117.786L146.075 505.977l-.455-.454c-10.614 10.65-21.158 21.371-31.393 32.377-5.393 5.8-7.384 13.173-1.166 19.87 6.506 7.012 14.346 6.588 21.53 1.266 5.376-3.982 10.062-8.948 14.822-13.705q150.23-150.18 300.194-300.633l60.89-10.613c-9.937-10.087-51.278-40.626-60.7-31.24z" class="cls-2"/><path d="M478.784 292.437a12.923 12.923 0 0 0-9.082-12.55c-9.699-3.506-16.357 2.168-22.599 8.406Q324.865 410.481 202.66 532.702c-7.21 7.214-14.657 15.812-5.816 25.346 9.758 10.524 18.9 2.988 26.64-4.743q123.57-123.452 247.065-246.983c3.915-3.915 7.825-7.863 8.236-13.885zm-162.923-9.911l17.142-17.141c-1.391-4.326-4.908-8.414-8.611-12.12Q206.824 135.632 89.169 18.086c-4.387-4.384-9.075-8.341-15.87-8.073-5.329.275-9.597 2.553-11.62 7.553-3.576 8.834.995 15.298 6.89 21.195q117.585 117.616 235.184 235.215c3.707 3.706 7.796 7.18 12.108 8.55zm154.131 108.506c7.257-7.343 13.7-16.123 3.918-25.36-8.782-8.293-17.17-2.51-24.072 4.354-31.334 31.157-62.48 62.504-93.819 93.655-10.96 10.893-10.454 21.057.401 31.721 18.385 18.067 36.744 36.174 54.585 54.771 10.004 10.428 20.93 16.95 35.042 14.194 3.259.21 5.737.691 8.15.466 10.303-.957 23.307-.281 23.634-14.478.335-14.644-12.332-14.708-22.943-14.312-10.777.402-18.684-4.032-25.845-11.565-10.991-11.561-21.99-23.19-33.87-33.808-10.513-9.4-9.018-16.292.55-25.497 25.204-24.25 49.677-49.261 74.27-74.14zm-209.337-75.967c3.818 3.802 8.394 7.687 13.347 9.321l17.063-17.063c-2.163-6.188-7.316-10.32-11.784-14.798q-72.062-72.226-144.255-144.32c-9.966-9.96-19.873-19.993-30.15-29.63-6.04-5.667-13.213-7.124-19.652-.742-6.13 6.073-5.69 13.22-.859 20.024a66.122 66.122 0 0 0 7.223 8.303q84.46 84.526 169.067 168.905zm-64.009 20.518c9.1 9.076 18.153 18.214 27.585 26.935a17.673 17.673 0 0 0 7.408 4.233l17.85-17.85c-1.172-4.601-4.226-8.242-7.63-11.65q-54.495-54.594-109.11-109.066a33.321 33.321 0 0 0-10.425-7.263c-5.97-2.449-12.126-2.054-16.872 3.173-4.793 5.279-4.73 11.353-1.011 16.908a96.1 96.1 0 0 0 11.722 14.029q40.113 40.402 80.483 80.551z" class="cls-2"/></svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg viewBox="0 0 735 593.5" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#0865ad" d="M297.496 1.488 65.749 113.096a15.035 15.035 0 0 0-8.135 10.194L.377 374.065a15.02 15.02 0 0 0 2.902 12.711l160.376 201.108a15.038 15.038 0 0 0 11.747 5.657H432.63c4.571 0 8.895-2.085 11.747-5.657l160.376-201.108a15.023 15.023 0 0 0 2.903-12.711L550.418 123.29a15.019 15.019 0 0 0-8.135-10.194L310.536 1.488a15.022 15.022 0 0 0-13.04 0"/>
|
||||
<path fill="#fff" d="M221.845 210.533h51.054v100.764h1.017c5.072-8.798 10.48-16.907 15.552-25.023l51.736-75.741h63.225l-75.398 97.039 79.455 130.856h-60.18l-55.792-98.394-19.615 24.005v74.389h-51.054V210.533Z"/>
|
||||
<path fill="#6695ca" d="m585.328 1.307-91.112 33.16a7.521 7.521 0 0 0-3.935 3.306l-48.478 83.964a7.513 7.513 0 0 0-.892 5.066l16.835 95.483a7.495 7.495 0 0 0 2.568 4.453l74.277 62.319a7.507 7.507 0 0 0 4.828 1.76h96.957a7.515 7.515 0 0 0 4.831-1.76l74.274-62.319a7.508 7.508 0 0 0 2.567-4.453l16.839-95.483a7.538 7.538 0 0 0-.896-5.066l-48.474-83.964a7.526 7.526 0 0 0-3.939-3.306l-91.112-33.16a7.5 7.5 0 0 0-5.138 0"/>
|
||||
<path fill="#fff" d="M570.231 111.865a59.358 59.358 0 0 1 5.654-4.821 37.76 37.76 0 0 1 6.228-3.773c2.192-1.052 4.559-1.866 7.101-2.452 2.542-.585 5.301-.876 8.281-.876 4.91 0 9.265.848 13.063 2.542 3.801 1.694 7.001 4.067 9.603 7.101 2.602 3.04 4.558 6.663 5.873 10.871 1.316 4.205 1.976 8.826 1.976 13.851v57.423h-24.115v-57.423c0-5.025-1.168-8.929-3.5-11.706-2.342-2.775-5.786-4.162-10.351-4.162-3.385 0-6.569.73-9.556 2.192-2.981 1.462-5.814 3.504-8.498 6.137v64.962h-24.202v-90.389h14.903c3.04 0 5.057 1.403 6.056 4.211l1.484 6.312Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="117" height="147" viewBox="0 0 117 147" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M117 0H0V135.975C0 142.064 4.91087 147 10.9687 147H106.031C112.089 147 117 142.064 117 135.975V0Z" fill="#878EDE"/>
|
||||
<path d="M17.7266 26.6445C17.7266 22.2263 21.3083 18.6445 25.7266 18.6445H27.4538C31.8721 18.6445 35.4538 22.2263 35.4538 26.6445V59.8135H17.7266V26.6445Z" fill="#5A44BA"/>
|
||||
<path d="M41.3633 130.388V112.744H91.2724C95.6906 112.744 99.2724 116.326 99.2724 120.744V122.388C99.2724 126.806 95.6907 130.388 91.2724 130.388H41.3633Z" fill="white"/>
|
||||
<path d="M17.6992 60H35.3992V122.8C35.3992 127.218 31.8175 130.8 27.3992 130.8H25.6992C21.2809 130.8 17.6992 127.218 17.6992 122.8V60Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 767 B |
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 23 23">
|
||||
<rect x="1" y="1" width="10" height="10" fill="#F35325"/>
|
||||
<rect x="12" y="1" width="10" height="10" fill="#81BC06"/>
|
||||
<rect x="1" y="12" width="10" height="10" fill="#05A6F0"/>
|
||||
<rect x="12" y="12" width="10" height="10" fill="#FFBA08"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 312 B |
@@ -0,0 +1 @@
|
||||
<svg role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>NVIDIA</title><path fill="#76B900" d="M8.948 8.798v-1.43a6.7 6.7 0 0 1 .424-.018c3.922-.124 6.493 3.374 6.493 3.374s-2.774 3.851-5.75 3.851c-.398 0-.787-.062-1.158-.185v-4.346c1.528.185 1.837.857 2.747 2.385l2.04-1.714s-1.492-1.952-4-1.952a6.016 6.016 0 0 0-.796.035m0-4.735v2.138l.424-.027c5.45-.185 9.01 4.47 9.01 4.47s-4.08 4.964-8.33 4.964c-.37 0-.733-.035-1.095-.097v1.325c.3.035.61.062.91.062 3.957 0 6.82-2.023 9.593-4.408.459.371 2.34 1.263 2.73 1.652-2.633 2.208-8.772 3.984-12.253 3.984-.335 0-.653-.018-.971-.053v1.864H24V4.063zm0 10.326v1.131c-3.657-.654-4.673-4.46-4.673-4.46s1.758-1.944 4.673-2.262v1.237H8.94c-1.528-.186-2.73 1.245-2.73 1.245s.68 2.412 2.739 3.11M2.456 10.9s2.164-3.197 6.5-3.533V6.201C4.153 6.59 0 10.653 0 10.653s2.35 6.802 8.948 7.42v-1.237c-4.84-.6-6.492-5.936-6.492-5.936z"/></svg>
|
||||
|
After Width: | Height: | Size: 897 B |
@@ -0,0 +1,15 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="12" fill="#0066CC"/>
|
||||
<circle cx="50" cy="14" r="9" fill="#0066CC"/>
|
||||
<circle cx="80" cy="32" r="9" fill="#0066CC"/>
|
||||
<circle cx="80" cy="68" r="9" fill="#0066CC"/>
|
||||
<circle cx="50" cy="86" r="9" fill="#0066CC"/>
|
||||
<circle cx="20" cy="68" r="9" fill="#0066CC"/>
|
||||
<circle cx="20" cy="32" r="9" fill="#0066CC"/>
|
||||
<line x1="50" y1="50" x2="50" y2="23" stroke="#0066CC" stroke-width="3"/>
|
||||
<line x1="50" y1="50" x2="71" y2="38" stroke="#0066CC" stroke-width="3"/>
|
||||
<line x1="50" y1="50" x2="71" y2="62" stroke="#0066CC" stroke-width="3"/>
|
||||
<line x1="50" y1="50" x2="50" y2="77" stroke="#0066CC" stroke-width="3"/>
|
||||
<line x1="50" y1="50" x2="29" y2="62" stroke="#0066CC" stroke-width="3"/>
|
||||
<line x1="50" y1="50" x2="29" y2="38" stroke="#0066CC" stroke-width="3"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 870 B |
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,5 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="48" fill="#F88A1E"/>
|
||||
<path d="M50 14 C30 14 14 30 14 50 C14 70 30 86 50 86 C62 86 72 80 79 71 L68 65 C64 71 57 75 50 75 C36 75 25 64 25 50 C25 36 36 25 50 25 C57 25 64 29 68 35 L79 29 C72 20 62 14 50 14Z" fill="white"/>
|
||||
<path d="M75 50 C75 44 73 39 70 35 L59 41 C61 43 63 46 63 50 C63 54 61 57 59 59 L70 65 C73 61 75 56 75 50Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 446 B |
@@ -0,0 +1,8 @@
|
||||
<svg width="160" height="160" viewBox="0 0 160 160" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect x="16" y="70" width="37" height="37" fill="#02A0CF"/>
|
||||
<rect x="72" y="70" width="37" height="37" fill="#02A0CF"/>
|
||||
<rect x="72" y="14" width="37" height="37" fill="#02A0CF"/>
|
||||
<rect x="72" y="109" width="37" height="37" fill="#02A0CF"/>
|
||||
<rect x="109" y="70" width="37" height="37" fill="#02A0CF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M114 88L69 133L66 130L111 85L114 88ZM112 89L38 89L38 85L112 85L112 89ZM66 43L111 88L114 85L69 40L66 43Z" fill="#02A0CF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 580 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img" viewBox="14.90 -7.60 688.70 733.20"><defs><linearGradient id="a" x1="40.578" x2="549.101" y1="662.91" y2="108.676" gradientTransform="matrix(1 0 0 -1 0 712.222)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#a677b4"/><stop offset=".363" stop-color="#f0515a"/><stop offset="1" stop-color="#2b338c"/></linearGradient></defs><path fill="url(#a)" fill-rule="evenodd" d="M297.486 319.777v6.908m182.388 217.198l6.011-1.615.718 4.665c3.409 21.442 1.884 40.012-6.819 58.942 13.458 1.884 25.21 8.343 31.4 22.07 4.396 9.689 8.613 20.993 8.703 31.758 0 7.985-2.512 15.97-8.792 21.173a20.86 20.86 0 0 1-13.188 4.755H427.66c-4.037 11.035-12.022 21.172-23.685 24.223a54.199 54.199 0 0 1-9.958 1.345c-3.589.18-7.087.27-10.586.27-9.061.089-18.122 0-27.184 0q-21.262-.27-42.524-.808a22.658 22.658 0 0 1-20.006-13.009 22.58 22.58 0 0 1-19.917 13.009c-14.264.359-28.439.628-42.614.807-9.06.09-18.122.18-27.183 0-3.499 0-6.998-.09-10.586-.269a47.501 47.501 0 0 1-10.048-1.345c-11.663-3.05-19.558-13.278-23.685-24.223H90.067a20.86 20.86 0 0 1-13.188-4.755c-6.28-5.203-8.792-13.188-8.792-21.173 0-10.765 4.307-22.07 8.613-31.758a36.138 36.138 0 0 1 10.407-13.457 42.391 42.391 0 0 1 20.365-8.613c-8.703-18.93-10.228-37.5-6.819-58.942l.718-4.665 6.729 1.794a95.2 95.2 0 0 1 3.23-12.022 78.076 78.076 0 0 1 24.85-36.154 64.905 64.905 0 0 1 13.547-8.344 239.918 239.918 0 0 1 5.114-38.218 174.147 174.147 0 0 1 14.892-49.163 68.053 68.053 0 0 1-9.15-14.444c-.36-.807-.718-1.615-.987-2.422a209.478 209.478 0 0 1-59.48-50.42c-9.87-12.11-24.313-30.95-25.57-46.83-.627-5.562-.807-11.125-.896-16.597a296.926 296.926 0 0 1 2.153-39.923c.897-7.715 2.153-15.43 3.678-23.056a214.155 214.155 0 0 1-26.645-38.398 194.37 194.37 0 0 1-22.249-69.528 189.93 189.93 0 0 1 5.473-72.13A27.186 27.186 0 0 1 62.256 6.496c45.933 0 85.587 18.75 122.46 42.973a216.023 216.023 0 0 1 225.72 0c36.782-24.222 76.436-42.973 122.37-42.973a26.901 26.901 0 0 1 26.106 20.007 191.986 191.986 0 0 1 5.383 72.13 194.37 194.37 0 0 1-22.249 69.528 213.693 213.693 0 0 1-26.555 38.397c1.435 7.267 2.601 14.534 3.588 21.98a293.14 293.14 0 0 1 2.243 40.64c-.09 5.653-.27 11.305-.897 16.777-1.435 16.328-15.43 34.63-25.569 47.01a210.939 210.939 0 0 1-59.48 50.42l-1.076 2.422a124.22 124.22 0 0 1-6.37 11.752 55.538 55.538 0 0 1-7.357 9.6 140.82 140.82 0 0 1 5.024 13.367 183.229 183.229 0 0 1 6.908 29.516c1.077 5.114 2.064 10.317 2.781 15.43 20.366-34.09 47.46-64.862 81.55-83.792 20.007-11.124 42.704-18.212 65.76-17.584 24.493.628 48.536 12.022 67.107 27.632 20.365 17.135 36.962 41.627 39.743 68.631a39.08 39.08 0 0 1-.897 13.278c-3.499 14.444-14.623 25.748-27.811 31.938-16.867 7.895-37.95 7.626-52.124-5.742-7.985-7.625-10.497-15.969-14.534-25.748-2.422-5.741-4.934-10.137-10.048-13.995a35.138 35.138 0 0 0-23.684-7.087c-12.112.807-22.877 7.715-31.4 15.969a162.575 162.575 0 0 0-13.457 14.892 253.303 253.303 0 0 0-21.8 31.58 203.902 203.902 0 0 0-13.278 26.106 11.685 11.685 0 0 1-.718 1.525 3.328 3.328 0 0 0 .18.808z"/></svg>
|
||||
|
After Width: | Height: | Size: 3.0 KiB |
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
|
||||
<rect width="100" height="100" rx="12" fill="#621773"/>
|
||||
<path d="M15 25 L50 75 L85 25" fill="none" stroke="white" stroke-width="14" stroke-linejoin="round" stroke-linecap="round"/>
|
||||
<circle cx="15" cy="25" r="7" fill="white"/>
|
||||
<circle cx="85" cy="25" r="7" fill="white"/>
|
||||
<circle cx="50" cy="75" r="7" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 396 B |
|
After Width: | Height: | Size: 6.1 KiB |