Compare commits
381 Commits
web/v1.5.0
...
master
Author | SHA1 | Date |
---|---|---|
|
010e944dd3 | |
|
7198d4a2a6 | |
|
b0c1c0fa27 | |
|
3226f7125e | |
|
50ded48356 | |
|
996881820b | |
|
5dde0ea32b | |
|
03b1f77395 | |
|
c77a468ead | |
|
7f11a66821 | |
|
e6e64b24ed | |
|
6b73caffc2 | |
|
1f14d1aa4c | |
|
f06efec826 | |
|
953d0e371a | |
|
87c55c3c5f | |
|
15ea484235 | |
|
a3fe907944 | |
|
685945aab8 | |
|
9a19cd158d | |
|
3e2411680f | |
|
a5d39769e5 | |
|
8f9cf5a28f | |
|
5fd9688fbf | |
|
22d5102cc0 | |
|
c541e0d7d1 | |
|
3900260cfc | |
|
a35e1398f7 | |
|
3645cf9d2d | |
|
2423bfe0a4 | |
|
32f9ecd298 | |
|
1b911f3175 | |
|
1a77e38f32 | |
|
6ce4de9d8c | |
|
f37d307a47 | |
|
f33c80d1df | |
|
2e89a34cbd | |
|
f933072263 | |
|
1199c8e625 | |
|
4aed7e134b | |
|
2cffabe0f3 | |
|
330cf333c5 | |
|
b3979fdf93 | |
|
0be2f95535 | |
|
feab6156e5 | |
|
1e0179afd2 | |
|
10b5fd413c | |
|
787bd727b8 | |
|
915818620c | |
|
b434d3a45c | |
|
114a0a6f76 | |
|
45f657fbb3 | |
|
8b4b30eee4 | |
|
78bc957173 | |
|
ee8b965861 | |
|
db45d3454b | |
|
6a511fcef3 | |
|
4032614d8f | |
|
b80685942c | |
|
5fa2d73d2f | |
|
bfd4932829 | |
|
9a78ca515c | |
|
2a3283cc06 | |
|
86c4cd0e0e | |
|
db08679bf2 | |
|
22e068a49a | |
|
4e94cb16ed | |
|
03b43ad074 | |
|
a1e3c29213 | |
|
4111b4fe95 | |
|
1e8572fa82 | |
|
1fac58a20a | |
|
abba0efe76 | |
|
b9e4ccf3e5 | |
|
86fd9f0452 | |
|
f1f356f79b | |
|
edce9b9dd4 | |
|
64530e3010 | |
|
fc9b50b433 | |
|
afc10b5431 | |
|
7f196eb6ce | |
|
8889900a6d | |
|
9828a0c5d1 | |
|
480ab4802b | |
|
f974ba8eb1 | |
|
56f0d8925b | |
|
dd0af7bf1d | |
|
4e01ddb061 | |
|
49d974a7e9 | |
|
b4ae93db7e | |
|
c700947650 | |
|
d0f499bb8e | |
|
370a012cff | |
|
bf2b8b7c75 | |
|
6371e6afbb | |
|
fbfcf51005 | |
|
8de1150125 | |
|
61ed5721cc | |
|
58b5d9b88b | |
|
adb2cdfeb5 | |
|
381cebe3d1 | |
|
49bf79bfa3 | |
|
bb8b78bfe7 | |
|
56b084e062 | |
|
d603957ae9 | |
|
4d642e2d10 | |
|
2c4826434c | |
|
11f6d15412 | |
|
936828aeda | |
|
f9e4de84e0 | |
|
750a650f1a | |
|
1351a9dcb7 | |
|
28ff4bfae5 | |
|
0b17b9a6ad | |
|
f5ccbc4ae7 | |
|
293965b156 | |
|
9f087aaf17 | |
|
ba60b98d1a | |
|
72072fbe7b | |
|
64e9a9a0bb | |
|
17c98dd22c | |
|
8208ab8673 | |
|
6516d2152e | |
|
51ea34fabc | |
|
a93bbf87c6 | |
|
35b99c41b0 | |
|
db6e1ee29a | |
|
2af4949c0f | |
|
86c73104e3 | |
|
26577ed0c6 | |
|
6f72d2ba1c | |
|
e1a5f6d493 | |
|
1a2415c130 | |
|
b6a35a71ae | |
|
a51afe31a3 | |
|
126d382b10 | |
|
2e5bee9859 | |
|
7417670613 | |
|
c8822538da | |
|
ebec351a98 | |
|
8f256b2c08 | |
|
51fb2bb319 | |
|
3c09f9df03 | |
|
ae1307f8db | |
|
ca30fdd437 | |
|
5a06b56351 | |
|
38e970c366 | |
|
3e47336388 | |
|
77e273d743 | |
|
a2b4d0a1dd | |
|
b41606ef76 | |
|
ff827676df | |
|
02165a22f9 | |
|
34c57c5523 | |
|
8e1b153e0e | |
|
0b577780c0 | |
|
9f850e2180 | |
|
927c02a3b4 | |
|
6032ed3ed3 | |
|
e3d87d0fb3 | |
|
e1e1576bf7 | |
|
9f22897ba9 | |
|
8996dfc22d | |
|
dcb589ce72 | |
|
c6dd5bda6f | |
|
71a83359f6 | |
|
b18c8e24b1 | |
|
ca5c61fbd5 | |
|
75d27b382a | |
|
dafe79f25c | |
|
6433cb2870 | |
|
31f5d62fc1 | |
|
2e588c625d | |
|
85bfb3cca4 | |
|
481b702caf | |
|
31d20080cb | |
|
2b05535c5b | |
|
ab8e3a65f2 | |
|
484f16e56f | |
|
d816ffbb83 | |
|
0b3d28562b | |
|
1b6dc93bb5 | |
|
ff1de9eb39 | |
|
60975e9865 | |
|
8d93b32e4a | |
|
f7ef975e39 | |
|
61772510ee | |
|
5840d5f9f7 | |
|
a6427f7e62 | |
|
fd00cadc8a | |
|
60e010d09c | |
|
f9d8cc355e | |
|
40212bc304 | |
|
cb6c66624f | |
|
83498c1e68 | |
|
1b9ffe652c | |
|
4f3d800f84 | |
|
e82d2ee057 | |
|
30b03c6e05 | |
|
6e01e53e6b | |
|
93336fd145 | |
|
02f8eba204 | |
|
62b75aa426 | |
|
64eb51bd4e | |
|
87fd41e8fe | |
|
63404fbb55 | |
|
7be0753188 | |
|
a4c4f657d9 | |
|
5c759731f6 | |
|
d488b00092 | |
|
d7170cb9ed | |
|
0d8a18f9dc | |
|
b33fcc0cdd | |
|
b26549b04b | |
|
d5e7b9175e | |
|
3c622f9b62 | |
|
22ac1043e7 | |
|
8ceadd7313 | |
|
8f5b815402 | |
|
6d92c92e25 | |
|
b0d6aa1871 | |
|
facf317e50 | |
|
9a02a3c42b | |
|
86c4715d2e | |
|
d94d048f07 | |
|
8c599097e3 | |
|
62287369cf | |
|
05d848134f | |
|
0a549afd62 | |
|
55ccad9ed3 | |
|
9a9fa4f08a | |
|
8c5a881db5 | |
|
df9d716f96 | |
|
74315bb0d4 | |
|
a5ac0dcc05 | |
|
b9c5b7ec3a | |
|
5010fddc7a | |
|
4f08b578a8 | |
|
82cec92fb5 | |
|
1d4fc5fd94 | |
|
afd4a74ba3 | |
|
52fbb31939 | |
|
5cd92019d0 | |
|
9a9ae766ad | |
|
dbb345d0cf | |
|
06ecf945c7 | |
|
bc1de9480f | |
|
c251f0065c | |
|
57b1409cc0 | |
|
dbe63d2c30 | |
|
eafd14c48b | |
|
ea45200dc3 | |
|
5405597923 | |
|
ea52fce05a | |
|
b11874a4fc | |
|
307382ff58 | |
|
cc0262c676 | |
|
9ef9e971f3 | |
|
221334281f | |
|
8159be2eff | |
|
5927f3171c | |
|
9b80774c6e | |
|
94890a272e | |
|
d416e972bd | |
|
e10fffa63d | |
|
cd120a45f8 | |
|
cd255b86cf | |
|
d60f940f44 | |
|
141a6a9a1f | |
|
b2976955cc | |
|
64b1480c7f | |
|
19c8c78ebb | |
|
3065b26121 | |
|
8123cea939 | |
|
94f8b9ce0a | |
|
d6b91f2afe | |
|
a0b5e5f8ec | |
|
d62ac59c1e | |
|
bed5a7d109 | |
|
f3e62a616a | |
|
c61a717604 | |
|
85f878d8f7 | |
|
9d465b0df1 | |
|
8a0b3ce0f3 | |
|
fc253a0231 | |
|
43d48cd762 | |
|
6ecd0c54eb | |
|
c3d4288d57 | |
|
1a72907478 | |
|
6392dbad9d | |
|
7a039a9093 | |
|
dab6370bf7 | |
|
7a6dd57d42 | |
|
acf6b9635d | |
|
a77c41338e | |
|
97cc319d93 | |
|
2e9ea1b90f | |
|
5a91d5e45d | |
|
eb26056f28 | |
|
409ab1f5f3 | |
|
8c641c9b2d | |
|
fcb80bc36f | |
|
4eb364a555 | |
|
85f3dc4a6a | |
|
48478e1e82 | |
|
c68c93a16e | |
|
7346c66274 | |
|
a991528770 | |
|
41611ad915 | |
|
36b08ee0ca | |
|
1e49059fda | |
|
2f436f0e97 | |
|
72c0b07b9b | |
|
c449e51d48 | |
|
5292689afd | |
|
06c0812194 | |
|
66885e1711 | |
|
8c15a76aec | |
|
e5cd861cb6 | |
|
5a587bd9fd | |
|
6957b1d05b | |
|
fa762b4ff6 | |
|
efaf9ad6e5 | |
|
cfb8bcbcba | |
|
29f6fbc415 | |
|
e275ef1dcd | |
|
5eb039e695 | |
|
9dc6e8fe99 | |
|
8fbe285144 | |
|
0dc016b53a | |
|
547fdd014c | |
|
e4db364f6f | |
|
f49b0e345c | |
|
d5a177e051 | |
|
b6d4c4d7a8 | |
|
4b66aa1eb5 | |
|
029a11984f | |
|
9d28815f43 | |
|
74112276f1 | |
|
4682e7a9ff | |
|
3dfee00e55 | |
|
6216f6446e | |
|
8793bb1056 | |
|
b88d645910 | |
|
47f018f475 | |
|
db013e535b | |
|
33478bd9c3 | |
|
07442666dd | |
|
e8e1a20689 | |
|
1b58a29c16 | |
|
e9ab24549b | |
|
2265f585b2 | |
|
eae51819a1 | |
|
05ece8640f | |
|
1bce96de15 | |
|
4369c69753 | |
|
8a4d7ad118 | |
|
b5e99193e8 | |
|
d6ad91e8ee | |
|
d15ef0433f | |
|
62a51199d9 | |
|
3fbe71d786 | |
|
7f74648ab1 | |
|
e11fa77ca9 | |
|
f9727f4946 | |
|
feacf02349 | |
|
4ee066dd86 | |
|
7d32494ec7 | |
|
1a2bb6fc81 | |
|
b2ff6eee95 | |
|
fddec688fb | |
|
8a3539e999 | |
|
919a759eb5 | |
|
f5b3638cf7 | |
|
27cc313fbc | |
|
aec1d634ea | |
|
4840b929cc | |
|
d0a4fd2b05 | |
|
e34c4da5ad | |
|
f1b0123643 | |
|
28539a32f1 |
|
@ -48,15 +48,15 @@ jobs:
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=match,pattern=\d+\.\d+\.\d+
|
type=match,pattern=\d+\.\d+\.\d+
|
||||||
type=sha
|
type=sha
|
||||||
- uses: docker/setup-qemu-action@v3.2.0
|
- uses: docker/setup-qemu-action@v3.6.0
|
||||||
- uses: docker/setup-buildx-action@v3.7.1
|
- uses: docker/setup-buildx-action@v3.10.0
|
||||||
with:
|
with:
|
||||||
config: .github/buildkitd.toml
|
config: .github/buildkitd.toml
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=match,pattern=\d+\.\d+\.\d+
|
type=match,pattern=\d+\.\d+\.\d+
|
||||||
type=sha
|
type=sha
|
||||||
- uses: docker/setup-qemu-action@v3.2.0
|
- uses: docker/setup-qemu-action@v3.6.0
|
||||||
- uses: docker/setup-buildx-action@v3.7.1
|
- uses: docker/setup-buildx-action@v3.10.0
|
||||||
with:
|
with:
|
||||||
config: .github/buildkitd.toml
|
config: .github/buildkitd.toml
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|
|
@ -30,13 +30,13 @@ jobs:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4.1.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: azure/setup-helm@v4.2.0
|
- uses: azure/setup-helm@v4.3.0
|
||||||
with:
|
with:
|
||||||
version: v3.12.1
|
version: v3.12.1
|
||||||
- uses: helm/chart-testing-action@v2.6.1
|
- uses: helm/chart-testing-action@v2.7.0
|
||||||
- uses: helm/kind-action@v1.10.0
|
- uses: helm/kind-action@v1.12.0
|
||||||
with:
|
with:
|
||||||
node_image: kindest/node:v1.30.2
|
node_image: kindest/node:v1.32.0
|
||||||
- run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
- run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
||||||
|
|
||||||
release:
|
release:
|
||||||
|
@ -57,7 +57,7 @@ jobs:
|
||||||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||||
|
|
||||||
- name: Set up Helm
|
- name: Set up Helm
|
||||||
uses: azure/setup-helm@v4.2.0
|
uses: azure/setup-helm@v4.3.0
|
||||||
with:
|
with:
|
||||||
version: v3.12.1
|
version: v3.12.1
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ jobs:
|
||||||
helm repo add kong https://charts.konghq.com
|
helm repo add kong https://charts.konghq.com
|
||||||
|
|
||||||
- name: Run chart-releaser
|
- name: Run chart-releaser
|
||||||
uses: helm/chart-releaser-action@v1.6.0
|
uses: helm/chart-releaser-action@v1.7.0
|
||||||
with:
|
with:
|
||||||
skip_existing: true
|
skip_existing: true
|
||||||
mark_as_latest: true
|
mark_as_latest: true
|
||||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=match,pattern=\d+\.\d+\.\d+
|
type=match,pattern=\d+\.\d+\.\d+
|
||||||
type=sha
|
type=sha
|
||||||
- uses: docker/setup-qemu-action@v3.2.0
|
- uses: docker/setup-qemu-action@v3.6.0
|
||||||
- uses: docker/setup-buildx-action@v3.7.1
|
- uses: docker/setup-buildx-action@v3.10.0
|
||||||
with:
|
with:
|
||||||
config: .github/buildkitd.toml
|
config: .github/buildkitd.toml
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
||||||
type=raw,value=latest
|
type=raw,value=latest
|
||||||
type=match,pattern=\d+\.\d+\.\d+
|
type=match,pattern=\d+\.\d+\.\d+
|
||||||
type=sha
|
type=sha
|
||||||
- uses: docker/setup-qemu-action@v3.2.0
|
- uses: docker/setup-qemu-action@v3.6.0
|
||||||
- uses: docker/setup-buildx-action@v3.7.1
|
- uses: docker/setup-buildx-action@v3.10.0
|
||||||
with:
|
with:
|
||||||
config: .github/buildkitd.toml
|
config: .github/buildkitd.toml
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||||
- uses: docker/login-action@v3.3.0
|
- uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ghcr.io
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
|
|
|
@ -23,24 +23,31 @@ jobs:
|
||||||
name: Lint and test
|
name: Lint and test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4.1.1
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: azure/setup-helm@v4.2.0
|
- name: Set up Helm
|
||||||
|
uses: azure/setup-helm@v4.3.0
|
||||||
with:
|
with:
|
||||||
version: v3.12.1
|
version: v3.12.1
|
||||||
- uses: helm/chart-testing-action@v2.6.1
|
- name: Set up Chart Testing CLI
|
||||||
- id: list-changed
|
uses: helm/chart-testing-action@v2.7.0
|
||||||
|
- name: Change Detection
|
||||||
|
id: list-changed
|
||||||
run: |
|
run: |
|
||||||
changed=$(ct list-changed --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }})
|
changed=$(ct list-changed --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }})
|
||||||
if [[ -n "$changed" ]]; then
|
if [[ -n "$changed" ]]; then
|
||||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||||
fi
|
fi
|
||||||
- if: steps.list-changed.outputs.changed == 'true'
|
- name: Lint Chart
|
||||||
run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }}
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
- if: steps.list-changed.outputs.changed == 'true'
|
run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }} --check-version-increment=false
|
||||||
uses: helm/kind-action@v1.10.0
|
- name: Set up Kind
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
|
uses: helm/kind-action@v1.12.0
|
||||||
with:
|
with:
|
||||||
node_image: kindest/node:v1.30.2
|
node_image: kindest/node:v1.32.0
|
||||||
- if: steps.list-changed.outputs.changed == 'true'
|
- name: Install Chart
|
||||||
|
if: steps.list-changed.outputs.changed == 'true'
|
||||||
run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
||||||
|
|
|
@ -64,7 +64,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5.0.2
|
- uses: actions/setup-go@v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: modules/api/go.mod
|
go-version-file: modules/api/go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
@ -81,7 +81,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5.0.2
|
- uses: actions/setup-go@v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: modules/api/go.mod
|
go-version-file: modules/api/go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
@ -99,7 +99,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5.0.2
|
- uses: actions/setup-go@v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: modules/api/go.mod
|
go-version-file: modules/api/go.mod
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
@ -116,6 +116,63 @@ jobs:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: make image
|
- run: make image
|
||||||
|
|
||||||
|
publish:
|
||||||
|
name: Build and push API container
|
||||||
|
if: github.event.pull_request.head.repo.full_name == github.repository && github.actor != 'dependabot[bot]' # not a fork and not dependabot
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Docket meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: |
|
||||||
|
ghcr.io/kubernetes/dashboard-api
|
||||||
|
docker.io/kubernetesui/dashboard-api
|
||||||
|
tags: |
|
||||||
|
type=sha
|
||||||
|
type=ref,event=pr
|
||||||
|
type=ref,event=branch
|
||||||
|
type=semver,pattern={{version}},value=${{ needs.prepare.outputs.new_release_version }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3.6.0
|
||||||
|
- name: set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3.10.0
|
||||||
|
with:
|
||||||
|
config: .github/buildkitd.toml
|
||||||
|
- name: Login to Docker
|
||||||
|
uses: docker/login-action@v3.4.0
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||||
|
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||||
|
- name: Login to GHCR
|
||||||
|
uses: docker/login-action@v3.4.0
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Build and push
|
||||||
|
id: push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: modules
|
||||||
|
file: modules/api/Dockerfile
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
platforms: linux/amd64
|
||||||
|
cache-from: type=gha
|
||||||
|
cache-to: type=gha,mode=max
|
||||||
|
build-args: |
|
||||||
|
VERSION=${{ steps.meta.outputs.version || 'latest' }}
|
||||||
|
|
||||||
unit-tests:
|
unit-tests:
|
||||||
name: Unit tests with coverage
|
name: Unit tests with coverage
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -123,7 +180,7 @@ jobs:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: actions/setup-go@v5.0.2
|
- uses: actions/setup-go@v5.5.0
|
||||||
with:
|
with:
|
||||||
go-version-file: modules/go.work
|
go-version-file: modules/go.work
|
||||||
check-latest: true
|
check-latest: true
|
||||||
|
@ -133,7 +190,7 @@ jobs:
|
||||||
- working-directory: modules/web
|
- working-directory: modules/web
|
||||||
run: yarn
|
run: yarn
|
||||||
- run: PATH=$PATH:$GOPATH/bin make coverage
|
- run: PATH=$PATH:$GOPATH/bin make coverage
|
||||||
- uses: codecov/codecov-action@v4.6.0
|
- uses: codecov/codecov-action@v5.4.2
|
||||||
with:
|
with:
|
||||||
directory: ./.tmp
|
directory: ./.tmp
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
@ -148,8 +205,8 @@ jobs:
|
||||||
# fetch-depth: 0
|
# fetch-depth: 0
|
||||||
# - uses: helm/kind-action@v1.9.0
|
# - uses: helm/kind-action@v1.9.0
|
||||||
# with:
|
# with:
|
||||||
# node_image: kindest/node:v1.30.2
|
# node_image: kindest/node:v1.32.0
|
||||||
# - uses: actions/setup-go@v5.0.2
|
# - uses: actions/setup-go@v5.5.0
|
||||||
# with:
|
# with:
|
||||||
# go-version-file: modules/api/go.mod
|
# go-version-file: modules/api/go.mod
|
||||||
# check-latest: true
|
# check-latest: true
|
||||||
|
|
|
@ -11,28 +11,41 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
|
||||||
|
version: "2"
|
||||||
run:
|
run:
|
||||||
modules-download-mode: readonly
|
modules-download-mode: readonly
|
||||||
allow-parallel-runners: true
|
|
||||||
timeout: 30m
|
|
||||||
issues-exit-code: 1
|
issues-exit-code: 1
|
||||||
tests: true
|
tests: true
|
||||||
|
allow-parallel-runners: true
|
||||||
linters:
|
linters:
|
||||||
disable-all: true
|
default: none
|
||||||
enable:
|
enable:
|
||||||
# default linters
|
|
||||||
- errcheck
|
- errcheck
|
||||||
- gosimple
|
- errorlint
|
||||||
|
- gocyclo
|
||||||
- govet
|
- govet
|
||||||
- ineffassign
|
- ineffassign
|
||||||
- staticcheck
|
|
||||||
- typecheck
|
|
||||||
- unused
|
|
||||||
- gocyclo
|
|
||||||
|
|
||||||
# additional linters
|
|
||||||
- errorlint
|
|
||||||
- errname
|
|
||||||
- goimports
|
|
||||||
- misspell
|
- misspell
|
||||||
|
- staticcheck
|
||||||
|
- unused
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
presets:
|
||||||
|
- comments
|
||||||
|
- common-false-positives
|
||||||
|
- legacy
|
||||||
|
- std-error-handling
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
formatters:
|
||||||
|
enable:
|
||||||
|
- goimports
|
||||||
|
exclusions:
|
||||||
|
generated: lax
|
||||||
|
paths:
|
||||||
|
- third_party$
|
||||||
|
- builtin$
|
||||||
|
- examples$
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: ingress-nginx
|
- name: ingress-nginx
|
||||||
repository: https://kubernetes.github.io/ingress-nginx
|
repository: https://kubernetes.github.io/ingress-nginx
|
||||||
version: 4.10.1
|
version: 4.12.0
|
||||||
- name: cert-manager
|
- name: cert-manager
|
||||||
repository: https://charts.jetstack.io
|
repository: https://charts.jetstack.io
|
||||||
version: v1.14.5
|
version: v1.16.2
|
||||||
- name: metrics-server
|
- name: metrics-server
|
||||||
repository: https://kubernetes-sigs.github.io/metrics-server/
|
repository: https://kubernetes-sigs.github.io/metrics-server/
|
||||||
version: 3.12.1
|
version: 3.12.2
|
||||||
- name: kong
|
- name: kong
|
||||||
repository: https://charts.konghq.com
|
repository: https://charts.konghq.com
|
||||||
version: 2.38.0
|
version: 2.46.0
|
||||||
digest: sha256:ef535931f6d08b3b4b242cba567d0c02a072cf7cf68431f58a0d8d283b3b72b5
|
digest: sha256:fa0fa7ff7e237c3db88016a57704d0f2c9f7dae9ac9b041a32112b6df35f8e23
|
||||||
generated: "2024-06-04T11:32:45.155515532+02:00"
|
generated: "2025-01-10T12:28:39.253786876+01:00"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: kubernetes-dashboard
|
name: kubernetes-dashboard
|
||||||
version: 7.7.0
|
version: 7.13.0
|
||||||
description: General-purpose web UI for Kubernetes clusters
|
description: General-purpose web UI for Kubernetes clusters
|
||||||
keywords:
|
keywords:
|
||||||
- kubernetes
|
- kubernetes
|
||||||
|
@ -32,18 +32,18 @@ kubeVersion: ">=1.21.0-0"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: ingress-nginx
|
- name: ingress-nginx
|
||||||
alias: nginx
|
alias: nginx
|
||||||
version: 4.10.1
|
version: 4.12.0
|
||||||
repository: https://kubernetes.github.io/ingress-nginx
|
repository: https://kubernetes.github.io/ingress-nginx
|
||||||
condition: nginx.enabled
|
condition: nginx.enabled
|
||||||
- name: cert-manager
|
- name: cert-manager
|
||||||
version: v1.14.5
|
version: v1.16.2
|
||||||
repository: https://charts.jetstack.io
|
repository: https://charts.jetstack.io
|
||||||
condition: cert-manager.enabled
|
condition: cert-manager.enabled
|
||||||
- name: metrics-server
|
- name: metrics-server
|
||||||
version: 3.12.1
|
version: 3.12.2
|
||||||
repository: https://kubernetes-sigs.github.io/metrics-server/
|
repository: https://kubernetes-sigs.github.io/metrics-server/
|
||||||
condition: metrics-server.enabled
|
condition: metrics-server.enabled
|
||||||
- name: kong
|
- name: kong
|
||||||
version: 2.38.0
|
version: 2.46.0
|
||||||
repository: https://charts.konghq.com
|
repository: https://charts.konghq.com
|
||||||
condition: kong.enabled
|
condition: kong.enabled
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
Congratulations! You have just installed Kubernetes Dashboard in your cluster.
|
Congratulations! You have just installed Kubernetes Dashboard in your cluster.
|
||||||
{{ if not (.Values.nginx.enabled) }}
|
{{ if not (.Values.nginx.enabled) }}
|
||||||
To access Dashboard run:
|
To access Dashboard run:
|
||||||
kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443
|
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ .Release.Name }}-kong-proxy 8443:443
|
||||||
|
|
||||||
NOTE: In case port-forward command does not work, make sure that kong service name is correct.
|
NOTE: In case port-forward command does not work, make sure that kong service name is correct.
|
||||||
Check the services in Kubernetes Dashboard namespace using:
|
Check the services in Kubernetes Dashboard namespace using:
|
||||||
|
@ -17,7 +17,7 @@ Dashboard will be available at:
|
||||||
|
|
||||||
{{ if and (has "localhost" .Values.app.ingress.hosts) (eq .Values.app.ingress.ingressClassName "internal-nginx") (.Values.nginx.enabled) }}
|
{{ if and (has "localhost" .Values.app.ingress.hosts) (eq .Values.app.ingress.ingressClassName "internal-nginx") (.Values.nginx.enabled) }}
|
||||||
To access Dashboard run:
|
To access Dashboard run:
|
||||||
kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-nginx-controller 8443:443
|
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ .Release.Name }}-nginx-controller 8443:443
|
||||||
|
|
||||||
NOTE: In case port-forward command does not work, make sure that nginx service name is correct.
|
NOTE: In case port-forward command does not work, make sure that nginx service name is correct.
|
||||||
Check the services in Kubernetes Dashboard namespace using:
|
Check the services in Kubernetes Dashboard namespace using:
|
||||||
|
|
|
@ -75,14 +75,14 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.cpu
|
resource: limits.cpu
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.api.containers.resources.limits.memory }}
|
{{- if .Values.api.containers.resources.limits.memory }}
|
||||||
- name: GOMEMLIMIT
|
- name: GOMEMLIMIT
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.memory
|
resource: limits.memory
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- with .Values.api.containers.env }}
|
{{- with .Values.api.containers.env }}
|
||||||
|
|
|
@ -76,14 +76,14 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.cpu
|
resource: limits.cpu
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.auth.containers.resources.limits.memory }}
|
{{- if .Values.auth.containers.resources.limits.memory }}
|
||||||
- name: GOMEMLIMIT
|
- name: GOMEMLIMIT
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.memory
|
resource: limits.memory
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- with .Values.auth.containers.env }}
|
{{- with .Values.auth.containers.env }}
|
||||||
|
|
|
@ -68,14 +68,14 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.cpu
|
resource: limits.cpu
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.metricsScraper.containers.resources.limits.memory }}
|
{{- if .Values.metricsScraper.containers.resources.limits.memory }}
|
||||||
- name: GOMEMLIMIT
|
- name: GOMEMLIMIT
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.memory
|
resource: limits.memory
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- with .Values.metricsScraper.containers.env }}
|
{{- with .Values.metricsScraper.containers.env }}
|
||||||
|
|
|
@ -70,14 +70,14 @@ spec:
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.cpu
|
resource: limits.cpu
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.web.containers.resources.limits.memory }}
|
{{- if .Values.web.containers.resources.limits.memory }}
|
||||||
- name: GOMEMLIMIT
|
- name: GOMEMLIMIT
|
||||||
valueFrom:
|
valueFrom:
|
||||||
resourceFieldRef:
|
resourceFieldRef:
|
||||||
resource: limits.memory
|
resource: limits.memory
|
||||||
divisor: 1
|
divisor: "1"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{- with .Values.web.containers.env }}
|
{{- with .Values.web.containers.env }}
|
||||||
|
|
|
@ -15,6 +15,12 @@
|
||||||
{{- if and .Values.app.ingress.enabled (eq .Values.app.mode "dashboard")}}
|
{{- if and .Values.app.ingress.enabled (eq .Values.app.mode "dashboard")}}
|
||||||
{{- include "kubernetes-dashboard.validate.ingressIssuerScope" $ }}
|
{{- include "kubernetes-dashboard.validate.ingressIssuerScope" $ }}
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the service port to use for the ingress configuration
|
||||||
|
# If TLS is enabled in the ingress configuration, use the TLS service port.
|
||||||
|
# Otherwise, fall back to the HTTP service port.
|
||||||
|
{{- $servicePort := (ternary $.Values.kong.proxy.tls.servicePort $.Values.kong.proxy.http.servicePort $.Values.app.ingress.tls.enabled) }}
|
||||||
|
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
metadata:
|
metadata:
|
||||||
|
@ -73,7 +79,7 @@ spec:
|
||||||
service:
|
service:
|
||||||
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.kong.proxy.tls.servicePort }}
|
number: {{ $servicePort }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
- http:
|
- http:
|
||||||
|
@ -84,6 +90,6 @@ spec:
|
||||||
service:
|
service:
|
||||||
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.kong.proxy.tls.servicePort }}
|
number: {{ $servicePort }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
@ -30,11 +30,19 @@ metadata:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.api.role }}
|
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.api.role }}
|
||||||
spec:
|
spec:
|
||||||
|
type: {{ .Values.api.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- name: {{ .Values.api.role }}
|
{{- range $port := .Values.api.containers.ports }}
|
||||||
{{- with (index .Values.api.containers.ports 0) }}
|
- name: {{ $port.name }}
|
||||||
port: {{ .containerPort }}
|
port: {{ $port.containerPort }}
|
||||||
|
{{ if $port.protocol }}protocol: {{ $port.protocol }}{{- end }}
|
||||||
|
{{ if $port.appProtocol }}appProtocol: {{ $port.appProtocol }}{{- end }}
|
||||||
|
{{ if $port.nodePort }}nodePort: {{ $port.nodePort }}{{- end }}
|
||||||
|
{{ if $port.targetPort }}targetPort: {{ $port.targetPort }}{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{ with .Values.api.service.extraSpec }}
|
||||||
|
{{ . | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.api.role }}
|
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.api.role }}
|
||||||
|
|
|
@ -32,11 +32,19 @@ metadata:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.auth.role }}
|
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.auth.role }}
|
||||||
spec:
|
spec:
|
||||||
|
type: {{ .Values.auth.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- name: {{ .Values.auth.role }}
|
{{- range $port := .Values.auth.containers.ports }}
|
||||||
{{- with (index .Values.auth.containers.ports 0) }}
|
- name: {{ $port.name }}
|
||||||
port: {{ .containerPort }}
|
port: {{ $port.containerPort }}
|
||||||
|
{{ if $port.protocol }}protocol: {{ $port.protocol }}{{- end }}
|
||||||
|
{{ if $port.appProtocol }}appProtocol: {{ $port.appProtocol }}{{- end }}
|
||||||
|
{{ if $port.nodePort }}nodePort: {{ $port.nodePort }}{{- end }}
|
||||||
|
{{ if $port.targetPort }}targetPort: {{ $port.targetPort }}{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{ with .Values.auth.service.extraSpec }}
|
||||||
|
{{ . | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.auth.role }}
|
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.auth.role }}
|
||||||
|
|
|
@ -32,10 +32,20 @@ metadata:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
name: {{ template "kubernetes-dashboard.metrics-scraper.name" . }}
|
name: {{ template "kubernetes-dashboard.metrics-scraper.name" . }}
|
||||||
spec:
|
spec:
|
||||||
|
type: {{ .Values.metricsScraper.service.type }}
|
||||||
ports:
|
ports:
|
||||||
{{- with (index .Values.metricsScraper.containers.ports 0) }}
|
{{- range $port := .Values.metricsScraper.containers.ports }}
|
||||||
- port: {{ .containerPort }}
|
# Name is intentionally not used here as it breaks the connection between API <-> Scraper
|
||||||
|
# Named ports have an issue when trying to connect through in-cluster service proxy.
|
||||||
|
- port: {{ $port.containerPort }}
|
||||||
|
{{ if $port.protocol }}protocol: {{ $port.protocol }}{{- end }}
|
||||||
|
{{ if $port.appProtocol }}appProtocol: {{ $port.appProtocol }}{{- end }}
|
||||||
|
{{ if $port.nodePort }}nodePort: {{ $port.nodePort }}{{- end }}
|
||||||
|
{{ if $port.targetPort }}targetPort: {{ $port.targetPort }}{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{ with .Values.metricsScraper.service.extraSpec }}
|
||||||
|
{{ . | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.metricsScraper.role }}
|
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.metricsScraper.role }}
|
||||||
|
|
|
@ -32,11 +32,19 @@ metadata:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.web.role }}
|
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.web.role }}
|
||||||
spec:
|
spec:
|
||||||
|
type: {{ .Values.web.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- name: {{ .Values.web.role }}
|
{{- range $port := .Values.web.containers.ports }}
|
||||||
{{- with (index .Values.web.containers.ports 0) }}
|
- name: {{ $port.name }}
|
||||||
port: {{ .containerPort }}
|
port: {{ $port.containerPort }}
|
||||||
|
{{ if $port.protocol }}protocol: {{ $port.protocol }}{{- end }}
|
||||||
|
{{ if $port.appProtocol }}appProtocol: {{ $port.appProtocol }}{{- end }}
|
||||||
|
{{ if $port.nodePort }}nodePort: {{ $port.nodePort }}{{- end }}
|
||||||
|
{{ if $port.targetPort }}targetPort: {{ $port.targetPort }}{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{ with .Values.web.service.extraSpec }}
|
||||||
|
{{ . | toYaml | nindent 2 }}
|
||||||
|
{{- end }}
|
||||||
selector:
|
selector:
|
||||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.web.role }}
|
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.web.role }}
|
||||||
|
|
|
@ -23,7 +23,7 @@ app:
|
||||||
pullSecrets: []
|
pullSecrets: []
|
||||||
scheduling:
|
scheduling:
|
||||||
# Node labels for pod assignment
|
# Node labels for pod assignment
|
||||||
# Ref: https://kubernetes.io/docs/user-guide/node-selection/
|
# Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
|
||||||
nodeSelector: {}
|
nodeSelector: {}
|
||||||
security:
|
security:
|
||||||
# Allow overriding csrfKey used by API/Auth containers.
|
# Allow overriding csrfKey used by API/Auth containers.
|
||||||
|
@ -84,6 +84,8 @@ app:
|
||||||
# resourceAutoRefreshTimeInterval: 10
|
# resourceAutoRefreshTimeInterval: 10
|
||||||
# # Hide all access denied warnings in the notification panel
|
# # Hide all access denied warnings in the notification panel
|
||||||
# disableAccessDeniedNotifications: false
|
# disableAccessDeniedNotifications: false
|
||||||
|
# # Hide all namespaces option in namespace selection dropdown to avoid accidental selection in large clusters thus preventing OOM errors
|
||||||
|
# hideAllNamespaces: false
|
||||||
# # Namespace that should be selected by default after logging in.
|
# # Namespace that should be selected by default after logging in.
|
||||||
# defaultNamespace: default
|
# defaultNamespace: default
|
||||||
# # List of namespaces that should be presented to user without namespace list privileges.
|
# # List of namespaces that should be presented to user without namespace list privileges.
|
||||||
|
@ -143,10 +145,13 @@ auth:
|
||||||
role: auth
|
role: auth
|
||||||
image:
|
image:
|
||||||
repository: docker.io/kubernetesui/dashboard-auth
|
repository: docker.io/kubernetesui/dashboard-auth
|
||||||
tag: 1.1.3
|
tag: 1.3.0
|
||||||
scaling:
|
scaling:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
revisionHistoryLimit: 10
|
revisionHistoryLimit: 10
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
extraSpec: ~
|
||||||
containers:
|
containers:
|
||||||
ports:
|
ports:
|
||||||
- name: auth
|
- name: auth
|
||||||
|
@ -182,10 +187,13 @@ api:
|
||||||
role: api
|
role: api
|
||||||
image:
|
image:
|
||||||
repository: docker.io/kubernetesui/dashboard-api
|
repository: docker.io/kubernetesui/dashboard-api
|
||||||
tag: 1.8.1
|
tag: 1.13.0
|
||||||
scaling:
|
scaling:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
revisionHistoryLimit: 10
|
revisionHistoryLimit: 10
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
extraSpec: ~
|
||||||
containers:
|
containers:
|
||||||
ports:
|
ports:
|
||||||
- name: api
|
- name: api
|
||||||
|
@ -239,10 +247,13 @@ web:
|
||||||
role: web
|
role: web
|
||||||
image:
|
image:
|
||||||
repository: docker.io/kubernetesui/dashboard-web
|
repository: docker.io/kubernetesui/dashboard-web
|
||||||
tag: 1.4.0
|
tag: 1.7.0
|
||||||
scaling:
|
scaling:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
revisionHistoryLimit: 10
|
revisionHistoryLimit: 10
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
extraSpec: ~
|
||||||
containers:
|
containers:
|
||||||
ports:
|
ports:
|
||||||
- name: web
|
- name: web
|
||||||
|
@ -299,10 +310,13 @@ metricsScraper:
|
||||||
role: metrics-scraper
|
role: metrics-scraper
|
||||||
image:
|
image:
|
||||||
repository: docker.io/kubernetesui/dashboard-metrics-scraper
|
repository: docker.io/kubernetesui/dashboard-metrics-scraper
|
||||||
tag: 1.1.1
|
tag: 1.2.2
|
||||||
scaling:
|
scaling:
|
||||||
replicas: 1
|
replicas: 1
|
||||||
revisionHistoryLimit: 10
|
revisionHistoryLimit: 10
|
||||||
|
service:
|
||||||
|
type: ClusterIP
|
||||||
|
extraSpec: ~
|
||||||
containers:
|
containers:
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 8000
|
- containerPort: 8000
|
||||||
|
|
|
@ -3,65 +3,81 @@
|
||||||
Dashboard containers accept multiple arguments that can be used to customize them.
|
Dashboard containers accept multiple arguments that can be used to customize them.
|
||||||
|
|
||||||
## API module arguments
|
## API module arguments
|
||||||
|
|
||||||
| Argument name | Default value | Description |
|
| Argument name | Default value | Description |
|
||||||
|------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| insecure-port | 9000 | The port to listen to for incoming HTTP requests. |
|
| disable-csrf-protection | false | Allows disabling CSRF protection. |
|
||||||
| port | 9001 | The secure port to listen to for incoming HTTPS requests. |
|
| act-as-proxy | false | Forces dashboard to work in full proxy mode, meaning that any internal in-cluster client calls are disabled. |
|
||||||
|
| openapi-enabled | false | Enables OpenAPI v2 endpoint user '/apidocs.json'. Used to autogenerate OpenAPI/GraphQL schema. |
|
||||||
|
| profiler | false | Enables pprof handler. By default it will be exposed on localhost:8070 under '/debug/pprof'. |
|
||||||
|
| prometheus-enabled | false | Enables prometheus metrics handler. By default it will be exposed on localhost:8080 under '/metrics'. |
|
||||||
|
| apiserver-skip-tls-verify | false | Enable if connection with remote Kubernetes API should skip TLS verify. |
|
||||||
|
| auto-generate-certificates | false | When set to true, Dashboard will automatically generate certificates used to serve HTTPS. |
|
||||||
|
| cache-enabled | true | Whether the client cache should be enabled or not. |
|
||||||
|
| cluster-context-enabled | false | Whether multi-cluster cache context support should be enabled or not. |
|
||||||
|
| cache-size | 1000 | Max number of cache entries to hold at once. |
|
||||||
|
| cache-ttl | 10m | Time to live of each cache entry. |
|
||||||
|
| cache-refresh-debounce | 5s | Minimal time between cache refreshes in background. |
|
||||||
|
| insecure-port | 8000 | The port to listen to for incoming HTTP requests. |
|
||||||
|
| port | 8001 | The secure port to listen to for incoming HTTPS requests. |
|
||||||
|
| metric-client-check-period | 30 | Time in seconds that defines how often configured metric client health check should be run. |
|
||||||
| insecure-bind-address | 127.0.0.1 | The IP address on which to serve the `--insecure-port` (set to 127.0.0.1 for loopback only). |
|
| insecure-bind-address | 127.0.0.1 | The IP address on which to serve the `--insecure-port` (set to 127.0.0.1 for loopback only). |
|
||||||
| bind-address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
| bind-address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
||||||
|
| token-exchange-endpoint | - | Endpoint used when `--cluster-context-enabled=true` to exchange auth token for the unique context identifier. |
|
||||||
| default-cert-dir | /certs | Directory path containing `--tls-cert-file` and `--tls-key-file` files. Used also when auto-generating certificates flag is set. Relative to the container, not the host. |
|
| default-cert-dir | /certs | Directory path containing `--tls-cert-file` and `--tls-key-file` files. Used also when auto-generating certificates flag is set. Relative to the container, not the host. |
|
||||||
| tls-cert-file | - | File containing the default x509 Certificate for HTTPS. |
|
| tls-cert-file | - | File containing the default x509 Certificate for HTTPS. |
|
||||||
| tls-key-file | - | File containing the default x509 private key matching --tls-cert-file. |
|
| tls-key-file | - | File containing the default x509 private key matching --tls-cert-file. |
|
||||||
| auto-generate-certificates | false | When set to true, Dashboard will automatically generate certificates used to serve HTTPS. |
|
|
||||||
| apiserver-host | - | The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and local discovery is attempted. |
|
| apiserver-host | - | The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and local discovery is attempted. |
|
||||||
| sidecar-host | - | The address of the Sidecar Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8000. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and service proxy will be used. |
|
|
||||||
| metrics-provider | sidecar | Select provider type for metrics. 'none' will not check metrics. |
|
| metrics-provider | sidecar | Select provider type for metrics. 'none' will not check metrics. |
|
||||||
| metric-client-check-period | 30 | Time in seconds that defines how often configured metric client health check should be run. |
|
| sidecar-host | - | The address of the Sidecar Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8000. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and service proxy will be used. |
|
||||||
| kubeconfig | - | Path to kubeconfig file with control plane location information. |
|
| kubeconfig | - | Path to kubeconfig file with control plane location information. |
|
||||||
| namespace | kubernetes-dashboard | Namespace to use when accessing Dashboard specific resources, i.e. metrics scraper service. |
|
| namespace | kubernetes-dashboard | Namespace to use when accessing Dashboard specific resources, i.e. metrics scraper service. |
|
||||||
| metrics-scraper-service-name | kubernetes-dashboard-metrics-scraper | Name of the dashboard metrics scraper service. |
|
| metrics-scraper-service-name | kubernetes-dashboard-metrics-scraper | Name of the dashboard metrics scraper service. |
|
||||||
| disable-csrf-protection | false | Allows disabling CSRF protection. |
|
|
||||||
| csrf-key | - | Base64 encoded random 256 bytes key. Can be loaded from 'CSRF_KEY' environment variable. |
|
| csrf-key | - | Base64 encoded random 256 bytes key. Can be loaded from 'CSRF_KEY' environment variable. |
|
||||||
| act-as-proxy | false | Forces dashboard to work in full proxy mode, meaning that any in-cluster calls are disabled. |
|
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
|
||||||
|
|
||||||
## Auth module arguments
|
## Auth module arguments
|
||||||
| Argument name | Default value | Description |
|
|
||||||
|---------------|---------------|------------------------------------------------------------------------------------------|
|
| Argument name | Default value | Description |
|
||||||
| port | 8000 | The secure port to listen to for incoming HTTPS requests. |
|
|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
| apiserver-skip-tls-verify | false | Enable if connection with remote Kubernetes API should skip TLS verify. |
|
||||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
| port | 8000 | The secure port to listen to for incoming HTTPS requests. |
|
||||||
| csrf-key | - | Base64 encoded random 256 bytes key. Can be loaded from 'CSRF_KEY' environment variable. |
|
| address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
||||||
| v | 1 | Number for the log level verbosity (default 1) | |# Metrics scraper module arguments
|
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||||
|
| apiserver-host | - | The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and local discovery is attempted. |
|
||||||
|
| csrf-key | - | Base64 encoded random 256 bytes key. Can be loaded from 'CSRF_KEY' environment variable. |
|
||||||
|
| v | 1 | Number for the log level verbosity (default 1) | |# Metrics scraper module arguments
|
||||||
|
|
||||||
## Metrics scraper module arguments
|
## Metrics scraper module arguments
|
||||||
| Argument name | Default value | Description |
|
|
||||||
|-------------------|-----------------|------------------------------------------------------------------------------|
|
| Argument name | Default value | Description |
|
||||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
|-------------------|-----------------|---------------------------------------------------------------------------|
|
||||||
| db-file | /tmp/metrics.db | What file to use as a SQLite3 database. |
|
| metric-resolution | 1m | The resolution at which dashboard-metrics-scraper will poll metrics. |
|
||||||
| metric-resolution | 1m | The resolution at which dashboard-metrics-scraper will poll metrics. |
|
| metric-duration | 15m | The duration after which metrics are purged from the database. |
|
||||||
| metric-duration | 15m | The duration after which metrics are purged from the database. |
|
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||||
| logtostderr | true | Log to standard error. |
|
| db-file | /tmp/metrics.db | What file to use as a SQLite3 database. |
|
||||||
| namespace | - | The namespace to use for all metric calls. When provided, skip node metrics. |
|
| namespaces | - | Namespaces to use for all metric calls. When provided, skip node metrics. |
|
||||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||||
|
|
||||||
## Web module arguments
|
## Web module arguments
|
||||||
|
|
||||||
| Argument name | Default value | Description |
|
| Argument name | Default value | Description |
|
||||||
|----------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|----------------------------|-------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| auto-generate-certificates | false | When set to true, Dashboard will automatically generate certificates used to serve HTTPS. |
|
||||||
| insecure-port | 8000 | The port to listen to for incoming HTTP requests. |
|
| insecure-port | 8000 | The port to listen to for incoming HTTP requests. |
|
||||||
| port | 8001 | The secure port to listen to for incoming HTTPS requests. |
|
| port | 8001 | The secure port to listen to for incoming HTTPS requests. |
|
||||||
| insecure-bind-address | 127.0.0.1 | The IP address on which to serve the `--insecure-port` (set to 127.0.0.1 for loopback only). |
|
| insecure-bind-address | 127.0.0.1 | The IP address on which to serve the `--insecure-port` (set to 127.0.0.1 for loopback only). |
|
||||||
| bind-address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
| bind-address | 0.0.0.0 | The IP address on which to serve the `--port` (set to 0.0.0.0 for all interfaces). |
|
||||||
|
| namespace | kube-system | Namespace to use when creating Dashboard specific resources, i.e. settings config map. |
|
||||||
| default-cert-dir | /certs | Directory path containing `--tls-cert-file` and `--tls-key-file` files. Used also when auto-generating certificates flag is set. Relative to the container, not the host. |
|
| default-cert-dir | /certs | Directory path containing `--tls-cert-file` and `--tls-key-file` files. Used also when auto-generating certificates flag is set. Relative to the container, not the host. |
|
||||||
| tls-cert-file | - | File containing the default x509 Certificate for HTTPS. |
|
| tls-cert-file | - | File containing the default x509 Certificate for HTTPS. |
|
||||||
| tls-key-file | - | File containing the default x509 private key matching --tls-cert-file. |
|
| tls-key-file | - | File containing the default x509 private key matching --tls-cert-file. |
|
||||||
| auto-generate-certificates | false | When set to true, Dashboard will automatically generate certificates used to serve HTTPS. |
|
|
||||||
| locale-config | ./locale_conf.json | File containing the configuration of locales. |
|
|
||||||
| namespace | kube-system | Namespace to use when creating Dashboard specific resources, i.e. settings config map. |
|
|
||||||
| settings-config-map-name | kubernetes-dashboard-settings | Name of a config map, that stores settings. |
|
| settings-config-map-name | kubernetes-dashboard-settings | Name of a config map, that stores settings. |
|
||||||
| system-banner | - | When non-empty displays message to Dashboard users. Accepts simple HTML tags. |
|
| system-banner | - | When non-empty displays message to Dashboard users. Accepts simple HTML tags. |
|
||||||
| system-banner-severity | INFO | Severity of system banner. Should be one of `INFO\|WARNING\|ERROR`. |
|
| system-banner-severity | INFO | Severity of system banner. Should be one of `INFO\|WARNING\|ERROR`. |
|
||||||
|
| locale-config | ./locale_conf.json | File containing the configuration of locales. |
|
||||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||||
|
|
||||||
----
|
----
|
||||||
_Copyright 2019 [The Kubernetes Dashboard Authors](https://github.com/kubernetes/dashboard/graphs/contributors)_
|
_Copyright 2019 [The Kubernetes Dashboard Authors](https://github.com/kubernetes/dashboard/graphs/contributors)_
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
This guide is for anyone interested in contributing design work themselves or contributing in a way that is impacted by design.
|
This guide is for anyone interested in contributing design work themselves or contributing in a way that is impacted by design.
|
||||||
|
|
||||||
## Resources:
|
## Resources:
|
||||||
* Get in touch with Dan Romlein (@danielromlein) for general Dashboard UX questions or suggestions of tasks that need design work.
|
|
||||||
* Follow the [Getting started guide](https://github.com/kubernetes/dashboard/wiki/Getting-started) to get the most recent version of Dashboard up and running.
|
* Follow the [Getting started guide](https://github.com/kubernetes/dashboard/wiki/Getting-started) to get the most recent version of Dashboard up and running.
|
||||||
* Dashboard is based on Google’s [Material](https://material.io/guidelines/) design system. Refer to their spec for guidance.
|
* Dashboard is based on Google’s [Material](https://material.io/guidelines/) design system. Refer to their spec for guidance.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
# Table of Contents
|
||||||
|
- [Motivation](#motivation)
|
||||||
|
- [Goals](#goals)
|
||||||
|
- [Non-Goals](#non-goals)
|
||||||
|
- [Terminology](#terminology)
|
||||||
|
- [Proposal](#proposal)
|
||||||
|
- [Design](#design)
|
||||||
|
- [Implementation](#implementation)
|
||||||
|
|
||||||
|
## Motivation
|
||||||
|
The Kubernetes Dashboard has been around for a long time now, and one of its pain points have always been the performance and responsiveness when running in clusters with a large number of resources. Given that, we have been thinking about implementing a proper API caching solution to enhance overall responsiveness and user experience. As clusters grow in size and complexity, users often face latency issues when interacting with the Dashboard, which can lead to inefficiencies in managing and troubleshooting applications. By implementing a proper caching solution, we can significantly reduce the time it takes to retrieve resource data, decrease peak memory usage and optimize overall resource consumption, thereby minimizing delays and improving the fluidity of the user interface.
|
||||||
|
|
||||||
|
### Goals
|
||||||
|
The primary goals of implementing the API caching solution are to:
|
||||||
|
- **Reduce Latency**: Minimize the time required to retrieve data from the Dashboard API during consecutive requests, enabling faster access to information.
|
||||||
|
- **Enhance User Experience**: Provide a smoother, more responsive interface for users managing complex clusters.
|
||||||
|
- **Optimize Resource Utilization**: Decrease the pressure on the Kubernetes API server by caching frequently accessed data, thus improving overall cluster performance.
|
||||||
|
- **Support Scalability**: Ensure the solution can accommodate clusters of varying sizes and complexities without degrading performance. Cache should be running in multi-cluster as well as in the single-cluster setup.
|
||||||
|
- **Configurability**: Provide opt-out and other configuration options.
|
||||||
|
|
||||||
|
### Non-Goals
|
||||||
|
This proposal does not aim to:
|
||||||
|
|
||||||
|
- **Replace Existing API Functionality**: The caching solution will transparently work with, not replace, the existing API endpoints and interactions.
|
||||||
|
- **Introduce Complexity for Users**: The implementation should remain transparent to users, avoiding any additional steps or configurations.
|
||||||
|
- **Cover All Resource Types Equally**: While the caching solution will enhance responsiveness, it may initially focus on the most frequently accessed resource types rather than attempting to cache every possible resource.
|
||||||
|
|
||||||
|
### Terminology
|
||||||
|
- **API Caching**: The process of storing responses from API requests temporarily to reduce the need for repeated fetching of the same data.
|
||||||
|
- **Resource**: An entity within Kubernetes, such as pods, services, deployments, etc., that users manage through the Dashboard.
|
||||||
|
- **Latency**: The time delay between a user action and the corresponding response from the system.
|
||||||
|
|
||||||
|
## Proposal
|
||||||
|
The proposed solution involves implementing a caching layer within the Kubernetes Dashboard that stores a configurable number of API responses for a configurable duration. This caching layer will hook into Kubernetes client interfaces and serve cached data when available, falling back to the API server only when necessary. The solution will leverage techniques such as time and cost-based expiration and cache invalidation strategies to ensure data freshness while balancing performance.
|
||||||
|
|
||||||
|
In general, it will resemble the "cache-and-network" type of caching due to the nature of Dashboard auth layer. Since Dashboard does not require any permissions on its own, it has to rely on the user permissions and the only time when it can act as a user is the time from receiving a request to sending a response. Such an architecture requires an on-the-fly client creation as well as background cache updates.
|
||||||
|
|
||||||
|
To ensure that cached data will not be served to unauthorized entities, every time before API returns data from the cache, it will first create a Self Subject Access Review request to the API server to validate user permissions.
|
||||||
|
|
||||||
|
It is especially important in a multi-cluster scenarios where Dashboard API is used to access multiple clusters. To avoid the situation where path stored in cache could be served from the wrong cluster context, multi-cluster cache context needs to have a way to exchange user authorization token for a unique context ID and it has to be a part of the cache key.
|
||||||
|
|
||||||
|
Cache key should consist of the below fields:
|
||||||
|
- **Kind**: resource kind
|
||||||
|
- **Namespace**: optional namespace name
|
||||||
|
- **List Options**: `v1.ListOptions` should also be part of the key to ensure that filtered API requests are stored under a separate cache key
|
||||||
|
- **Context ID**: optional context (cluster) identifier, used only in multi-context caching, controlled by dedicated argument
|
||||||
|
|
||||||
|
SHA should be created based on the above key structure and used as an internal cache key.
|
||||||
|
|
||||||
|
## Design
|
||||||
|
These sequence diagrams show simplified way of how cache works.
|
||||||
|
|
||||||
|
### Standard Caching
|
||||||
|

|
||||||
|
|
||||||
|
1. User requests to see a cached resource view
|
||||||
|
2. API checks if unique key generated based on the request has a corresponding value in the cache
|
||||||
|
1. In case value is not cached, return the data directly from K8S API and cache it.
|
||||||
|
2. In case value is cached, create a Self Subject Access Review to check user permissions, return cached data and in background request latest data from K8S API to update cache.
|
||||||
|
|
||||||
|
### Multi-Context Caching
|
||||||
|

|
||||||
|
|
||||||
|
The flow is very similar to the standard caching with the difference being that provided user authorization token has to be able to be exchanged for the unique context ID using configured `token-exchange-endpoint`. It is then used to create unique cache key.
|
||||||
|
|
||||||
|
## Implementation
|
||||||
|
Cache is implemented with the help of [Theine](Yiling-J/theine-go) package. It provides in-memory cache that has good performance, supports generics and keeps its API simple.
|
||||||
|
|
||||||
|
Cache is a global variable initialized during application startup. It maps internal key SHAs to the resource lists.
|
||||||
|
|
||||||
|
It can be configured via the following arguments:
|
||||||
|
|
||||||
|
- `cache-enabled` - Enables the cache. Enabled by default.
|
||||||
|
- `cache-size` - Maximum number of items in the cache. Set to 1000 by default.
|
||||||
|
- `cache-ttl` - Cache entry time-to-live. Set to 10 minutes by default.
|
||||||
|
- `cache-refresh-debounce` - Minimal time that has to pass between consecutive cache refreshes in the background. Set to 5 seconds by default.
|
||||||
|
- `cluster-context-enabled` - Enables multi-context cache. Disabled by default. Requires `token-exchange-endpoint` to be set if enabled.
|
||||||
|
- `token-exchange-endpoint` - Endpoint used when multi-context cache is enabled. It exchanges tokens for a context identifiers. It has to be HTTP(s) `GET` that returns raw string with context identifier and accepts `Authorization: Bearer <token>` header.
|
||||||
|
|
||||||
|
Cache package provides following interface:
|
||||||
|
|
||||||
|
- `Get` - fetches item from the cache.
|
||||||
|
- `Set` - stores item in the cache.
|
||||||
|
- `DefferedLoad` - updates cache in the background. Used after cache is read to refresh items.
|
||||||
|
- `SyncedLoad` - initializes the cache ensuring that there will be no concurrent calls to the Kubernetes API for the same resources.
|
||||||
|
|
||||||
|
In order to minimize the amount of code, we have created custom interfaces similar to the `client-go` interfaces where we could override only a single `List` method and still use their generic `client.Interface`. This way our internal implementation and usage of kubernetes client did not have to change at all and we were able to inject cached client globally.
|
||||||
|
|
||||||
|
The initial implementation supports caching of the following resources:
|
||||||
|
1. Core
|
||||||
|
1. Pod
|
||||||
|
2. Node
|
||||||
|
3. ConfigMap
|
||||||
|
4. Secret
|
||||||
|
5. Namespace
|
||||||
|
6. PVC
|
||||||
|
7. PV
|
||||||
|
2. Extensions
|
||||||
|
1. Custom Resource Definitions
|
||||||
|
|
||||||
|
Whole cache implementation lives under [modules/common/client/cache](../../modules/common/client/cache).
|
||||||
|
- **Generic ResourceLister**: [resourcelister.go](../../modules/common/client/cache/client/common/resourcelister.go)
|
||||||
|
- **Core Client**: [core.go](../../modules/common/client/cache/client/core/core.go)
|
||||||
|
- **Extensions Client**: [extensions.go](../../modules/common/client/cache/client/extensions/extensions.go)
|
Binary file not shown.
After Width: | Height: | Size: 62 KiB |
Binary file not shown.
After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 72 KiB |
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
|
@ -70,7 +70,7 @@ type: kubernetes.io/service-account-token
|
||||||
After Secret is created, we can execute the following command to get the token which is saved in the Secret:
|
After Secret is created, we can execute the following command to get the token which is saved in the Secret:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath={".data.token"} | base64 -d
|
kubectl get secret admin-user -n kubernetes-dashboard -o jsonpath="{.data.token}" | base64 -d
|
||||||
```
|
```
|
||||||
|
|
||||||
Check [Kubernetes docs](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-long-lived-api-token-for-a-serviceaccount) for more information about long-lived API tokens for a ServiceAccount.
|
Check [Kubernetes docs](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-a-long-lived-api-token-for-a-serviceaccount) for more information about long-lived API tokens for a ServiceAccount.
|
||||||
|
|
|
@ -54,6 +54,7 @@ services:
|
||||||
command:
|
command:
|
||||||
--kubeconfig=${KUBECONFIG:?}
|
--kubeconfig=${KUBECONFIG:?}
|
||||||
--sidecar-host=${SIDECAR_HOST:?}
|
--sidecar-host=${SIDECAR_HOST:?}
|
||||||
|
--v=4
|
||||||
volumes:
|
volumes:
|
||||||
- ${PWD}/modules/common:/workspace/common # Required - Common dir watched by AIR
|
- ${PWD}/modules/common:/workspace/common # Required - Common dir watched by AIR
|
||||||
- ${PWD}/modules/api/pkg:/workspace/api/pkg # Required - Source dir watched by AIR
|
- ${PWD}/modules/api/pkg:/workspace/api/pkg # Required - Source dir watched by AIR
|
||||||
|
|
|
@ -21,7 +21,7 @@ DOCKER_COMPOSE_DEV_PATH := $(DOCKER_DIRECTORY)/dev.compose.yml
|
||||||
TMP_DIRECTORY := $(ROOT_DIRECTORY)/.tmp
|
TMP_DIRECTORY := $(ROOT_DIRECTORY)/.tmp
|
||||||
# Kind
|
# Kind
|
||||||
KIND_CLUSTER_NAME := kubernetes-dashboard
|
KIND_CLUSTER_NAME := kubernetes-dashboard
|
||||||
KIND_CLUSTER_VERSION := 1.29.0
|
KIND_CLUSTER_VERSION := 1.32.0
|
||||||
KIND_CLUSTER_IMAGE := docker.io/kindest/node:v${KIND_CLUSTER_VERSION}
|
KIND_CLUSTER_IMAGE := docker.io/kindest/node:v${KIND_CLUSTER_VERSION}
|
||||||
KIND_CLUSTER_INTERNAL_KUBECONFIG_PATH := $(TMP_DIRECTORY)/kubeconfig
|
KIND_CLUSTER_INTERNAL_KUBECONFIG_PATH := $(TMP_DIRECTORY)/kubeconfig
|
||||||
KIND_CLUSTER_KUBECONFIG_CONTEXT := kind-$(KIND_CLUSTER_NAME)
|
KIND_CLUSTER_KUBECONFIG_CONTEXT := kind-$(KIND_CLUSTER_NAME)
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
FROM alpine:3.19 as user
|
FROM alpine:3.21 AS user
|
||||||
|
|
||||||
ENV USER=nonroot
|
ENV USER=nonroot
|
||||||
ENV UID=10001
|
ENV UID=10001
|
||||||
|
@ -27,7 +27,7 @@ RUN adduser \
|
||||||
--uid "${UID}" \
|
--uid "${UID}" \
|
||||||
"${USER}"
|
"${USER}"
|
||||||
|
|
||||||
FROM golang:1.23-alpine3.19 as builder
|
FROM golang:1.23-alpine3.21 AS builder
|
||||||
|
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
|
@ -58,7 +58,7 @@ RUN echo ${VERSION}
|
||||||
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags="-s -w -X k8s.io/dashboard/api/pkg/environment.Version=${VERSION}" -o dashboard-api .
|
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -trimpath -ldflags="-s -w -X k8s.io/dashboard/api/pkg/environment.Version=${VERSION}" -o dashboard-api .
|
||||||
|
|
||||||
# Scratch can be used as the base image because the binary is compiled to include all dependencies.
|
# Scratch can be used as the base image because the binary is compiled to include all dependencies.
|
||||||
FROM scratch as final
|
FROM scratch AS final
|
||||||
|
|
||||||
COPY --from=builder /workspace/api/dashboard-api /dashboard-api
|
COPY --from=builder /workspace/api/dashboard-api /dashboard-api
|
||||||
|
|
||||||
|
|
|
@ -14,11 +14,11 @@
|
||||||
|
|
||||||
# ! Context expected to be set to "modules" dir !
|
# ! Context expected to be set to "modules" dir !
|
||||||
|
|
||||||
FROM golang:1.23-alpine3.19 as AIR
|
FROM golang:1.23-alpine3.21 AS AIR
|
||||||
|
|
||||||
RUN go install github.com/air-verse/air@latest
|
RUN go install github.com/air-verse/air@latest
|
||||||
|
|
||||||
FROM golang:1.23-alpine3.19
|
FROM golang:1.23-alpine3.21
|
||||||
|
|
||||||
# Copy air binary
|
# Copy air binary
|
||||||
COPY --from=AIR $GOPATH/bin/air $GOPATH/bin/air
|
COPY --from=AIR $GOPATH/bin/air $GOPATH/bin/air
|
||||||
|
|
|
@ -4,17 +4,18 @@ go 1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/distribution/reference v0.6.0
|
github.com/distribution/reference v0.6.0
|
||||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2
|
github.com/emicklei/go-restful-openapi/v2 v2.11.0
|
||||||
github.com/emicklei/go-restful/v3 v3.12.1
|
github.com/emicklei/go-restful/v3 v3.12.1
|
||||||
github.com/go-openapi/spec v0.21.0
|
github.com/go-openapi/spec v0.21.0
|
||||||
github.com/prometheus/client_golang v1.20.4
|
github.com/prometheus/client_golang v1.20.5
|
||||||
|
github.com/samber/lo v1.47.0
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
golang.org/x/net v0.30.0
|
golang.org/x/net v0.40.0
|
||||||
gopkg.in/igm/sockjs-go.v2 v2.1.0
|
gopkg.in/igm/sockjs-go.v2 v2.1.0
|
||||||
k8s.io/api v0.31.1
|
k8s.io/api v0.32.0
|
||||||
k8s.io/apiextensions-apiserver v0.31.1
|
k8s.io/apiextensions-apiserver v0.32.0
|
||||||
k8s.io/apimachinery v0.31.1
|
k8s.io/apimachinery v0.32.0
|
||||||
k8s.io/client-go v0.31.1
|
k8s.io/client-go v0.32.0
|
||||||
k8s.io/dashboard/certificates v0.0.0-00010101000000-000000000000
|
k8s.io/dashboard/certificates v0.0.0-00010101000000-000000000000
|
||||||
k8s.io/dashboard/client v0.0.0-00010101000000-000000000000
|
k8s.io/dashboard/client v0.0.0-00010101000000-000000000000
|
||||||
k8s.io/dashboard/csrf v0.0.0-00010101000000-000000000000
|
k8s.io/dashboard/csrf v0.0.0-00010101000000-000000000000
|
||||||
|
@ -22,100 +23,100 @@ require (
|
||||||
k8s.io/dashboard/helpers v0.0.0-00010101000000-000000000000
|
k8s.io/dashboard/helpers v0.0.0-00010101000000-000000000000
|
||||||
k8s.io/dashboard/types v0.0.0-00010101000000-000000000000
|
k8s.io/dashboard/types v0.0.0-00010101000000-000000000000
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
k8s.io/kubectl v0.31.1
|
k8s.io/kubectl v0.32.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||||
|
github.com/Yiling-J/theine-go v0.6.0 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||||
github.com/bytedance/sonic v1.11.6 // indirect
|
github.com/bytedance/sonic v1.12.7 // indirect
|
||||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
github.com/bytedance/sonic/loader v0.2.2 // indirect
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
github.com/chai2010/gettext-go v1.0.3 // indirect
|
||||||
github.com/cloudwego/base64x v0.1.4 // indirect
|
github.com/cloudwego/base64x v0.1.4 // indirect
|
||||||
github.com/cloudwego/iasm v0.2.0 // indirect
|
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
github.com/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||||
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||||
github.com/gin-gonic/gin v1.10.0 // indirect
|
github.com/gin-gonic/gin v1.10.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.5.1 // indirect
|
||||||
github.com/go-logr/logr v1.4.2 // indirect
|
github.com/go-logr/logr v1.4.2 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
github.com/go-openapi/jsonpointer v0.21.0 // indirect
|
||||||
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
github.com/go-openapi/jsonreference v0.21.0 // indirect
|
||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||||
github.com/gobuffalo/flect v1.0.3 // indirect
|
github.com/gobuffalo/flect v1.0.3 // indirect
|
||||||
github.com/goccy/go-json v0.10.2 // indirect
|
github.com/goccy/go-json v0.10.4 // indirect
|
||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/btree v1.0.1 // indirect
|
github.com/google/btree v1.1.3 // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.9 // indirect
|
||||||
github.com/google/go-cmp v0.6.0 // indirect
|
github.com/google/go-cmp v0.6.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.0 // indirect
|
github.com/gorilla/websocket v1.5.3 // indirect
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||||
github.com/imdario/mergo v0.3.16 // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.9 // indirect
|
github.com/klauspost/compress v1.17.11 // indirect
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.9.0 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||||
github.com/moby/spdystream v0.4.0 // indirect
|
github.com/moby/spdystream v0.5.0 // indirect
|
||||||
github.com/moby/term v0.5.0 // indirect
|
github.com/moby/term v0.5.2 // indirect
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||||
github.com/pkg/errors v0.9.1 // indirect
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.61.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
|
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||||
github.com/samber/lo v1.47.0 // indirect
|
|
||||||
github.com/spf13/cobra v1.8.1 // indirect
|
github.com/spf13/cobra v1.8.1 // indirect
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xlab/treeprint v1.2.0 // indirect
|
github.com/xlab/treeprint v1.2.0 // indirect
|
||||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||||
golang.org/x/arch v0.8.0 // indirect
|
golang.org/x/arch v0.13.0 // indirect
|
||||||
golang.org/x/crypto v0.28.0 // indirect
|
golang.org/x/crypto v0.38.0 // indirect
|
||||||
golang.org/x/oauth2 v0.21.0 // indirect
|
golang.org/x/oauth2 v0.25.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.14.0 // indirect
|
||||||
golang.org/x/sys v0.26.0 // indirect
|
golang.org/x/sys v0.33.0 // indirect
|
||||||
golang.org/x/term v0.25.0 // indirect
|
golang.org/x/term v0.32.0 // indirect
|
||||||
golang.org/x/text v0.19.0 // indirect
|
golang.org/x/text v0.25.0 // indirect
|
||||||
golang.org/x/time v0.5.0 // indirect
|
golang.org/x/time v0.9.0 // indirect
|
||||||
google.golang.org/protobuf v1.34.2 // indirect
|
golang.org/x/tools v0.29.0 // indirect
|
||||||
|
google.golang.org/protobuf v1.36.2 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/cli-runtime v0.31.1 // indirect
|
k8s.io/cli-runtime v0.32.0 // indirect
|
||||||
k8s.io/component-base v0.31.1 // indirect
|
k8s.io/component-base v0.32.0 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||||
sigs.k8s.io/kustomize/api v0.17.2 // indirect
|
sigs.k8s.io/kustomize/api v0.18.0 // indirect
|
||||||
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
|
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,26 @@
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
|
||||||
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/Yiling-J/theine-go v0.6.0 h1:jv7V/tcD6ijL0T4kfbJDKP81TCZBkoriNTPSqwivWuY=
|
||||||
|
github.com/Yiling-J/theine-go v0.6.0/go.mod h1:mdch1vjgGWd7s3rWKvY+MF5InRLfRv/CWVI9RVNQ8wY=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
|
||||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
|
||||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
|
||||||
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
|
|
||||||
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/bytedance/sonic/loader v0.2.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o=
|
||||||
|
github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
|
github.com/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
|
||||||
github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
||||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
|
||||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
|
||||||
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
|
||||||
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
|
||||||
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
|
|
||||||
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
@ -37,25 +32,25 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2 h1:RfxWvGmASIwVoZIEncvXLi5HxYQ0S8rNBkPresDMt1c=
|
github.com/emicklei/go-restful-openapi/v2 v2.11.0 h1:Ur+yGxoOH/7KRmcj/UoMFqC3VeNc9VOe+/XidumxTvk=
|
||||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2/go.mod h1:4CTuOXHFg3jkvCpnXN+Wkw5prVUnP8hIACssJTYorWo=
|
github.com/emicklei/go-restful-openapi/v2 v2.11.0/go.mod h1:4CTuOXHFg3jkvCpnXN+Wkw5prVUnP8hIACssJTYorWo=
|
||||||
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||||
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
|
||||||
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
@ -78,57 +73,39 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o
|
||||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
github.com/go-playground/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||||
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
||||||
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
||||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
|
||||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
|
||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
|
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4=
|
|
||||||
github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
|
@ -137,11 +114,11 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
@ -159,16 +136,16 @@ github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||||
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
|
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||||
github.com/moby/spdystream v0.4.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||||
github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
|
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||||
github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
|
@ -181,14 +158,14 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8m
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus=
|
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/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||||
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
|
||||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
|
||||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
|
@ -196,17 +173,16 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
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/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
github.com/prometheus/client_golang v1.20.4/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
||||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
github.com/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||||
|
@ -229,8 +205,8 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||||
|
@ -241,98 +217,63 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
||||||
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
|
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
|
||||||
|
github.com/zeebo/xxh3 v1.0.2 h1:xZmwmqxHZA8AI603jOQ0tMqmBr9lPeFwGg6d+xy9DC0=
|
||||||
|
github.com/zeebo/xxh3 v1.0.2/go.mod h1:5NWz9Sef7zIDm2JHfFlcQvNekmcEl9ekUZQQKCYaDcA=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
|
||||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||||
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
|
||||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
|
||||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
|
||||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
|
||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
|
||||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
|
||||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
|
||||||
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
|
||||||
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@ -345,44 +286,39 @@ gopkg.in/igm/sockjs-go.v2 v2.1.0/go.mod h1:9l1o9p5TJvh2l+Q0EGE8USVB69QPfcvI7fR0H
|
||||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
|
||||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
|
||||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
|
||||||
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
|
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
|
||||||
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
|
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
k8s.io/cli-runtime v0.32.0 h1:dP+OZqs7zHPpGQMCGAhectbHU2SNCuZtIimRKTv2T1c=
|
||||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
k8s.io/cli-runtime v0.32.0/go.mod h1:Mai8ht2+esoDRK5hr861KRy6z0zHsSTYttNVJXgP3YQ=
|
||||||
k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk=
|
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
|
||||||
k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U=
|
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
|
||||||
k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
|
k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
|
||||||
k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
|
k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
|
||||||
k8s.io/component-base v0.31.1 h1:UpOepcrX3rQ3ab5NB6g5iP0tvsgJWzxTyAo20sgYSy8=
|
|
||||||
k8s.io/component-base v0.31.1/go.mod h1:WGeaw7t/kTsqpVTaCoVEtillbqAhF2/JgvO0LDOMa0w=
|
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
|
||||||
k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24=
|
k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw=
|
||||||
k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM=
|
k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE=
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
|
||||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo=
|
||||||
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
|
sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U=
|
||||||
sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0=
|
sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ=
|
sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
|
||||||
sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
|
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||||
|
|
|
@ -23,6 +23,8 @@ import (
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
// Load client args
|
||||||
|
_ "k8s.io/dashboard/client/args"
|
||||||
"k8s.io/dashboard/csrf"
|
"k8s.io/dashboard/csrf"
|
||||||
"k8s.io/dashboard/helpers"
|
"k8s.io/dashboard/helpers"
|
||||||
)
|
)
|
||||||
|
@ -37,26 +39,41 @@ const (
|
||||||
LogLevelTrace = klog.Level(5)
|
LogLevelTrace = klog.Level(5)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultInsecurePort = 8000
|
||||||
|
defaultPort = 8001
|
||||||
|
defaultProfilerPort = 8070
|
||||||
|
defaultPrometheusPort = 8080
|
||||||
|
|
||||||
|
defaultProfilerPath = "/debug/pprof/"
|
||||||
|
defaultPrometheusPath = "/metrics"
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
argInsecurePort = pflag.Int("insecure-port", 8000, "port to listen to for incoming HTTP requests")
|
argDisableCSRFProtection = pflag.Bool("disable-csrf-protection", false, "allows disabling CSRF protection")
|
||||||
argPort = pflag.Int("port", 8001, "secure port to listen to for incoming HTTPS requests")
|
argIsProxyEnabled = pflag.Bool("act-as-proxy", false, "forces dashboard to work in full proxy mode, meaning that any in-cluster calls are disabled")
|
||||||
argInsecureBindAddress = pflag.IP("insecure-bind-address", net.IPv4(127, 0, 0, 1), "IP address on which to serve the --insecure-port, set to 127.0.0.1 for all interfaces")
|
argOpenAPIEnabled = pflag.Bool("openapi-enabled", false, "enables OpenAPI v2 endpoint under '/apidocs.json'")
|
||||||
argBindAddress = pflag.IP("bind-address", net.IPv4(0, 0, 0, 0), "IP address on which to serve the --port, set to 0.0.0.0 for all interfaces")
|
argProfiler = pflag.Bool("profiler", false, "Enable pprof handler. By default it will be exposed on localhost:8070 under '/debug/pprof'")
|
||||||
|
argPrometheusEnabled = pflag.Bool("prometheus-enabled", false, "Enable prometheus metrics handler. By default it will be exposed on localhost:8080 under '/metrics'")
|
||||||
|
argApiServerSkipTLSVerify = pflag.Bool("apiserver-skip-tls-verify", false, "enable if connection with remote Kubernetes API server should skip TLS verify")
|
||||||
|
argAutoGenerateCertificates = pflag.Bool("auto-generate-certificates", false, "enables automatic certificates generation used to serve HTTPS")
|
||||||
|
|
||||||
|
argInsecurePort = pflag.Int("insecure-port", defaultInsecurePort, "port to listen to for incoming HTTP requests")
|
||||||
|
argPort = pflag.Int("port", defaultPort, "secure port to listen to for incoming HTTPS requests")
|
||||||
|
argMetricClientCheckPeriod = pflag.Int("metric-client-check-period", 30, "time interval between separate metric client health checks in seconds")
|
||||||
|
|
||||||
|
argInsecureBindAddress = pflag.IP("insecure-bind-address", net.IPv4(127, 0, 0, 1), "IP address on which to serve the --insecure-port, set to 0.0.0.0 for all interfaces")
|
||||||
|
argBindAddress = pflag.IP("bind-address", net.IPv4(0, 0, 0, 0), "IP address on which to serve the --port, set to 0.0.0.0 for all interfaces")
|
||||||
|
|
||||||
argDefaultCertDir = pflag.String("default-cert-dir", "/certs", "directory path containing files from --tls-cert-file and --tls-key-file, used also when auto-generating certificates flag is set")
|
argDefaultCertDir = pflag.String("default-cert-dir", "/certs", "directory path containing files from --tls-cert-file and --tls-key-file, used also when auto-generating certificates flag is set")
|
||||||
argCertFile = pflag.String("tls-cert-file", "", "file containing the default x509 certificate for HTTPS")
|
argCertFile = pflag.String("tls-cert-file", "", "file containing the default x509 certificate for HTTPS")
|
||||||
argKeyFile = pflag.String("tls-key-file", "", "file containing the default x509 private key matching --tls-cert-file")
|
argKeyFile = pflag.String("tls-key-file", "", "file containing the default x509 private key matching --tls-cert-file")
|
||||||
argApiServerHost = pflag.String("apiserver-host", "", "address of the Kubernetes API server to connect to in the format of protocol://address:port, leave it empty if the binary runs inside cluster for local discovery attempt")
|
argApiServerHost = pflag.String("apiserver-host", "", "address of the Kubernetes API server to connect to in the format of protocol://address:port, leave it empty if the binary runs inside cluster for local discovery attempt")
|
||||||
argApiServerSkipTLSVerify = pflag.Bool("apiserver-skip-tls-verify", false, "enable if connection with remote Kubernetes API server should skip TLS verify")
|
|
||||||
argMetricsProvider = pflag.String("metrics-provider", "sidecar", "select provider type for metrics, 'none' will not check metrics")
|
argMetricsProvider = pflag.String("metrics-provider", "sidecar", "select provider type for metrics, 'none' will not check metrics")
|
||||||
argSidecarHost = pflag.String("sidecar-host", "", "address of the Sidecar API server to connect to in the format of protocol://address:port, leave it empty if the binary runs inside cluster for service proxy usage")
|
argSidecarHost = pflag.String("sidecar-host", "", "address of the Sidecar API server to connect to in the format of protocol://address:port, leave it empty if the binary runs inside cluster for service proxy usage")
|
||||||
argKubeConfigFile = pflag.String("kubeconfig", "", "path to kubeconfig file with control plane location information")
|
argKubeConfigFile = pflag.String("kubeconfig", "", "path to kubeconfig file with control plane location information")
|
||||||
argMetricClientCheckPeriod = pflag.Int("metric-client-check-period", 30, "time interval between separate metric client health checks in seconds")
|
|
||||||
argAutoGenerateCertificates = pflag.Bool("auto-generate-certificates", false, "enables automatic certificates generation used to serve HTTPS")
|
|
||||||
argNamespace = pflag.String("namespace", helpers.GetEnv("POD_NAMESPACE", "kubernetes-dashboard"), "Namespace to use when accessing Dashboard specific resources, i.e. metrics scraper service")
|
argNamespace = pflag.String("namespace", helpers.GetEnv("POD_NAMESPACE", "kubernetes-dashboard"), "Namespace to use when accessing Dashboard specific resources, i.e. metrics scraper service")
|
||||||
argMetricsScraperServiceName = pflag.String("metrics-scraper-service-name", "kubernetes-dashboard-metrics-scraper", "name of the dashboard metrics scraper service")
|
argMetricsScraperServiceName = pflag.String("metrics-scraper-service-name", "kubernetes-dashboard-metrics-scraper", "name of the dashboard metrics scraper service")
|
||||||
argDisableCSRFProtection = pflag.Bool("disable-csrf-protection", false, "allows disabling CSRF protection")
|
|
||||||
argIsProxyEnabled = pflag.Bool("act-as-proxy", false, "forces dashboard to work in full proxy mode, meaning that any in-cluster calls are disabled")
|
|
||||||
argOpenAPIEnabled = pflag.Bool("openapi-enabled", false, "enables OpenAPI v2 endpoint under '/apidocs.json'")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -73,6 +90,14 @@ func init() {
|
||||||
if IsCSRFProtectionEnabled() {
|
if IsCSRFProtectionEnabled() {
|
||||||
csrf.Ensure()
|
csrf.Ensure()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if *argProfiler {
|
||||||
|
initProfiler()
|
||||||
|
}
|
||||||
|
|
||||||
|
if *argPrometheusEnabled {
|
||||||
|
initPrometheus()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Address() string {
|
func Address() string {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2017 The Kubernetes Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package args
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/http/pprof"
|
||||||
|
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initProfiler() {
|
||||||
|
klog.V(LogLevelInfo).Info("Initializing profiler")
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc(defaultProfilerPath, pprof.Index)
|
||||||
|
go func() {
|
||||||
|
if err := http.ListenAndServe(fmt.Sprintf(":%d", defaultProfilerPort), mux); err != nil {
|
||||||
|
klog.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
// Copyright 2017 The Kubernetes Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package args
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func initPrometheus() {
|
||||||
|
klog.V(LogLevelInfo).Info("Initializing prometheus metrics")
|
||||||
|
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.Handle(defaultPrometheusPath, promhttp.Handler())
|
||||||
|
go func() {
|
||||||
|
if err := http.ListenAndServe(fmt.Sprintf(":%d", defaultPrometheusPort), mux); err != nil {
|
||||||
|
klog.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -77,14 +77,23 @@ func formatRequestLog(request *restful.Request) string {
|
||||||
content = "{ content hidden }"
|
content = "{ content hidden }"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf(RequestLogString, time.Now().Format(time.RFC3339), request.Request.Proto,
|
return fmt.Sprintf(
|
||||||
request.Request.Method, uri, getRemoteAddr(request.Request), content)
|
RequestLogString,
|
||||||
|
request.Request.Proto,
|
||||||
|
request.Request.Method,
|
||||||
|
uri,
|
||||||
|
getRemoteAddr(request.Request),
|
||||||
|
content,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// formatResponseLog formats response log string.
|
// formatResponseLog formats response log string.
|
||||||
func formatResponseLog(response *restful.Response, request *restful.Request) string {
|
func formatResponseLog(response *restful.Response, request *restful.Request) string {
|
||||||
return fmt.Sprintf(ResponseLogString, time.Now().Format(time.RFC3339),
|
return fmt.Sprintf(
|
||||||
getRemoteAddr(request.Request), response.StatusCode())
|
ResponseLogString,
|
||||||
|
getRemoteAddr(request.Request),
|
||||||
|
response.StatusCode(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkSensitiveUrl checks if a string matches against a sensitive URL
|
// checkSensitiveUrl checks if a string matches against a sensitive URL
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/v3"
|
"github.com/emicklei/go-restful/v3"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
)
|
)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
@ -33,6 +32,9 @@ import (
|
||||||
"k8s.io/client-go/kubernetes/scheme"
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/remotecommand"
|
"k8s.io/client-go/tools/remotecommand"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/dashboard/api/pkg/args"
|
||||||
)
|
)
|
||||||
|
|
||||||
const END_OF_TRANSMISSION = "\u0004"
|
const END_OF_TRANSMISSION = "\u0004"
|
||||||
|
@ -164,7 +166,7 @@ func (sm *SessionMap) Close(sessionId string, status uint32, reason string) {
|
||||||
ses := sm.Sessions[sessionId]
|
ses := sm.Sessions[sessionId]
|
||||||
err := ses.sockJSSession.Close(status, reason)
|
err := ses.sockJSSession.Close(status, reason)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Println(err)
|
klog.Error(err)
|
||||||
}
|
}
|
||||||
close(ses.sizeChan)
|
close(ses.sizeChan)
|
||||||
delete(sm.Sessions, sessionId)
|
delete(sm.Sessions, sessionId)
|
||||||
|
@ -182,22 +184,22 @@ func handleTerminalSession(session sockjs.Session) {
|
||||||
)
|
)
|
||||||
|
|
||||||
if buf, err = session.Recv(); err != nil {
|
if buf, err = session.Recv(); err != nil {
|
||||||
log.Printf("handleTerminalSession: can't Recv: %v", err)
|
klog.Errorf("handleTerminalSession: can't Recv: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = json.Unmarshal([]byte(buf), &msg); err != nil {
|
if err = json.Unmarshal([]byte(buf), &msg); err != nil {
|
||||||
log.Printf("handleTerminalSession: can't UnMarshal (%v): %s", err, buf)
|
klog.Errorf("handleTerminalSession: can't UnMarshal (%v): %s", err, buf)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if msg.Op != "bind" {
|
if msg.Op != "bind" {
|
||||||
log.Printf("handleTerminalSession: expected 'bind' message, got: %s", buf)
|
klog.V(args.LogLevelVerbose).Infof("handleTerminalSession: expected 'bind' message, got: %s", buf)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if terminalSession = terminalSessions.Get(msg.SessionID); terminalSession.id == "" {
|
if terminalSession = terminalSessions.Get(msg.SessionID); terminalSession.id == "" {
|
||||||
log.Printf("handleTerminalSession: can't find session '%s'", msg.SessionID)
|
klog.V(args.LogLevelVerbose).Infof("handleTerminalSession: can't find session '%s'", msg.SessionID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,16 +33,16 @@ type Handler struct {
|
||||||
//
|
//
|
||||||
// By default, endpoint for checking state of the integrations is installed. It allows user
|
// By default, endpoint for checking state of the integrations is installed. It allows user
|
||||||
// to check state of integration by accessing `<DASHBOARD_URL>/api/v1/integration/{name}/state`.
|
// to check state of integration by accessing `<DASHBOARD_URL>/api/v1/integration/{name}/state`.
|
||||||
func (self Handler) Install(ws *restful.WebService) {
|
func (in Handler) Install(ws *restful.WebService) {
|
||||||
ws.Route(
|
ws.Route(
|
||||||
ws.GET("/integration/{name}/state").
|
ws.GET("/integration/{name}/state").
|
||||||
To(self.handleGetState).
|
To(in.handleGetState).
|
||||||
Writes(api.IntegrationState{}))
|
Writes(api.IntegrationState{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self Handler) handleGetState(request *restful.Request, response *restful.Response) {
|
func (in Handler) handleGetState(request *restful.Request, response *restful.Response) {
|
||||||
integrationName := request.PathParameter("name")
|
integrationName := request.PathParameter("name")
|
||||||
state, err := self.manager.GetState(api.IntegrationID(integrationName))
|
state, err := in.manager.GetState(api.IntegrationID(integrationName))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.AddHeader("Content-Type", "text/plain")
|
response.AddHeader("Content-Type", "text/plain")
|
||||||
_ = response.WriteErrorString(http.StatusInternalServerError, err.Error()+"\n")
|
_ = response.WriteErrorString(http.StatusInternalServerError, err.Error()+"\n")
|
||||||
|
|
|
@ -31,7 +31,7 @@ func areErrorsEqual(err1, err2 error) bool {
|
||||||
// Removes all quote signs that might have been added to the message.
|
// Removes all quote signs that might have been added to the message.
|
||||||
// Might depend on dependencies version how they are constructed.
|
// Might depend on dependencies version how they are constructed.
|
||||||
func normalize(msg string) string {
|
func normalize(msg string) string {
|
||||||
return strings.Replace(msg, "\"", "", -1)
|
return strings.ReplaceAll(msg, "\"", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewIntegrationManager(t *testing.T) {
|
func TestNewIntegrationManager(t *testing.T) {
|
||||||
|
@ -82,6 +82,6 @@ func TestIntegrationManager_GetState(t *testing.T) {
|
||||||
func TestIntegrationManager_Metric(t *testing.T) {
|
func TestIntegrationManager_Metric(t *testing.T) {
|
||||||
metricManager := integration.NewIntegrationManager().Metric()
|
metricManager := integration.NewIntegrationManager().Metric()
|
||||||
if metricManager == nil {
|
if metricManager == nil {
|
||||||
t.Error("Failed to get metric manager.")
|
t.Error("failed to get metric manager.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,15 +127,15 @@ type MetricPoint struct {
|
||||||
// Label stores information about identity of resources (UIDs) described by metric.
|
// Label stores information about identity of resources (UIDs) described by metric.
|
||||||
type Label map[types.ResourceKind][]apimachinery.UID
|
type Label map[types.ResourceKind][]apimachinery.UID
|
||||||
|
|
||||||
// AddMetricLabel returns a unique combined Label of self and other resource.
|
// AddMetricLabel returns a unique combined Label of in and other resource.
|
||||||
// New label describes both resources.
|
// New label describes both resources.
|
||||||
func (self Label) AddMetricLabel(other Label) Label {
|
func (in Label) AddMetricLabel(other Label) Label {
|
||||||
if other == nil {
|
if other == nil {
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
uniqueMap := map[apimachinery.UID]bool{}
|
uniqueMap := map[apimachinery.UID]bool{}
|
||||||
for _, v := range self {
|
for _, v := range in {
|
||||||
for _, t := range v {
|
for _, t := range v {
|
||||||
uniqueMap[t] = true
|
uniqueMap[t] = true
|
||||||
}
|
}
|
||||||
|
@ -144,11 +144,11 @@ func (self Label) AddMetricLabel(other Label) Label {
|
||||||
for k, v := range other {
|
for k, v := range other {
|
||||||
for _, t := range v {
|
for _, t := range v {
|
||||||
if _, exists := uniqueMap[t]; !exists {
|
if _, exists := uniqueMap[t]; !exists {
|
||||||
self[k] = append(self[k], t)
|
in[k] = append(in[k], t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Metric is a format of data used in this module. This is also the format of data that is being sent by backend client.
|
// Metric is a format of data used in this module. This is also the format of data that is being sent by backend client.
|
||||||
|
@ -190,18 +190,18 @@ func (metric *SidecarMetric) AddMetricPoint(item MetricPoint) []MetricPoint {
|
||||||
return metric.MetricPoints
|
return metric.MetricPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (metric *Metric) AddMetricPoint(item MetricPoint) []MetricPoint {
|
func (in *Metric) AddMetricPoint(item MetricPoint) []MetricPoint {
|
||||||
metric.MetricPoints = append(metric.MetricPoints, item)
|
in.MetricPoints = append(in.MetricPoints, item)
|
||||||
return metric.MetricPoints
|
return in.MetricPoints
|
||||||
}
|
}
|
||||||
|
|
||||||
// String implements stringer interface to allow easy printing
|
// String implements stringer interface to allow easy printing
|
||||||
func (self Metric) String() string {
|
func (in Metric) String() string {
|
||||||
return "{\nDataPoints: " + fmt.Sprintf("%v", self.DataPoints) +
|
return "{\nDataPoints: " + fmt.Sprintf("%v", in.DataPoints) +
|
||||||
"\nMetricPoints: " + fmt.Sprintf("%v", self.MetricPoints) +
|
"\nMetricPoints: " + fmt.Sprintf("%v", in.MetricPoints) +
|
||||||
"\nMetricName: " + self.MetricName +
|
"\nMetricName: " + in.MetricName +
|
||||||
"\nLabel: " + fmt.Sprintf("%v", self.Label) +
|
"\nLabel: " + fmt.Sprintf("%v", in.Label) +
|
||||||
"\nAggregate: " + fmt.Sprintf("%v", self.Aggregate)
|
"\nAggregate: " + fmt.Sprintf("%v", in.Aggregate)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MetricPromise is used for parallel data extraction. Contains len 1 channels for Metric and Error.
|
// MetricPromise is used for parallel data extraction. Contains len 1 channels for Metric and Error.
|
||||||
|
@ -211,12 +211,12 @@ type MetricPromise struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMetric returns pointer to received Metrics and forwarded error (if any)
|
// GetMetric returns pointer to received Metrics and forwarded error (if any)
|
||||||
func (self MetricPromise) GetMetric() (*Metric, error) {
|
func (in MetricPromise) GetMetric() (*Metric, error) {
|
||||||
err := <-self.Error
|
err := <-in.Error
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return <-self.Metric, nil
|
return <-in.Metric, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricPromise creates a MetricPromise structure with both channels of length 1.
|
// NewMetricPromise creates a MetricPromise structure with both channels of length 1.
|
||||||
|
@ -231,10 +231,10 @@ type MetricPromises []MetricPromise
|
||||||
|
|
||||||
// GetMetrics returns all metrics from MetricPromises.
|
// GetMetrics returns all metrics from MetricPromises.
|
||||||
// In case of no metrics were downloaded it does not initialise []Metric and returns nil.
|
// In case of no metrics were downloaded it does not initialise []Metric and returns nil.
|
||||||
func (self MetricPromises) GetMetrics() ([]Metric, error) {
|
func (in MetricPromises) GetMetrics() ([]Metric, error) {
|
||||||
result := make([]Metric, 0)
|
result := make([]Metric, 0)
|
||||||
|
|
||||||
for _, metricPromise := range self {
|
for _, metricPromise := range in {
|
||||||
metric, err := metricPromise.GetMetric()
|
metric, err := metricPromise.GetMetric()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Do not fail when cannot resolve one of the metrics promises and return what can be resolved.
|
// Do not fail when cannot resolve one of the metrics promises and return what can be resolved.
|
||||||
|
@ -252,8 +252,8 @@ func (self MetricPromises) GetMetrics() ([]Metric, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutMetrics forwards provided list of metrics to all channels. If provided err is not nil, error will be forwarded.
|
// PutMetrics forwards provided list of metrics to all channels. If provided err is not nil, error will be forwarded.
|
||||||
func (self MetricPromises) PutMetrics(metrics []Metric, err error) {
|
func (in MetricPromises) PutMetrics(metrics []Metric, err error) {
|
||||||
for i, metricPromise := range self {
|
for i, metricPromise := range in {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
metricPromise.Metric <- nil
|
metricPromise.Metric <- nil
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -52,39 +52,39 @@ type metricManager struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddClient implements metric manager interface. See MetricManager for more information.
|
// AddClient implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) AddClient(client metricapi.MetricClient) MetricManager {
|
func (in *metricManager) AddClient(client metricapi.MetricClient) MetricManager {
|
||||||
if client != nil {
|
if client != nil {
|
||||||
self.clients[client.ID()] = client
|
in.clients[client.ID()] = client
|
||||||
}
|
}
|
||||||
|
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client implements metric manager interface. See MetricManager for more information.
|
// Client implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) Client() metricapi.MetricClient {
|
func (in *metricManager) Client() metricapi.MetricClient {
|
||||||
return self.active
|
return in.active
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable implements metric manager interface. See MetricManager for more information.
|
// Enable implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) Enable(id integrationapi.IntegrationID) error {
|
func (in *metricManager) Enable(id integrationapi.IntegrationID) error {
|
||||||
metricClient, exists := self.clients[id]
|
metricClient, exists := in.clients[id]
|
||||||
if !exists {
|
if !exists {
|
||||||
return fmt.Errorf("No metric client found for integration id: %s", id)
|
return fmt.Errorf("no metric client found for integration id: %s", id)
|
||||||
}
|
}
|
||||||
|
|
||||||
err := metricClient.HealthCheck()
|
err := metricClient.HealthCheck()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Health check failed: %s", err.Error())
|
return fmt.Errorf("health check failed: %s", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
self.active = metricClient
|
in.active = metricClient
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnableWithRetry implements metric manager interface. See MetricManager for more information.
|
// EnableWithRetry implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) EnableWithRetry(id integrationapi.IntegrationID, period time.Duration) {
|
func (in *metricManager) EnableWithRetry(id integrationapi.IntegrationID, period time.Duration) {
|
||||||
go wait.Forever(func() {
|
go wait.Forever(func() {
|
||||||
metricClient, exists := self.clients[id]
|
metricClient, exists := in.clients[id]
|
||||||
if !exists {
|
if !exists {
|
||||||
klog.V(5).InfoS("Metric client does not exist", "clientID", id)
|
klog.V(5).InfoS("Metric client does not exist", "clientID", id)
|
||||||
return
|
return
|
||||||
|
@ -92,22 +92,22 @@ func (self *metricManager) EnableWithRetry(id integrationapi.IntegrationID, peri
|
||||||
|
|
||||||
err := metricClient.HealthCheck()
|
err := metricClient.HealthCheck()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
self.active = nil
|
in.active = nil
|
||||||
klog.Errorf("Metric client health check failed: %s. Retrying in %d seconds.", err, period)
|
klog.Errorf("Metric client health check failed: %s. Retrying in %d seconds.", err, period)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.active == nil {
|
if in.active == nil {
|
||||||
klog.V(1).Infof("Successful request to %s", id)
|
klog.V(1).Infof("Successful request to %s", id)
|
||||||
self.active = metricClient
|
in.active = metricClient
|
||||||
}
|
}
|
||||||
}, period*time.Second)
|
}, period*time.Second)
|
||||||
}
|
}
|
||||||
|
|
||||||
// List implements metric manager interface. See MetricManager for more information.
|
// List implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) List() []integrationapi.Integration {
|
func (in *metricManager) List() []integrationapi.Integration {
|
||||||
result := make([]integrationapi.Integration, 0)
|
result := make([]integrationapi.Integration, 0)
|
||||||
for _, c := range self.clients {
|
for _, c := range in.clients {
|
||||||
result = append(result, c.(integrationapi.Integration))
|
result = append(result, c.(integrationapi.Integration))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,16 +115,16 @@ func (self *metricManager) List() []integrationapi.Integration {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfigureSidecar implements metric manager interface. See MetricManager for more information.
|
// ConfigureSidecar implements metric manager interface. See MetricManager for more information.
|
||||||
func (self *metricManager) ConfigureSidecar(host string) MetricManager {
|
func (in *metricManager) ConfigureSidecar(host string) MetricManager {
|
||||||
inClusterClient := client.InClusterClient()
|
inClusterClient := client.InClusterClient()
|
||||||
metricClient, err := sidecar.CreateSidecarClient(host, inClusterClient)
|
metricClient, err := sidecar.CreateSidecarClient(host, inClusterClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("There was an error during sidecar client creation: %s", err.Error())
|
klog.Errorf("There was an error during sidecar client creation: %s", err.Error())
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
self.clients[metricClient.ID()] = metricClient
|
in.clients[metricClient.ID()] = metricClient
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMetricManager creates metric manager.
|
// NewMetricManager creates metric manager.
|
||||||
|
|
|
@ -33,25 +33,25 @@ func (FakeMetricClient) ID() integrationapi.IntegrationID {
|
||||||
return fakeMetricClientID
|
return fakeMetricClientID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeMetricClient) HealthCheck() error {
|
func (in FakeMetricClient) HealthCheck() error {
|
||||||
if self.healthOk {
|
if in.healthOk {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errors.NewInvalid("test-error")
|
return errors.NewInvalid("test-error")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeMetricClient) DownloadMetric(selectors []api.ResourceSelector, metricName string,
|
func (in FakeMetricClient) DownloadMetric(selectors []api.ResourceSelector, metricName string,
|
||||||
cachedResources *api.CachedResources) api.MetricPromises {
|
cachedResources *api.CachedResources) api.MetricPromises {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeMetricClient) DownloadMetrics(selectors []api.ResourceSelector, metricNames []string,
|
func (in FakeMetricClient) DownloadMetrics(selectors []api.ResourceSelector, metricNames []string,
|
||||||
cachedResources *api.CachedResources) api.MetricPromises {
|
cachedResources *api.CachedResources) api.MetricPromises {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeMetricClient) AggregateMetrics(metrics api.MetricPromises, metricName string,
|
func (in FakeMetricClient) AggregateMetrics(metrics api.MetricPromises, metricName string,
|
||||||
aggregations api.AggregationModes) api.MetricPromises {
|
aggregations api.AggregationModes) api.MetricPromises {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ func TestMetricManager_Enable(t *testing.T) {
|
||||||
client api.MetricClient
|
client api.MetricClient
|
||||||
expected error
|
expected error
|
||||||
}{
|
}{
|
||||||
{&FakeMetricClient{healthOk: false}, errors.NewInvalid("Health check failed: test-error")},
|
{&FakeMetricClient{healthOk: false}, errors.NewInvalid("health check failed: test-error")},
|
||||||
{&FakeMetricClient{healthOk: true}, nil},
|
{&FakeMetricClient{healthOk: true}, nil},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
@ -41,56 +40,56 @@ type sidecarClient struct {
|
||||||
// Implement Integration interface.
|
// Implement Integration interface.
|
||||||
|
|
||||||
// HealthCheck implements integration app interface. See Integration interface for more information.
|
// HealthCheck implements integration app interface. See Integration interface for more information.
|
||||||
func (self sidecarClient) HealthCheck() error {
|
func (in sidecarClient) HealthCheck() error {
|
||||||
if self.client == nil {
|
if in.client == nil {
|
||||||
return errors.New("Sidecar not configured")
|
return errors.New("sidecar not configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.client.HealthCheck()
|
return in.client.HealthCheck()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID implements integration app interface. See Integration interface for more information.
|
// ID implements integration app interface. See Integration interface for more information.
|
||||||
func (self sidecarClient) ID() integrationapi.IntegrationID {
|
func (in sidecarClient) ID() integrationapi.IntegrationID {
|
||||||
return integrationapi.SidecarIntegrationID
|
return integrationapi.SidecarIntegrationID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement MetricClient interface
|
// Implement MetricClient interface
|
||||||
|
|
||||||
// DownloadMetrics implements metric client interface. See MetricClient for more information.
|
// DownloadMetrics implements metric client interface. See MetricClient for more information.
|
||||||
func (self sidecarClient) DownloadMetrics(selectors []metricapi.ResourceSelector,
|
func (in sidecarClient) DownloadMetrics(selectors []metricapi.ResourceSelector,
|
||||||
metricNames []string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
metricNames []string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
||||||
result := metricapi.MetricPromises{}
|
result := metricapi.MetricPromises{}
|
||||||
for _, metricName := range metricNames {
|
for _, metricName := range metricNames {
|
||||||
collectedMetrics := self.DownloadMetric(selectors, metricName, cachedResources)
|
collectedMetrics := in.DownloadMetric(selectors, metricName, cachedResources)
|
||||||
result = append(result, collectedMetrics...)
|
result = append(result, collectedMetrics...)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// DownloadMetric implements metric client interface. See MetricClient for more information.
|
// DownloadMetric implements metric client interface. See MetricClient for more information.
|
||||||
func (self sidecarClient) DownloadMetric(selectors []metricapi.ResourceSelector,
|
func (in sidecarClient) DownloadMetric(selectors []metricapi.ResourceSelector,
|
||||||
metricName string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
metricName string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
||||||
sidecarSelectors := getSidecarSelectors(selectors, cachedResources)
|
sidecarSelectors := getSidecarSelectors(selectors, cachedResources)
|
||||||
|
|
||||||
// Downloads metric in the fastest possible way by first compressing SidecarSelectors and later unpacking the result to separate boxes.
|
// Downloads metric in the fastest possible way by first compressing SidecarSelectors and later unpacking the result to separate boxes.
|
||||||
compressedSelectors, reverseMapping := compress(sidecarSelectors)
|
compressedSelectors, reverseMapping := compress(sidecarSelectors)
|
||||||
return self.downloadMetric(sidecarSelectors, compressedSelectors, reverseMapping, metricName)
|
return in.downloadMetric(sidecarSelectors, compressedSelectors, reverseMapping, metricName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// AggregateMetrics implements metric client interface. See MetricClient for more information.
|
// AggregateMetrics implements metric client interface. See MetricClient for more information.
|
||||||
func (self sidecarClient) AggregateMetrics(metrics metricapi.MetricPromises, metricName string,
|
func (in sidecarClient) AggregateMetrics(metrics metricapi.MetricPromises, metricName string,
|
||||||
aggregations metricapi.AggregationModes) metricapi.MetricPromises {
|
aggregations metricapi.AggregationModes) metricapi.MetricPromises {
|
||||||
return common.AggregateMetricPromises(metrics, metricName, aggregations, nil)
|
return common.AggregateMetricPromises(metrics, metricName, aggregations, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self sidecarClient) downloadMetric(sidecarSelectors []sidecarSelector,
|
func (in sidecarClient) downloadMetric(sidecarSelectors []sidecarSelector,
|
||||||
compressedSelectors []sidecarSelector, reverseMapping map[string][]int,
|
compressedSelectors []sidecarSelector, reverseMapping map[string][]int,
|
||||||
metricName string) metricapi.MetricPromises {
|
metricName string) metricapi.MetricPromises {
|
||||||
// collect all the required data (as promises)
|
// collect all the required data (as promises)
|
||||||
unassignedResourcePromisesList := make([]metricapi.MetricPromises, len(compressedSelectors))
|
unassignedResourcePromisesList := make([]metricapi.MetricPromises, len(compressedSelectors))
|
||||||
for selectorId, compressedSelector := range compressedSelectors {
|
for selectorId, compressedSelector := range compressedSelectors {
|
||||||
unassignedResourcePromisesList[selectorId] =
|
unassignedResourcePromisesList[selectorId] =
|
||||||
self.downloadMetricForEachTargetResource(compressedSelector, metricName)
|
in.downloadMetricForEachTargetResource(compressedSelector, metricName)
|
||||||
}
|
}
|
||||||
// prepare final result
|
// prepare final result
|
||||||
result := metricapi.NewMetricPromises(len(sidecarSelectors))
|
result := metricapi.NewMetricPromises(len(sidecarSelectors))
|
||||||
|
@ -135,28 +134,28 @@ func (self sidecarClient) downloadMetric(sidecarSelectors []sidecarSelector,
|
||||||
}
|
}
|
||||||
|
|
||||||
// downloadMetricForEachTargetResource downloads requested metric for each resource present in SidecarSelector
|
// downloadMetricForEachTargetResource downloads requested metric for each resource present in SidecarSelector
|
||||||
// and returns the result as a list of promises - one promise for each resource. Order of promises returned is the same as order in self.Resources.
|
// and returns the result as a list of promises - one promise for each resource. Order of promises returned is the same as order in in.Resources.
|
||||||
func (self sidecarClient) downloadMetricForEachTargetResource(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
func (in sidecarClient) downloadMetricForEachTargetResource(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||||
var notAggregatedMetrics metricapi.MetricPromises
|
var notAggregatedMetrics metricapi.MetricPromises
|
||||||
if SidecarAllInOneDownloadConfig[selector.TargetResourceType] {
|
if SidecarAllInOneDownloadConfig[selector.TargetResourceType] {
|
||||||
notAggregatedMetrics = self.allInOneDownload(selector, metricName)
|
notAggregatedMetrics = in.allInOneDownload(selector, metricName)
|
||||||
} else {
|
} else {
|
||||||
notAggregatedMetrics = metricapi.MetricPromises{}
|
notAggregatedMetrics = metricapi.MetricPromises{}
|
||||||
for i := range selector.Resources {
|
for i := range selector.Resources {
|
||||||
notAggregatedMetrics = append(notAggregatedMetrics, self.ithResourceDownload(selector, metricName, i))
|
notAggregatedMetrics = append(notAggregatedMetrics, in.ithResourceDownload(selector, metricName, i))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return notAggregatedMetrics
|
return notAggregatedMetrics
|
||||||
}
|
}
|
||||||
|
|
||||||
// ithResourceDownload downloads metric for ith resource in self.Resources. Use only in case all in 1 download is not supported
|
// ithResourceDownload downloads metric for ith resource in in.Resources. Use only in case all in 1 download is not supported
|
||||||
// for this resource type.
|
// for this resource type.
|
||||||
func (self sidecarClient) ithResourceDownload(selector sidecarSelector, metricName string,
|
func (in sidecarClient) ithResourceDownload(selector sidecarSelector, metricName string,
|
||||||
i int) metricapi.MetricPromise {
|
i int) metricapi.MetricPromise {
|
||||||
result := metricapi.NewMetricPromise()
|
result := metricapi.NewMetricPromise()
|
||||||
go func() {
|
go func() {
|
||||||
rawResult := metricapi.SidecarMetricResultList{}
|
rawResult := metricapi.SidecarMetricResultList{}
|
||||||
err := self.unmarshalType(selector.Path+selector.Resources[i]+"/metrics/"+metricName, &rawResult)
|
err := in.unmarshalType(selector.Path+selector.Resources[i]+"/metrics/"+metricName, &rawResult)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.Metric <- nil
|
result.Metric <- nil
|
||||||
result.Error <- err
|
result.Error <- err
|
||||||
|
@ -186,9 +185,9 @@ func (self sidecarClient) ithResourceDownload(selector sidecarSelector, metricNa
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// allInOneDownload downloads metrics for all resources present in self.Resources in one request.
|
// allInOneDownload downloads metrics for all resources present in in.Resources in one request.
|
||||||
// returns a list of metric promises - one promise for each resource. Order of self.Resources is preserved.
|
// returns a list of metric promises - one promise for each resource. Order of in.Resources is preserved.
|
||||||
func (self sidecarClient) allInOneDownload(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
func (in sidecarClient) allInOneDownload(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||||
result := metricapi.NewMetricPromises(len(selector.Resources))
|
result := metricapi.NewMetricPromises(len(selector.Resources))
|
||||||
go func() {
|
go func() {
|
||||||
if len(selector.Resources) == 0 {
|
if len(selector.Resources) == 0 {
|
||||||
|
@ -196,7 +195,7 @@ func (self sidecarClient) allInOneDownload(selector sidecarSelector, metricName
|
||||||
}
|
}
|
||||||
rawResults := metricapi.SidecarMetricResultList{}
|
rawResults := metricapi.SidecarMetricResultList{}
|
||||||
|
|
||||||
err := self.unmarshalType(selector.Path+strings.Join(selector.Resources, ",")+"/metrics/"+metricName, &rawResults)
|
err := in.unmarshalType(selector.Path+strings.Join(selector.Resources, ",")+"/metrics/"+metricName, &rawResults)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
result.PutMetrics(nil, err)
|
result.PutMetrics(nil, err)
|
||||||
|
@ -204,7 +203,7 @@ func (self sidecarClient) allInOneDownload(selector sidecarSelector, metricName
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(result) != len(rawResults.Items) {
|
if len(result) != len(rawResults.Items) {
|
||||||
log.Printf(`received %d resources from sidecar instead of %d`, len(rawResults.Items), len(result))
|
klog.V(args.LogLevelVerbose).Infof(`received %d resources from sidecar instead of %d`, len(rawResults.Items), len(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawResult.Items have indefinite order.
|
// rawResult.Items have indefinite order.
|
||||||
|
@ -249,8 +248,8 @@ func (self sidecarClient) allInOneDownload(selector sidecarSelector, metricName
|
||||||
|
|
||||||
// unmarshalType performs sidecar GET request to the specifies path and transfers
|
// unmarshalType performs sidecar GET request to the specifies path and transfers
|
||||||
// the data to the interface provided.
|
// the data to the interface provided.
|
||||||
func (self sidecarClient) unmarshalType(path string, v interface{}) error {
|
func (in sidecarClient) unmarshalType(path string, v interface{}) error {
|
||||||
rawData, err := self.client.Get("/api/v1/dashboard/" + path).DoRaw(context.TODO())
|
rawData, err := in.client.Get("/api/v1/dashboard/" + path).DoRaw(context.TODO())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -44,7 +43,7 @@ func areErrorsEqual(err1, err2 error) bool {
|
||||||
// Removes all quote signs that might have been added to the message.
|
// Removes all quote signs that might have been added to the message.
|
||||||
// Might depend on dependencies version how they are constructed.
|
// Might depend on dependencies version how they are constructed.
|
||||||
func normalize(msg string) string {
|
func normalize(msg string) string {
|
||||||
return strings.Replace(msg, "\"", "", -1)
|
return strings.ReplaceAll(msg, "\"", "")
|
||||||
}
|
}
|
||||||
|
|
||||||
type GlobalCounter int32
|
type GlobalCounter int32
|
||||||
|
@ -77,28 +76,27 @@ type FakeRequest struct {
|
||||||
type PodData map[string][]metricapi.MetricPoint
|
type PodData map[string][]metricapi.MetricPoint
|
||||||
type NodeData map[string][]metricapi.MetricPoint
|
type NodeData map[string][]metricapi.MetricPoint
|
||||||
|
|
||||||
func (self FakeSidecar) Get(path string) RequestInterface {
|
func (in FakeSidecar) Get(path string) RequestInterface {
|
||||||
return FakeRequest{self.PodData, self.NodeData, path}
|
return FakeRequest{in.PodData, in.NodeData, path}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeSidecar) GetNumberOfRequestsMade() int {
|
func (in FakeSidecar) GetNumberOfRequestsMade() int {
|
||||||
num := int(_NumRequests.get())
|
num := int(_NumRequests.get())
|
||||||
_NumRequests.set(0)
|
_NumRequests.set(0)
|
||||||
return num
|
return num
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeSidecar) HealthCheck() error {
|
func (in FakeSidecar) HealthCheck() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeSidecar) ID() integrationapi.IntegrationID {
|
func (in FakeSidecar) ID() integrationapi.IntegrationID {
|
||||||
return "fakeSidecar"
|
return "fakeSidecar"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
func (in FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
||||||
_NumRequests.increment()
|
_NumRequests.increment()
|
||||||
log.Println("Performing req...")
|
path := in.Path
|
||||||
path := self.Path
|
|
||||||
time.Sleep(50 * time.Millisecond) // simulate response delay of 0.05 seconds
|
time.Sleep(50 * time.Millisecond) // simulate response delay of 0.05 seconds
|
||||||
if strings.Contains(path, "/pod-list/") {
|
if strings.Contains(path, "/pod-list/") {
|
||||||
r, _ := regexp.Compile(`\/pod\-list\/(.+)\/metrics\/`)
|
r, _ := regexp.Compile(`\/pod\-list\/(.+)\/metrics\/`)
|
||||||
|
@ -117,10 +115,9 @@ func (self FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
||||||
|
|
||||||
items := metricapi.SidecarMetricResultList{}
|
items := metricapi.SidecarMetricResultList{}
|
||||||
for _, pod := range requestedPods {
|
for _, pod := range requestedPods {
|
||||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: self.PodData[pod+"/"+namespace], UIDs: []string{pod}})
|
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: in.PodData[pod+"/"+namespace], UIDs: []string{pod}})
|
||||||
}
|
}
|
||||||
x, err := json.Marshal(items)
|
x, err := json.Marshal(items)
|
||||||
log.Println("Got you:", string(x))
|
|
||||||
return x, err
|
return x, err
|
||||||
|
|
||||||
} else if strings.Contains(path, "/nodes/") {
|
} else if strings.Contains(path, "/nodes/") {
|
||||||
|
@ -132,17 +129,16 @@ func (self FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
||||||
requestedNode := submatch[1]
|
requestedNode := submatch[1]
|
||||||
|
|
||||||
items := metricapi.SidecarMetricResultList{}
|
items := metricapi.SidecarMetricResultList{}
|
||||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: self.NodeData[requestedNode], UIDs: []string{requestedNode}})
|
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: in.NodeData[requestedNode], UIDs: []string{requestedNode}})
|
||||||
|
|
||||||
x, err := json.Marshal(items)
|
x, err := json.Marshal(items)
|
||||||
log.Println("Got you:", string(x))
|
|
||||||
return x, err
|
return x, err
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("Invalid request url %s", path)
|
return nil, fmt.Errorf("Invalid request url %s", path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self FakeRequest) AbsPath(segments ...string) *rest.Request {
|
func (in FakeRequest) AbsPath(segments ...string) *rest.Request {
|
||||||
return &rest.Request{}
|
return &rest.Request{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,7 +290,6 @@ func TestDownloadMetric(t *testing.T) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, testCase := range testCases {
|
for _, testCase := range testCases {
|
||||||
log.Println("-----------\n\n\n", testCase.Info, int(_NumRequests.get()))
|
|
||||||
hClient := sidecarClient{fakeSidecarClient}
|
hClient := sidecarClient{fakeSidecarClient}
|
||||||
promises := hClient.DownloadMetric(testCase.Selectors, "",
|
promises := hClient.DownloadMetric(testCase.Selectors, "",
|
||||||
&metricapi.CachedResources{})
|
&metricapi.CachedResources{})
|
||||||
|
|
|
@ -56,8 +56,8 @@ func (c inClusterSidecarClient) Get(path string) RequestInterface {
|
||||||
|
|
||||||
// HealthCheck does a health check of the application.
|
// HealthCheck does a health check of the application.
|
||||||
// Returns nil if connection to application can be established, error object otherwise.
|
// Returns nil if connection to application can be established, error object otherwise.
|
||||||
func (self inClusterSidecarClient) HealthCheck() error {
|
func (in inClusterSidecarClient) HealthCheck() error {
|
||||||
_, err := self.client.Get().
|
_, err := in.client.Get().
|
||||||
Namespace(args.Namespace()).
|
Namespace(args.Namespace()).
|
||||||
Resource("services").
|
Resource("services").
|
||||||
Name(args.MetricsScraperServiceName()).
|
Name(args.MetricsScraperServiceName()).
|
||||||
|
@ -80,7 +80,7 @@ func (c remoteSidecarClient) Get(path string) RequestInterface {
|
||||||
|
|
||||||
// HealthCheck does a health check of the application.
|
// HealthCheck does a health check of the application.
|
||||||
// Returns nil if connection to application can be established, error object otherwise.
|
// Returns nil if connection to application can be established, error object otherwise.
|
||||||
func (self remoteSidecarClient) HealthCheck() error {
|
func (in remoteSidecarClient) HealthCheck() error {
|
||||||
_, err := self.Get("healthz").AbsPath("/").DoRaw(context.TODO())
|
_, err := in.Get("healthz").AbsPath("/").DoRaw(context.TODO())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,9 @@ package sidecar
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/emicklei/go-restful/v3/log"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
apimachinery "k8s.io/apimachinery/pkg/types"
|
apimachinery "k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/helpers"
|
"k8s.io/dashboard/helpers"
|
||||||
|
@ -39,7 +39,7 @@ func getSidecarSelectors(selectors []metricapi.ResourceSelector,
|
||||||
for i, selector := range selectors {
|
for i, selector := range selectors {
|
||||||
sidecarSelector, err := getSidecarSelector(selector, cachedResources)
|
sidecarSelector, err := getSidecarSelector(selector, cachedResources)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("There was an error during transformation to sidecar selector: %s", err.Error())
|
klog.Errorf("There was an error during transformation to sidecar selector: %s", err.Error())
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func getSidecarSelector(selector metricapi.ResourceSelector,
|
||||||
selector.Namespace, podListToNameList(myPods), podListToUIDList(myPods))
|
selector.Namespace, podListToNameList(myPods), podListToUIDList(myPods))
|
||||||
}
|
}
|
||||||
// currently can only convert derived resource to pods. You can change it by implementing other methods
|
// currently can only convert derived resource to pods. You can change it by implementing other methods
|
||||||
return sidecarSelector{}, fmt.Errorf(`Internal Error: Requested summing resources not supported. Requested "%s"`, summingResource)
|
return sidecarSelector{}, fmt.Errorf(`internal Error: Requested summing resources not supported. Requested "%s"`, summingResource)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getMyPodsFromCache returns a full list of pods that belong to this resource.
|
// getMyPodsFromCache returns a full list of pods that belong to this resource.
|
||||||
|
@ -76,11 +76,11 @@ func getSidecarSelector(selector metricapi.ResourceSelector,
|
||||||
func getMyPodsFromCache(selector metricapi.ResourceSelector, cachedPods []v1.Pod) (matchingPods []v1.Pod, err error) {
|
func getMyPodsFromCache(selector metricapi.ResourceSelector, cachedPods []v1.Pod) (matchingPods []v1.Pod, err error) {
|
||||||
switch {
|
switch {
|
||||||
case cachedPods == nil:
|
case cachedPods == nil:
|
||||||
err = fmt.Errorf(`Pods were not available in cache. Required for resource type: "%s"`,
|
err = fmt.Errorf(`pods were not available in cache. Required for resource type: "%s"`,
|
||||||
selector.ResourceType)
|
selector.ResourceType)
|
||||||
case selector.ResourceType == types.ResourceKindDeployment:
|
case selector.ResourceType == types.ResourceKindDeployment:
|
||||||
for _, pod := range cachedPods {
|
for _, pod := range cachedPods {
|
||||||
if pod.ObjectMeta.Namespace == selector.Namespace && helpers.IsSelectorMatching(selector.Selector, pod.Labels) {
|
if pod.Namespace == selector.Namespace && helpers.IsSelectorMatching(selector.Selector, pod.Labels) {
|
||||||
matchingPods = append(matchingPods, pod)
|
matchingPods = append(matchingPods, pod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,22 +104,23 @@ func getMyPodsFromCache(selector metricapi.ResourceSelector, cachedPods []v1.Pod
|
||||||
func newSidecarSelectorFromNativeResource(resourceType types.ResourceKind, namespace string,
|
func newSidecarSelectorFromNativeResource(resourceType types.ResourceKind, namespace string,
|
||||||
resourceNames []string, resourceUIDs []apimachinery.UID) (sidecarSelector, error) {
|
resourceNames []string, resourceUIDs []apimachinery.UID) (sidecarSelector, error) {
|
||||||
// Here we have 2 possibilities because this module allows downloading Nodes and Pods from sidecar
|
// Here we have 2 possibilities because this module allows downloading Nodes and Pods from sidecar
|
||||||
if resourceType == types.ResourceKindPod {
|
switch resourceType {
|
||||||
|
case types.ResourceKindPod:
|
||||||
return sidecarSelector{
|
return sidecarSelector{
|
||||||
TargetResourceType: types.ResourceKindPod,
|
TargetResourceType: types.ResourceKindPod,
|
||||||
Path: `namespaces/` + namespace + `/pod-list/`,
|
Path: `namespaces/` + namespace + `/pod-list/`,
|
||||||
Resources: resourceNames,
|
Resources: resourceNames,
|
||||||
Label: metricapi.Label{resourceType: resourceUIDs},
|
Label: metricapi.Label{resourceType: resourceUIDs},
|
||||||
}, nil
|
}, nil
|
||||||
} else if resourceType == types.ResourceKindNode {
|
case types.ResourceKindNode:
|
||||||
return sidecarSelector{
|
return sidecarSelector{
|
||||||
TargetResourceType: types.ResourceKindNode,
|
TargetResourceType: types.ResourceKindNode,
|
||||||
Path: `nodes/`,
|
Path: `nodes/`,
|
||||||
Resources: resourceNames,
|
Resources: resourceNames,
|
||||||
Label: metricapi.Label{resourceType: resourceUIDs},
|
Label: metricapi.Label{resourceType: resourceUIDs},
|
||||||
}, nil
|
}, nil
|
||||||
} else {
|
default:
|
||||||
return sidecarSelector{}, fmt.Errorf(`Resource "%s" is not a native sidecar resource type or is not supported`, resourceType)
|
return sidecarSelector{}, fmt.Errorf(`resource "%s" is not a native sidecar resource type or is not supported`, resourceType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,14 +22,14 @@ import (
|
||||||
|
|
||||||
type RoleCell ClusterRole
|
type RoleCell ClusterRole
|
||||||
|
|
||||||
func (self RoleCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in RoleCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -15,10 +15,9 @@
|
||||||
package clusterrole
|
package clusterrole
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
rbac "k8s.io/api/rbac/v1"
|
rbac "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -40,7 +39,7 @@ type ClusterRole struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetClusterRoleList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleList, error) {
|
func GetClusterRoleList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleList, error) {
|
||||||
log.Println("Getting list of RBAC roles")
|
klog.V(4).Info("Getting list of RBAC roles")
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
ClusterRoleList: common.GetClusterRoleListChannel(client, 1),
|
ClusterRoleList: common.GetClusterRoleListChannel(client, 1),
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,14 +22,14 @@ import (
|
||||||
|
|
||||||
type ClusterRoleBindingCell ClusterRoleBinding
|
type ClusterRoleBindingCell ClusterRoleBinding
|
||||||
|
|
||||||
func (self ClusterRoleBindingCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in ClusterRoleBindingCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -15,10 +15,9 @@
|
||||||
package clusterrolebinding
|
package clusterrolebinding
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
rbac "k8s.io/api/rbac/v1"
|
rbac "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -44,7 +43,7 @@ type ClusterRoleBinding struct {
|
||||||
|
|
||||||
// GetClusterRoleBindingList returns a list of all ClusterRoleBindings in the cluster.
|
// GetClusterRoleBindingList returns a list of all ClusterRoleBindings in the cluster.
|
||||||
func GetClusterRoleBindingList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleBindingList, error) {
|
func GetClusterRoleBindingList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleBindingList, error) {
|
||||||
log.Print("Getting list of all clusterRoleBindings in the cluster")
|
klog.V(4).Infof("Getting list of all clusterRoleBindings in the cluster")
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
ClusterRoleBindingList: common.GetClusterRoleBindingListChannel(client, 1),
|
ClusterRoleBindingList: common.GetClusterRoleBindingListChannel(client, 1),
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ import (
|
||||||
batch "k8s.io/api/batch/v1"
|
batch "k8s.io/api/batch/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
|
policyv1 "k8s.io/api/policy/v1"
|
||||||
rbac "k8s.io/api/rbac/v1"
|
rbac "k8s.io/api/rbac/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||||
|
@ -124,6 +125,8 @@ type ResourceChannels struct {
|
||||||
|
|
||||||
// List and error channels to ClusterRoleBindings
|
// List and error channels to ClusterRoleBindings
|
||||||
ClusterRoleBindingList ClusterRoleBindingListChannel
|
ClusterRoleBindingList ClusterRoleBindingListChannel
|
||||||
|
|
||||||
|
PodDisruptionBudget PodDisruptionBudgetListChannel
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServiceListChannel is a list and error channels to Services.
|
// ServiceListChannel is a list and error channels to Services.
|
||||||
|
@ -145,7 +148,7 @@ func GetServiceListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
||||||
list, err := client.CoreV1().Services(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.CoreV1().Services(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []v1.Service
|
var filteredItems []v1.Service
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,7 +181,7 @@ func GetIngressListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
||||||
list, err := client.NetworkingV1().Ingresses(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.NetworkingV1().Ingresses(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []networkingv1.Ingress
|
var filteredItems []networkingv1.Ingress
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -295,7 +298,7 @@ func GetEventListChannelWithOptions(client client.Interface,
|
||||||
list, err := client.CoreV1().Events(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
list, err := client.CoreV1().Events(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
||||||
var filteredItems []v1.Event
|
var filteredItems []v1.Event
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,7 +368,7 @@ func GetPodListChannelWithOptions(client client.Interface, nsQuery *NamespaceQue
|
||||||
list, err := client.CoreV1().Pods(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
list, err := client.CoreV1().Pods(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
||||||
var filteredItems []v1.Pod
|
var filteredItems []v1.Pod
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,7 +404,7 @@ func GetReplicationControllerListChannel(client client.Interface,
|
||||||
List(context.TODO(), helpers.ListEverything)
|
List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []v1.ReplicationController
|
var filteredItems []v1.ReplicationController
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -436,7 +439,7 @@ func GetDeploymentListChannel(client client.Interface,
|
||||||
List(context.TODO(), helpers.ListEverything)
|
List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []apps.Deployment
|
var filteredItems []apps.Deployment
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -477,7 +480,7 @@ func GetReplicaSetListChannelWithOptions(client client.Interface, nsQuery *Names
|
||||||
List(context.TODO(), options)
|
List(context.TODO(), options)
|
||||||
var filteredItems []apps.ReplicaSet
|
var filteredItems []apps.ReplicaSet
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -509,7 +512,7 @@ func GetDaemonSetListChannel(client client.Interface, nsQuery *NamespaceQuery, n
|
||||||
list, err := client.AppsV1().DaemonSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.AppsV1().DaemonSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []apps.DaemonSet
|
var filteredItems []apps.DaemonSet
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -541,7 +544,7 @@ func GetJobListChannel(client client.Interface,
|
||||||
list, err := client.BatchV1().Jobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.BatchV1().Jobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []batch.Job
|
var filteredItems []batch.Job
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +575,7 @@ func GetCronJobListChannel(client client.Interface, nsQuery *NamespaceQuery, num
|
||||||
list, err := client.BatchV1().CronJobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.BatchV1().CronJobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []batch.CronJob
|
var filteredItems []batch.CronJob
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -605,7 +608,7 @@ func GetStatefulSetListChannel(client client.Interface,
|
||||||
statefulSets, err := client.AppsV1().StatefulSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
statefulSets, err := client.AppsV1().StatefulSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []apps.StatefulSet
|
var filteredItems []apps.StatefulSet
|
||||||
for _, item := range statefulSets.Items {
|
for _, item := range statefulSets.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -639,7 +642,7 @@ func GetConfigMapListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
||||||
list, err := client.CoreV1().ConfigMaps(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.CoreV1().ConfigMaps(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []v1.ConfigMap
|
var filteredItems []v1.ConfigMap
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -673,7 +676,7 @@ func GetSecretListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
||||||
list, err := client.CoreV1().Secrets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
list, err := client.CoreV1().Secrets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
var filteredItems []v1.Secret
|
var filteredItems []v1.Secret
|
||||||
for _, item := range list.Items {
|
for _, item := range list.Items {
|
||||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
if nsQuery.Matches(item.Namespace) {
|
||||||
filteredItems = append(filteredItems, item)
|
filteredItems = append(filteredItems, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -841,6 +844,30 @@ func GetPersistentVolumeClaimListChannel(client client.Interface, nsQuery *Names
|
||||||
return channel
|
return channel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PodDisruptionBudgetListChannel struct {
|
||||||
|
List chan *policyv1.PodDisruptionBudgetList
|
||||||
|
Error chan error
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPodDisruptionBudgetListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
||||||
|
numReads int) PodDisruptionBudgetListChannel {
|
||||||
|
|
||||||
|
channel := PodDisruptionBudgetListChannel{
|
||||||
|
List: make(chan *policyv1.PodDisruptionBudgetList, numReads),
|
||||||
|
Error: make(chan error, numReads),
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
list, err := client.PolicyV1().PodDisruptionBudgets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||||
|
for i := 0; i < numReads; i++ {
|
||||||
|
channel.List <- list
|
||||||
|
channel.Error <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
return channel
|
||||||
|
}
|
||||||
|
|
||||||
// CustomResourceDefinitionChannelV1 is a list and error channels to CustomResourceDefinition.
|
// CustomResourceDefinitionChannelV1 is a list and error channels to CustomResourceDefinition.
|
||||||
type CustomResourceDefinitionChannelV1 struct {
|
type CustomResourceDefinitionChannelV1 struct {
|
||||||
List chan *apiextensions.CustomResourceDefinitionList
|
List chan *apiextensions.CustomResourceDefinitionList
|
||||||
|
|
|
@ -27,7 +27,7 @@ func FilterNamespacedServicesBySelector(services []v1.Service, namespace string,
|
||||||
|
|
||||||
var matchingServices []v1.Service
|
var matchingServices []v1.Service
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
if service.ObjectMeta.Namespace == namespace &&
|
if service.Namespace == namespace &&
|
||||||
helpers.IsSelectorMatching(service.Spec.Selector, resourceSelector) {
|
helpers.IsSelectorMatching(service.Spec.Selector, resourceSelector) {
|
||||||
matchingServices = append(matchingServices, service)
|
matchingServices = append(matchingServices, service)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
|
|
||||||
type ConfigMapCell api.ConfigMap
|
type ConfigMapCell api.ConfigMap
|
||||||
|
|
||||||
func (self ConfigMapCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in ConfigMapCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,11 +16,11 @@ package configmap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ConfigMapDetail API resource provides mechanisms to inject containers with configuration data while keeping
|
// ConfigMapDetail API resource provides mechanisms to inject containers with configuration data while keeping
|
||||||
|
@ -36,7 +36,7 @@ type ConfigMapDetail struct {
|
||||||
|
|
||||||
// GetConfigMapDetail returns detailed information about a config map
|
// GetConfigMapDetail returns detailed information about a config map
|
||||||
func GetConfigMapDetail(client kubernetes.Interface, namespace, name string) (*ConfigMapDetail, error) {
|
func GetConfigMapDetail(client kubernetes.Interface, namespace, name string) (*ConfigMapDetail, error) {
|
||||||
log.Printf("Getting details of %s config map in %s namespace", name, namespace)
|
klog.V(4).Infof("Getting details of %s config map in %s namespace", name, namespace)
|
||||||
|
|
||||||
rawConfigMap, err := client.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
rawConfigMap, err := client.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
package configmap
|
package configmap
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -47,7 +46,7 @@ type ConfigMap struct {
|
||||||
|
|
||||||
// GetConfigMapList returns a list of all ConfigMaps in the cluster.
|
// GetConfigMapList returns a list of all ConfigMaps in the cluster.
|
||||||
func GetConfigMapList(client kubernetes.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*ConfigMapList, error) {
|
func GetConfigMapList(client kubernetes.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*ConfigMapList, error) {
|
||||||
log.Printf("Getting list config maps in the namespace %s", nsQuery.ToRequestParam())
|
klog.V(4).Infof("Getting list config maps in the namespace %s", nsQuery.ToRequestParam())
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
ConfigMapList: common.GetConfigMapListChannel(client, nsQuery, 1),
|
ConfigMapList: common.GetConfigMapListChannel(client, nsQuery, 1),
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,46 +112,46 @@ func NewResourceController(ref meta.OwnerReference, namespace string, client cli
|
||||||
type JobController batch.Job
|
type JobController batch.Job
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self JobController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
func (in JobController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsForJob(batch.Job(self), allPods)
|
matchingPods := common.FilterPodsForJob(batch.Job(in), allPods)
|
||||||
podInfo := common.GetPodInfo(self.Status.Active, self.Spec.Completions, matchingPods)
|
podInfo := common.GetPodInfo(in.Status.Active, in.Spec.Completions, matchingPods)
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindJob),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindJob),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self JobController) UID() apimachinery.UID {
|
func (in JobController) UID() apimachinery.UID {
|
||||||
return batch.Job(self).UID
|
return batch.Job(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self JobController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in JobController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsForJob(batch.Job(self), allPods)
|
controlledPods := common.FilterPodsForJob(batch.Job(in), allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type PodController v1.Pod
|
type PodController v1.Pod
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
func (in PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
podInfo := common.GetPodInfo(int32(len(matchingPods)), nil, matchingPods) // Pods should not desire any Pods
|
podInfo := common.GetPodInfo(int32(len(matchingPods)), nil, matchingPods) // Pods should not desire any Pods
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetNonduplicateContainerImages(matchingPods),
|
ContainerImages: common.GetNonduplicateContainerImages(matchingPods),
|
||||||
InitContainerImages: common.GetNonduplicateInitContainerImages(matchingPods),
|
InitContainerImages: common.GetNonduplicateInitContainerImages(matchingPods),
|
||||||
|
@ -159,13 +159,13 @@ func (self PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOw
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self PodController) UID() apimachinery.UID {
|
func (in PodController) UID() apimachinery.UID {
|
||||||
return v1.Pod(self).UID
|
return v1.Pod(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetNonduplicateContainerNames(controlledPods),
|
ContainerNames: common.GetNonduplicateContainerNames(controlledPods),
|
||||||
|
@ -178,32 +178,32 @@ func (self PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
type ReplicaSetController apps.ReplicaSet
|
type ReplicaSetController apps.ReplicaSet
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self ReplicaSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
func (in ReplicaSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicaSet),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicaSet),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self ReplicaSetController) UID() apimachinery.UID {
|
func (in ReplicaSetController) UID() apimachinery.UID {
|
||||||
return apps.ReplicaSet(self).UID
|
return apps.ReplicaSet(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,33 +212,33 @@ func (self ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
type ReplicationControllerController v1.ReplicationController
|
type ReplicationControllerController v1.ReplicationController
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self ReplicationControllerController) Get(allPods []v1.Pod,
|
func (in ReplicationControllerController) Get(allPods []v1.Pod,
|
||||||
allEvents []v1.Event) ResourceOwner {
|
allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicationController),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicationController),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self ReplicationControllerController) UID() apimachinery.UID {
|
func (in ReplicationControllerController) UID() apimachinery.UID {
|
||||||
return v1.ReplicationController(self).UID
|
return v1.ReplicationController(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -247,33 +247,33 @@ func (self ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogS
|
||||||
type DaemonSetController apps.DaemonSet
|
type DaemonSetController apps.DaemonSet
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self DaemonSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
func (in DaemonSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
podInfo := common.GetPodInfo(self.Status.CurrentNumberScheduled,
|
podInfo := common.GetPodInfo(in.Status.CurrentNumberScheduled,
|
||||||
&self.Status.DesiredNumberScheduled, matchingPods)
|
&in.Status.DesiredNumberScheduled, matchingPods)
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindDaemonSet),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindDaemonSet),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self DaemonSetController) UID() apimachinery.UID {
|
func (in DaemonSetController) UID() apimachinery.UID {
|
||||||
return apps.DaemonSet(self).UID
|
return apps.DaemonSet(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,32 +282,32 @@ func (self DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
type StatefulSetController apps.StatefulSet
|
type StatefulSetController apps.StatefulSet
|
||||||
|
|
||||||
// Get is an implementation of Get method from ResourceController interface.
|
// Get is an implementation of Get method from ResourceController interface.
|
||||||
func (self StatefulSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
func (in StatefulSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||||
|
|
||||||
return ResourceOwner{
|
return ResourceOwner{
|
||||||
TypeMeta: types.NewTypeMeta(types.ResourceKindStatefulSet),
|
TypeMeta: types.NewTypeMeta(types.ResourceKindStatefulSet),
|
||||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||||
Pods: podInfo,
|
Pods: podInfo,
|
||||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UID is an implementation of UID method from ResourceController interface.
|
// UID is an implementation of UID method from ResourceController interface.
|
||||||
func (self StatefulSetController) UID() apimachinery.UID {
|
func (in StatefulSetController) UID() apimachinery.UID {
|
||||||
return apps.StatefulSet(self).UID
|
return apps.StatefulSet(in).UID
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||||
func (self StatefulSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
func (in StatefulSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||||
return LogSources{
|
return LogSources{
|
||||||
PodNames: getPodNames(controlledPods),
|
PodNames: getPodNames(controlledPods),
|
||||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,26 +27,26 @@ import (
|
||||||
|
|
||||||
type CronJobCell batch.CronJob
|
type CronJobCell batch.CronJob
|
||||||
|
|
||||||
func (self CronJobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in CronJobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self CronJobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
func (in CronJobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||||
return &metricapi.ResourceSelector{
|
return &metricapi.ResourceSelector{
|
||||||
Namespace: self.ObjectMeta.Namespace,
|
Namespace: in.Namespace,
|
||||||
ResourceType: types.ResourceKindCronJob,
|
ResourceType: types.ResourceKindCronJob,
|
||||||
ResourceName: self.ObjectMeta.Name,
|
ResourceName: in.Name,
|
||||||
UID: self.UID,
|
UID: in.UID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,16 +114,11 @@ func TriggerCronJob(client client.Interface,
|
||||||
|
|
||||||
jobToCreate := &batch.Job{
|
jobToCreate := &batch.Job{
|
||||||
ObjectMeta: meta.ObjectMeta{
|
ObjectMeta: meta.ObjectMeta{
|
||||||
Name: newJobName,
|
Name: newJobName,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Annotations: annotations,
|
Annotations: annotations,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
OwnerReferences: []meta.OwnerReference{{
|
OwnerReferences: []meta.OwnerReference{*meta.NewControllerRef(cronJob, batch.SchemeGroupVersion.WithKind("CronJob"))},
|
||||||
APIVersion: CronJobAPIVersion,
|
|
||||||
Kind: CronJobKindName,
|
|
||||||
Name: cronJob.Name,
|
|
||||||
UID: cronJob.UID,
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
Spec: cronJob.Spec.JobTemplate.Spec,
|
Spec: cronJob.Spec.JobTemplate.Spec,
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
package cronjob
|
package cronjob
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
batch "k8s.io/api/batch/v1"
|
batch "k8s.io/api/batch/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -55,7 +54,7 @@ type CronJob struct {
|
||||||
// GetCronJobList returns a list of all CronJobs in the cluster.
|
// GetCronJobList returns a list of all CronJobs in the cluster.
|
||||||
func GetCronJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
func GetCronJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
||||||
dsQuery *dataselect.DataSelectQuery) (*CronJobList, error) {
|
dsQuery *dataselect.DataSelectQuery) (*CronJobList, error) {
|
||||||
log.Print("Getting list of all cron jobs in the cluster")
|
klog.V(4).Infof("Getting list of all cron jobs in the cluster")
|
||||||
|
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
CronJobList: common.GetCronJobListChannel(client, nsQuery, 1),
|
CronJobList: common.GetCronJobListChannel(client, nsQuery, 1),
|
||||||
|
|
|
@ -48,20 +48,6 @@ func GetExtensionsAPIVersion(client apiextensionsclientset.Interface) (string, e
|
||||||
return "", errors.NewNotFound("supported version for extensions api not found")
|
return "", errors.NewNotFound("supported version for extensions api not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetExtensionsAPIRestClient(client apiextensionsclientset.Interface) (rest.Interface, error) {
|
|
||||||
version, err := GetExtensionsAPIVersion(client)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
switch version {
|
|
||||||
case v1:
|
|
||||||
return client.ApiextensionsV1().RESTClient(), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, errors.NewNotFound(fmt.Sprintf("unsupported extensions api version: %s", version))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCustomResourceDefinitionList(client apiextensionsclientset.Interface, dsQuery *dataselect.DataSelectQuery) (*types.CustomResourceDefinitionList, error) {
|
func GetCustomResourceDefinitionList(client apiextensionsclientset.Interface, dsQuery *dataselect.DataSelectQuery) (*types.CustomResourceDefinitionList, error) {
|
||||||
version, err := GetExtensionsAPIVersion(client)
|
version, err := GetExtensionsAPIVersion(client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -82,7 +82,7 @@ func (r *CustomResourceObject) UnmarshalJSON(data []byte) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.TypeMeta = types.NewTypeMeta(types.ResourceKind(tempStruct.TypeMeta.Kind))
|
r.TypeMeta = types.NewTypeMeta(types.ResourceKind(tempStruct.Kind))
|
||||||
r.ObjectMeta = types.NewObjectMeta(tempStruct.ObjectMeta)
|
r.ObjectMeta = types.NewObjectMeta(tempStruct.ObjectMeta)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,12 +25,12 @@ import (
|
||||||
|
|
||||||
type CustomResourceDefinitionCell apiextensions.CustomResourceDefinition
|
type CustomResourceDefinitionCell apiextensions.CustomResourceDefinition
|
||||||
|
|
||||||
func (self CustomResourceDefinitionCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in CustomResourceDefinitionCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
@ -58,14 +58,14 @@ func fromCells(cells []dataselect.DataCell) []apiextensions.CustomResourceDefini
|
||||||
// The code below allows to perform complex data section on CustomResourceObject.
|
// The code below allows to perform complex data section on CustomResourceObject.
|
||||||
type CustomResourceObjectCell types.CustomResourceObject
|
type CustomResourceObjectCell types.CustomResourceObject
|
||||||
|
|
||||||
func (self CustomResourceObjectCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in CustomResourceObjectCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -67,26 +67,26 @@ func GetServicesForDSDeletion(client client.Interface, labelSelector labels.Sele
|
||||||
|
|
||||||
type DaemonSetCell apps.DaemonSet
|
type DaemonSetCell apps.DaemonSet
|
||||||
|
|
||||||
func (self DaemonSetCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in DaemonSetCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self DaemonSetCell) GetResourceSelector() *metricapi.ResourceSelector {
|
func (in DaemonSetCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||||
return &metricapi.ResourceSelector{
|
return &metricapi.ResourceSelector{
|
||||||
Namespace: self.ObjectMeta.Namespace,
|
Namespace: in.Namespace,
|
||||||
ResourceType: types.ResourceKindDaemonSet,
|
ResourceType: types.ResourceKindDaemonSet,
|
||||||
ResourceName: self.ObjectMeta.Name,
|
ResourceName: in.Name,
|
||||||
UID: self.UID,
|
UID: in.UID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,11 @@ package daemonset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
)
|
)
|
||||||
|
@ -39,7 +40,7 @@ type DaemonSetDetail struct {
|
||||||
func GetDaemonSetDetail(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
func GetDaemonSetDetail(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||||
namespace, name string) (*DaemonSetDetail, error) {
|
namespace, name string) (*DaemonSetDetail, error) {
|
||||||
|
|
||||||
log.Printf("Getting details of %s daemon set in %s namespace", name, namespace)
|
klog.V(4).Infof("Getting details of %s daemon set in %s namespace", name, namespace)
|
||||||
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -106,7 +106,7 @@ func TestGetDaemonSetListFromChannels(t *testing.T) {
|
||||||
Labels: map[string]string{"key": "value"},
|
Labels: map[string]string{"key": "value"},
|
||||||
CreationTimestamp: metaV1.Unix(111, 222),
|
CreationTimestamp: metaV1.Unix(111, 222),
|
||||||
},
|
},
|
||||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||||
Pods: common.PodInfo{
|
Pods: common.PodInfo{
|
||||||
Current: 0,
|
Current: 0,
|
||||||
Failed: 0,
|
Failed: 0,
|
||||||
|
@ -351,7 +351,7 @@ func TestToDaemonSetList(t *testing.T) {
|
||||||
Namespace: "namespace-1",
|
Namespace: "namespace-1",
|
||||||
UID: "uid-1",
|
UID: "uid-1",
|
||||||
},
|
},
|
||||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||||
ContainerImages: []string{"my-container-image-1"},
|
ContainerImages: []string{"my-container-image-1"},
|
||||||
InitContainerImages: []string{"my-init-container-image-1"},
|
InitContainerImages: []string{"my-init-container-image-1"},
|
||||||
Pods: common.PodInfo{
|
Pods: common.PodInfo{
|
||||||
|
@ -367,7 +367,7 @@ func TestToDaemonSetList(t *testing.T) {
|
||||||
Name: "my-app-2",
|
Name: "my-app-2",
|
||||||
Namespace: "namespace-2",
|
Namespace: "namespace-2",
|
||||||
},
|
},
|
||||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||||
ContainerImages: []string{"my-container-image-2"},
|
ContainerImages: []string{"my-container-image-2"},
|
||||||
InitContainerImages: []string{"my-init-container-image-2"},
|
InitContainerImages: []string{"my-init-container-image-2"},
|
||||||
Pods: common.PodInfo{
|
Pods: common.PodInfo{
|
||||||
|
@ -379,7 +379,7 @@ func TestToDaemonSetList(t *testing.T) {
|
||||||
Name: "my-app-3",
|
Name: "my-app-3",
|
||||||
Namespace: "namespace-3",
|
Namespace: "namespace-3",
|
||||||
},
|
},
|
||||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||||
ContainerImages: []string{"my-container-image-3"},
|
ContainerImages: []string{"my-container-image-3"},
|
||||||
InitContainerImages: []string{"my-init-container-image-3"},
|
InitContainerImages: []string{"my-init-container-image-3"},
|
||||||
Pods: common.PodInfo{
|
Pods: common.PodInfo{
|
||||||
|
|
|
@ -16,11 +16,12 @@ package daemonset
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -32,7 +33,7 @@ import (
|
||||||
// GetDaemonSetPods return list of pods targeting daemon set.
|
// GetDaemonSetPods return list of pods targeting daemon set.
|
||||||
func GetDaemonSetPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
func GetDaemonSetPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||||
dsQuery *dataselect.DataSelectQuery, daemonSetName, namespace string) (*pod.PodList, error) {
|
dsQuery *dataselect.DataSelectQuery, daemonSetName, namespace string) (*pod.PodList, error) {
|
||||||
log.Printf("Getting replication controller %s pods in namespace %s", daemonSetName, namespace)
|
klog.V(4).Infof("Getting replication controller %s pods in namespace %s", daemonSetName, namespace)
|
||||||
|
|
||||||
pods, err := getRawDaemonSetPods(client, daemonSetName, namespace)
|
pods, err := getRawDaemonSetPods(client, daemonSetName, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
// Copyright 2017 The Kubernetes Authors.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package daemonset
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
v1 "k8s.io/api/apps/v1"
|
||||||
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// RestartedAtAnnotationKey is an annotation key for rollout restart
|
||||||
|
RestartedAtAnnotationKey = "kubectl.kubernetes.io/restartedAt"
|
||||||
|
)
|
||||||
|
|
||||||
|
// RestartDaemonSet restarts a daemon set in the manner of `kubectl rollout restart`.
|
||||||
|
func RestartDaemonSet(client client.Interface, namespace, name string) (*v1.DaemonSet, error) {
|
||||||
|
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if daemonSet.Spec.Template.Annotations == nil {
|
||||||
|
daemonSet.Spec.Template.Annotations = map[string]string{}
|
||||||
|
}
|
||||||
|
daemonSet.Spec.Template.Annotations[RestartedAtAnnotationKey] = time.Now().Format(time.RFC3339)
|
||||||
|
return client.AppsV1().DaemonSets(namespace).Update(context.TODO(), daemonSet, metaV1.UpdateOptions{})
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ import (
|
||||||
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/dashboard/api/pkg/args"
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/errors"
|
"k8s.io/dashboard/errors"
|
||||||
)
|
)
|
||||||
|
@ -43,9 +44,9 @@ type MetricDataCell interface {
|
||||||
|
|
||||||
// ComparableValue hold any value that can be compared to its own kind.
|
// ComparableValue hold any value that can be compared to its own kind.
|
||||||
type ComparableValue interface {
|
type ComparableValue interface {
|
||||||
// Compares self with other value. Returns 1 if other value is smaller, 0 if they are the same, -1 if other is larger.
|
// Compares in with other value. Returns 1 if other value is smaller, 0 if they are the same, -1 if other is larger.
|
||||||
Compare(ComparableValue) int
|
Compare(ComparableValue) int
|
||||||
// Returns true if self value contains or is equal to other value, false otherwise.
|
// Returns true if in value contains or is equal to other value, false otherwise.
|
||||||
Contains(ComparableValue) bool
|
Contains(ComparableValue) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,18 +72,18 @@ type DataSelector struct {
|
||||||
// Implementation of sort.Interface so that we can use built-in sort function (sort.Sort) for sorting SelectableData
|
// Implementation of sort.Interface so that we can use built-in sort function (sort.Sort) for sorting SelectableData
|
||||||
|
|
||||||
// Len returns the length of data inside SelectableData.
|
// Len returns the length of data inside SelectableData.
|
||||||
func (self DataSelector) Len() int { return len(self.GenericDataList) }
|
func (in DataSelector) Len() int { return len(in.GenericDataList) }
|
||||||
|
|
||||||
// Swap swaps 2 indices inside SelectableData.
|
// Swap swaps 2 indices inside SelectableData.
|
||||||
func (self DataSelector) Swap(i, j int) {
|
func (in DataSelector) Swap(i, j int) {
|
||||||
self.GenericDataList[i], self.GenericDataList[j] = self.GenericDataList[j], self.GenericDataList[i]
|
in.GenericDataList[i], in.GenericDataList[j] = in.GenericDataList[j], in.GenericDataList[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Less compares 2 indices inside SelectableData and returns true if first index is larger.
|
// Less compares 2 indices inside SelectableData and returns true if first index is larger.
|
||||||
func (self DataSelector) Less(i, j int) bool {
|
func (in DataSelector) Less(i, j int) bool {
|
||||||
for _, sortBy := range self.DataSelectQuery.SortQuery.SortByList {
|
for _, sortBy := range in.DataSelectQuery.SortQuery.SortByList {
|
||||||
a := self.GenericDataList[i].GetProperty(sortBy.Property)
|
a := in.GenericDataList[i].GetProperty(sortBy.Property)
|
||||||
b := self.GenericDataList[j].GetProperty(sortBy.Property)
|
b := in.GenericDataList[j].GetProperty(sortBy.Property)
|
||||||
// ignore sort completely if property name not found
|
// ignore sort completely if property name not found
|
||||||
if a == nil || b == nil {
|
if a == nil || b == nil {
|
||||||
break
|
break
|
||||||
|
@ -97,19 +98,19 @@ func (self DataSelector) Less(i, j int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort sorts the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
// Sort sorts the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||||
func (self *DataSelector) Sort() *DataSelector {
|
func (in *DataSelector) Sort() *DataSelector {
|
||||||
sort.Sort(*self)
|
sort.Sort(*in)
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
// Filter the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||||
func (self *DataSelector) Filter() *DataSelector {
|
func (in *DataSelector) Filter() *DataSelector {
|
||||||
filteredList := []DataCell{}
|
filteredList := []DataCell{}
|
||||||
|
|
||||||
for _, c := range self.GenericDataList {
|
for _, c := range in.GenericDataList {
|
||||||
matches := true
|
matches := true
|
||||||
for _, filterBy := range self.DataSelectQuery.FilterQuery.FilterByList {
|
for _, filterBy := range in.DataSelectQuery.FilterQuery.FilterByList {
|
||||||
v := c.GetProperty(filterBy.Property)
|
v := c.GetProperty(filterBy.Property)
|
||||||
if v == nil || !v.Contains(filterBy.Value) {
|
if v == nil || !v.Contains(filterBy.Value) {
|
||||||
matches = false
|
matches = false
|
||||||
|
@ -121,11 +122,11 @@ func (self *DataSelector) Filter() *DataSelector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.GenericDataList = filteredList
|
in.GenericDataList = filteredList
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
func (in *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
||||||
[]metricapi.MetricPromises, error) {
|
[]metricapi.MetricPromises, error) {
|
||||||
metricPromises := make([]metricapi.MetricPromises, 0)
|
metricPromises := make([]metricapi.MetricPromises, 0)
|
||||||
|
|
||||||
|
@ -133,13 +134,13 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
||||||
return metricPromises, nil
|
return metricPromises, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
|
metricNames := in.DataSelectQuery.MetricQuery.MetricNames
|
||||||
if metricNames == nil {
|
if metricNames == nil {
|
||||||
return metricPromises, errors.NewInternal("No metrics specified. Skipping metrics.")
|
return metricPromises, errors.NewInternal("No metrics specified. Skipping metrics.")
|
||||||
}
|
}
|
||||||
|
|
||||||
selectors := make([]metricapi.ResourceSelector, len(self.GenericDataList))
|
selectors := make([]metricapi.ResourceSelector, len(in.GenericDataList))
|
||||||
for i, dataCell := range self.GenericDataList {
|
for i, dataCell := range in.GenericDataList {
|
||||||
// make sure data cells support metrics
|
// make sure data cells support metrics
|
||||||
metricDataCell, ok := dataCell.(MetricDataCell)
|
metricDataCell, ok := dataCell.(MetricDataCell)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -151,24 +152,24 @@ func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, metricName := range metricNames {
|
for _, metricName := range metricNames {
|
||||||
promises := metricClient.DownloadMetric(selectors, metricName, self.CachedResources)
|
promises := metricClient.DownloadMetric(selectors, metricName, in.CachedResources)
|
||||||
metricPromises = append(metricPromises, promises)
|
metricPromises = append(metricPromises, promises)
|
||||||
}
|
}
|
||||||
|
|
||||||
return metricPromises, nil
|
return metricPromises, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetMetrics downloads metrics for data cells currently present in self.GenericDataList as instructed
|
// GetMetrics downloads metrics for data cells currently present in in.GenericDataList as instructed
|
||||||
// by MetricQuery and inserts resulting MetricPromises to self.MetricsPromises.
|
// by MetricQuery and inserts resulting MetricPromises to in.MetricsPromises.
|
||||||
func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
func (in *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||||
metricPromisesList, err := self.getMetrics(metricClient)
|
metricPromisesList, err := in.getMetrics(metricClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "error during getting metrics")
|
klog.ErrorS(err, "error during getting metrics")
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metricPromisesList) == 0 {
|
if len(metricPromisesList) == 0 {
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
metricPromises := make(metricapi.MetricPromises, 0)
|
metricPromises := make(metricapi.MetricPromises, 0)
|
||||||
|
@ -176,30 +177,30 @@ func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataS
|
||||||
metricPromises = append(metricPromises, promises...)
|
metricPromises = append(metricPromises, promises...)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.MetricsPromises = metricPromises
|
in.MetricsPromises = metricPromises
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetCumulativeMetrics downloads and aggregates metrics for data cells currently present in self.GenericDataList as instructed
|
// GetCumulativeMetrics downloads and aggregates metrics for data cells currently present in in.GenericDataList as instructed
|
||||||
// by MetricQuery and inserts resulting MetricPromises to self.CumulativeMetricsPromises.
|
// by MetricQuery and inserts resulting MetricPromises to in.CumulativeMetricsPromises.
|
||||||
func (self *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
func (in *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||||
metricPromisesList, err := self.getMetrics(metricClient)
|
metricPromisesList, err := in.getMetrics(metricClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.ErrorS(err, "error during getting metrics")
|
klog.ErrorS(err, "error during getting metrics")
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(metricPromisesList) == 0 {
|
if len(metricPromisesList) == 0 {
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
|
metricNames := in.DataSelectQuery.MetricQuery.MetricNames
|
||||||
if metricNames == nil {
|
if metricNames == nil {
|
||||||
klog.V(1).Info("Metrics names not provided. Skipping.")
|
klog.V(args.LogLevelVerbose).Info("Metrics names not provided. Skipping.")
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
aggregations := self.DataSelectQuery.MetricQuery.Aggregations
|
aggregations := in.DataSelectQuery.MetricQuery.Aggregations
|
||||||
if aggregations == nil {
|
if aggregations == nil {
|
||||||
aggregations = metricapi.OnlyDefaultAggregation
|
aggregations = metricapi.OnlyDefaultAggregation
|
||||||
}
|
}
|
||||||
|
@ -210,28 +211,28 @@ func (self *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClie
|
||||||
metricPromises = append(metricPromises, promises...)
|
metricPromises = append(metricPromises, promises...)
|
||||||
}
|
}
|
||||||
|
|
||||||
self.CumulativeMetricsPromises = metricPromises
|
in.CumulativeMetricsPromises = metricPromises
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// Paginates the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
// Paginates the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||||
func (self *DataSelector) Paginate() *DataSelector {
|
func (in *DataSelector) Paginate() *DataSelector {
|
||||||
pQuery := self.DataSelectQuery.PaginationQuery
|
pQuery := in.DataSelectQuery.PaginationQuery
|
||||||
dataList := self.GenericDataList
|
dataList := in.GenericDataList
|
||||||
startIndex, endIndex := pQuery.GetPaginationSettings(len(dataList))
|
startIndex, endIndex := pQuery.GetPaginationSettings(len(dataList))
|
||||||
|
|
||||||
// Return all items if provided settings do not meet requirements
|
// Return all items if provided settings do not meet requirements
|
||||||
if !pQuery.IsValidPagination() {
|
if !pQuery.IsValidPagination() {
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
// Return no items if requested page does not exist
|
// Return no items if requested page does not exist
|
||||||
if !pQuery.IsPageAvailable(len(self.GenericDataList), startIndex) {
|
if !pQuery.IsPageAvailable(len(in.GenericDataList), startIndex) {
|
||||||
self.GenericDataList = []DataCell{}
|
in.GenericDataList = []DataCell{}
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
self.GenericDataList = dataList[startIndex:endIndex]
|
in.GenericDataList = dataList[startIndex:endIndex]
|
||||||
return self
|
return in
|
||||||
}
|
}
|
||||||
|
|
||||||
// GenericDataSelect takes a list of GenericDataCells and DataSelectQuery and returns selected data as instructed by dsQuery.
|
// GenericDataSelect takes a list of GenericDataCells and DataSelectQuery and returns selected data as instructed by dsQuery.
|
||||||
|
|
|
@ -36,12 +36,12 @@ type TestDataCell struct {
|
||||||
Id int
|
Id int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self TestDataCell) GetProperty(name PropertyName) ComparableValue {
|
func (in TestDataCell) GetProperty(name PropertyName) ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case NameProperty:
|
case NameProperty:
|
||||||
return StdComparableString(self.Name)
|
return StdComparableString(in.Name)
|
||||||
case CreationTimestampProperty:
|
case CreationTimestampProperty:
|
||||||
return StdComparableInt(self.Id)
|
return StdComparableInt(in.Id)
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,11 +119,12 @@ func NewSortQuery(sortByListRaw []string) *SortQuery {
|
||||||
// parse order option
|
// parse order option
|
||||||
var ascending bool
|
var ascending bool
|
||||||
orderOption := sortByListRaw[i]
|
orderOption := sortByListRaw[i]
|
||||||
if orderOption == "a" {
|
switch orderOption {
|
||||||
|
case "a":
|
||||||
ascending = true
|
ascending = true
|
||||||
} else if orderOption == "d" {
|
case "d":
|
||||||
ascending = false
|
ascending = false
|
||||||
} else {
|
default:
|
||||||
// Invalid order option. Only ascending (a), descending (d) options are supported
|
// Invalid order option. Only ascending (a), descending (d) options are supported
|
||||||
return NoSort
|
return NoSort
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,60 +23,60 @@ import (
|
||||||
// These types specify how given value should be compared
|
// These types specify how given value should be compared
|
||||||
// They all implement ComparableValueInterface
|
// They all implement ComparableValueInterface
|
||||||
// You can convert basic types to these types to support auto sorting etc.
|
// You can convert basic types to these types to support auto sorting etc.
|
||||||
// If you can't find your type compare here you will have to implement it yourself :)
|
// If you can't find your type compare here you will have to implement it yourin :)
|
||||||
|
|
||||||
type StdComparableInt int
|
type StdComparableInt int
|
||||||
|
|
||||||
func (self StdComparableInt) Compare(otherV ComparableValue) int {
|
func (in StdComparableInt) Compare(otherV ComparableValue) int {
|
||||||
other := otherV.(StdComparableInt)
|
other := otherV.(StdComparableInt)
|
||||||
return intsCompare(int(self), int(other))
|
return intsCompare(int(in), int(other))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self StdComparableInt) Contains(otherV ComparableValue) bool {
|
func (in StdComparableInt) Contains(otherV ComparableValue) bool {
|
||||||
return self.Compare(otherV) == 0
|
return in.Compare(otherV) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type StdComparableString string
|
type StdComparableString string
|
||||||
|
|
||||||
func (self StdComparableString) Compare(otherV ComparableValue) int {
|
func (in StdComparableString) Compare(otherV ComparableValue) int {
|
||||||
other := otherV.(StdComparableString)
|
other := otherV.(StdComparableString)
|
||||||
return strings.Compare(string(self), string(other))
|
return strings.Compare(string(in), string(other))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self StdComparableString) Contains(otherV ComparableValue) bool {
|
func (in StdComparableString) Contains(otherV ComparableValue) bool {
|
||||||
other := otherV.(StdComparableString)
|
other := otherV.(StdComparableString)
|
||||||
return strings.Contains(string(self), string(other))
|
return strings.Contains(string(in), string(other))
|
||||||
}
|
}
|
||||||
|
|
||||||
// StdComparableRFC3339Timestamp takes RFC3339 Timestamp strings and compares them as TIMES. In case of time parsing error compares values as strings.
|
// StdComparableRFC3339Timestamp takes RFC3339 Timestamp strings and compares them as TIMES. In case of time parsing error compares values as strings.
|
||||||
type StdComparableRFC3339Timestamp string
|
type StdComparableRFC3339Timestamp string
|
||||||
|
|
||||||
func (self StdComparableRFC3339Timestamp) Compare(otherV ComparableValue) int {
|
func (in StdComparableRFC3339Timestamp) Compare(otherV ComparableValue) int {
|
||||||
other := otherV.(StdComparableRFC3339Timestamp)
|
other := otherV.(StdComparableRFC3339Timestamp)
|
||||||
// try to compare as timestamp (earlier = smaller)
|
// try to compare as timestamp (earlier = smaller)
|
||||||
selfTime, err1 := time.Parse(time.RFC3339, string(self))
|
inTime, err1 := time.Parse(time.RFC3339, string(in))
|
||||||
otherTime, err2 := time.Parse(time.RFC3339, string(other))
|
otherTime, err2 := time.Parse(time.RFC3339, string(other))
|
||||||
|
|
||||||
if err1 != nil || err2 != nil {
|
if err1 != nil || err2 != nil {
|
||||||
// in case of timestamp parsing failure just compare as strings
|
// in case of timestamp parsing failure just compare as strings
|
||||||
return strings.Compare(string(self), string(other))
|
return strings.Compare(string(in), string(other))
|
||||||
}
|
}
|
||||||
return ints64Compare(selfTime.Unix(), otherTime.Unix())
|
return ints64Compare(inTime.Unix(), otherTime.Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self StdComparableRFC3339Timestamp) Contains(otherV ComparableValue) bool {
|
func (in StdComparableRFC3339Timestamp) Contains(otherV ComparableValue) bool {
|
||||||
return self.Compare(otherV) == 0
|
return in.Compare(otherV) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
type StdComparableTime time.Time
|
type StdComparableTime time.Time
|
||||||
|
|
||||||
func (self StdComparableTime) Compare(otherV ComparableValue) int {
|
func (in StdComparableTime) Compare(otherV ComparableValue) int {
|
||||||
other := otherV.(StdComparableTime)
|
other := otherV.(StdComparableTime)
|
||||||
return ints64Compare(time.Time(self).Unix(), time.Time(other).Unix())
|
return ints64Compare(time.Time(in).Unix(), time.Time(other).Unix())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self StdComparableTime) Contains(otherV ComparableValue) bool {
|
func (in StdComparableTime) Contains(otherV ComparableValue) bool {
|
||||||
return self.Compare(otherV) == 0
|
return in.Compare(otherV) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Int comparison functions. Similar to strings.Compare.
|
// Int comparison functions. Similar to strings.Compare.
|
||||||
|
|
|
@ -30,27 +30,27 @@ import (
|
||||||
type DeploymentCell apps.Deployment
|
type DeploymentCell apps.Deployment
|
||||||
|
|
||||||
// GetProperty is used to get property of the deployment
|
// GetProperty is used to get property of the deployment
|
||||||
func (self DeploymentCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in DeploymentCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self DeploymentCell) GetResourceSelector() *metricapi.ResourceSelector {
|
func (in DeploymentCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||||
return &metricapi.ResourceSelector{
|
return &metricapi.ResourceSelector{
|
||||||
Namespace: self.ObjectMeta.Namespace,
|
Namespace: in.Namespace,
|
||||||
ResourceType: types.ResourceKindDeployment,
|
ResourceType: types.ResourceKindDeployment,
|
||||||
ResourceName: self.ObjectMeta.Name,
|
ResourceName: in.Name,
|
||||||
Selector: self.Spec.Selector.MatchLabels,
|
Selector: in.Spec.Selector.MatchLabels,
|
||||||
UID: self.UID,
|
UID: in.UID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,6 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
apps "k8s.io/api/apps/v1"
|
apps "k8s.io/api/apps/v1"
|
||||||
|
@ -35,7 +34,9 @@ import (
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/dashboard/api/pkg/args"
|
||||||
derrors "k8s.io/dashboard/errors"
|
derrors "k8s.io/dashboard/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -161,7 +162,7 @@ type Protocols struct {
|
||||||
// client. App deployment consists of a deployment and an optional service. Both of them
|
// client. App deployment consists of a deployment and an optional service. Both of them
|
||||||
// share common labels.
|
// share common labels.
|
||||||
func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
|
func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
|
||||||
log.Printf("Deploying %s application into %s namespace", spec.Name, spec.Namespace)
|
klog.V(args.LogLevelVerbose).Infof("Deploying %s application into %s namespace", spec.Name, spec.Namespace)
|
||||||
|
|
||||||
annotations := map[string]string{}
|
annotations := map[string]string{}
|
||||||
if spec.Description != nil {
|
if spec.Description != nil {
|
||||||
|
@ -304,7 +305,7 @@ func getLabelsMap(labels []Label) map[string]string {
|
||||||
// DeployAppFromFile deploys an app based on the given yaml or json file.
|
// DeployAppFromFile deploys an app based on the given yaml or json file.
|
||||||
func DeployAppFromFile(cfg *rest.Config, spec *AppDeploymentFromFileSpec) (bool, error) {
|
func DeployAppFromFile(cfg *rest.Config, spec *AppDeploymentFromFileSpec) (bool, error) {
|
||||||
reader := strings.NewReader(spec.Content)
|
reader := strings.NewReader(spec.Content)
|
||||||
log.Printf("Namespace for deploy from file: %s\n", spec.Namespace)
|
klog.V(args.LogLevelVerbose).Infof("Namespace for deploy from file: %s\n", spec.Namespace)
|
||||||
d := yaml.NewYAMLOrJSONDecoder(reader, 4096)
|
d := yaml.NewYAMLOrJSONDecoder(reader, 4096)
|
||||||
for {
|
for {
|
||||||
data := &unstructured.Unstructured{}
|
data := &unstructured.Unstructured{}
|
||||||
|
|
|
@ -16,12 +16,13 @@ package deployment
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
apps "k8s.io/api/apps/v1"
|
apps "k8s.io/api/apps/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/intstr"
|
"k8s.io/apimachinery/pkg/util/intstr"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/errors"
|
"k8s.io/dashboard/errors"
|
||||||
)
|
)
|
||||||
|
@ -82,7 +83,7 @@ type DeploymentDetail struct {
|
||||||
// GetDeploymentDetail returns model object of deployment and error, if any.
|
// GetDeploymentDetail returns model object of deployment and error, if any.
|
||||||
func GetDeploymentDetail(client client.Interface, namespace string, deploymentName string) (*DeploymentDetail, error) {
|
func GetDeploymentDetail(client client.Interface, namespace string, deploymentName string) (*DeploymentDetail, error) {
|
||||||
|
|
||||||
log.Printf("Getting details of %s deployment in %s namespace", deploymentName, namespace)
|
klog.V(4).Infof("Getting details of %s deployment in %s namespace", deploymentName, namespace)
|
||||||
|
|
||||||
deployment, err := client.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metaV1.GetOptions{})
|
deployment, err := client.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metaV1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
package deployment
|
package deployment
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
apps "k8s.io/api/apps/v1"
|
apps "k8s.io/api/apps/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
|
@ -64,7 +63,7 @@ type Deployment struct {
|
||||||
// GetDeploymentList returns a list of all Deployments in the cluster.
|
// GetDeploymentList returns a list of all Deployments in the cluster.
|
||||||
func GetDeploymentList(client client.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery,
|
func GetDeploymentList(client client.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery,
|
||||||
metricClient metricapi.MetricClient) (*DeploymentList, error) {
|
metricClient metricapi.MetricClient) (*DeploymentList, error) {
|
||||||
log.Print("Getting list of all deployments in the cluster")
|
klog.V(4).Infof("Getting list of all deployments in the cluster")
|
||||||
|
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
DeploymentList: common.GetDeploymentListChannel(client, nsQuery, 1),
|
DeploymentList: common.GetDeploymentListChannel(client, nsQuery, 1),
|
||||||
|
|
|
@ -47,7 +47,7 @@ func RollbackDeployment(client client.Interface, rolloutSpec *RolloutSpec, names
|
||||||
}
|
}
|
||||||
currRevision := deployment.Annotations[RevisionAnnotationKey]
|
currRevision := deployment.Annotations[RevisionAnnotationKey]
|
||||||
if currRevision == FirstRevision {
|
if currRevision == FirstRevision {
|
||||||
return nil, errors.New("No revision for rolling back ")
|
return nil, errors.New("no revision for rolling back")
|
||||||
}
|
}
|
||||||
matchRS, err := GetReplicaSetFromDeployment(client, namespace, name)
|
matchRS, err := GetReplicaSetFromDeployment(client, namespace, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -66,7 +66,7 @@ func RollbackDeployment(client client.Interface, rolloutSpec *RolloutSpec, names
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, errors.New("There is no ReplicaSet that has the requested revision for the Deployment.")
|
return nil, errors.New("there is no ReplicaSet that has the requested revision for the Deployment")
|
||||||
}
|
}
|
||||||
|
|
||||||
// PauseDeployment is used to pause a deployment
|
// PauseDeployment is used to pause a deployment
|
||||||
|
@ -83,7 +83,7 @@ func PauseDeployment(client client.Interface, namespace, name string) (*v1.Deplo
|
||||||
}
|
}
|
||||||
return deployment, nil
|
return deployment, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("The Deployment is already paused.")
|
return nil, errors.New("the Deployment is already paused")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResumeDeployment is used to resume a deployment
|
// ResumeDeployment is used to resume a deployment
|
||||||
|
@ -100,7 +100,7 @@ func ResumeDeployment(client client.Interface, namespace, name string) (*v1.Depl
|
||||||
}
|
}
|
||||||
return deployment, nil
|
return deployment, nil
|
||||||
}
|
}
|
||||||
return nil, errors.New("The deployment is already resumed.")
|
return nil, errors.New("the deployment is already resumed")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestartDeployment restarts a deployment in the manner of `kubectl rollout restart`.
|
// RestartDeployment restarts a deployment in the manner of `kubectl rollout restart`.
|
||||||
|
@ -110,10 +110,10 @@ func RestartDeployment(client client.Interface, namespace, name string) (*Rollou
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if deployment.Spec.Template.ObjectMeta.Annotations == nil {
|
if deployment.Spec.Template.Annotations == nil {
|
||||||
deployment.Spec.Template.ObjectMeta.Annotations = map[string]string{}
|
deployment.Spec.Template.Annotations = map[string]string{}
|
||||||
}
|
}
|
||||||
deployment.Spec.Template.ObjectMeta.Annotations[RestartedAtAnnotationKey] = time.Now().Format(time.RFC3339)
|
deployment.Spec.Template.Annotations[RestartedAtAnnotationKey] = time.Now().Format(time.RFC3339)
|
||||||
res, err := client.AppsV1().Deployments(namespace).Update(context.TODO(), deployment, metaV1.UpdateOptions{})
|
res, err := client.AppsV1().Deployments(namespace).Update(context.TODO(), deployment, metaV1.UpdateOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
package endpoint
|
package endpoint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/dashboard/api/pkg/args"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/types"
|
"k8s.io/dashboard/types"
|
||||||
)
|
)
|
||||||
|
@ -57,7 +57,7 @@ func GetServiceEndpoints(client k8sClient.Interface, namespace, name string) (*E
|
||||||
}
|
}
|
||||||
|
|
||||||
endpointList = toEndpointList(serviceEndpoints)
|
endpointList = toEndpointList(serviceEndpoints)
|
||||||
log.Printf("Found %d endpoints related to %s service in %s namespace", len(endpointList.Endpoints), name, namespace)
|
klog.V(args.LogLevelVerbose).Infof("Found %d endpoints related to %s service in %s namespace", len(endpointList.Endpoints), name, namespace)
|
||||||
return endpointList, nil
|
return endpointList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -244,20 +244,20 @@ func CreateEventList(events []v1.Event, dsQuery *dataselect.DataSelectQuery) com
|
||||||
|
|
||||||
type EventCell v1.Event
|
type EventCell v1.Event
|
||||||
|
|
||||||
func (self EventCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in EventCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.FirstSeenProperty:
|
case dataselect.FirstSeenProperty:
|
||||||
return dataselect.StdComparableTime(self.FirstTimestamp.Time)
|
return dataselect.StdComparableTime(in.FirstTimestamp.Time)
|
||||||
case dataselect.LastSeenProperty:
|
case dataselect.LastSeenProperty:
|
||||||
return dataselect.StdComparableTime(self.LastTimestamp.Time)
|
return dataselect.StdComparableTime(in.LastTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
case dataselect.ReasonProperty:
|
case dataselect.ReasonProperty:
|
||||||
return dataselect.StdComparableString(self.Reason)
|
return dataselect.StdComparableString(in.Reason)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -15,9 +15,9 @@
|
||||||
package event
|
package event
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
"k8s.io/dashboard/errors"
|
"k8s.io/dashboard/errors"
|
||||||
|
@ -25,7 +25,7 @@ import (
|
||||||
|
|
||||||
func GetEventList(client k8sClient.Interface, nsQuery *common.NamespaceQuery,
|
func GetEventList(client k8sClient.Interface, nsQuery *common.NamespaceQuery,
|
||||||
dsQuery *dataselect.DataSelectQuery) (*common.EventList, error) {
|
dsQuery *dataselect.DataSelectQuery) (*common.EventList, error) {
|
||||||
log.Printf("Getting list of events in namespace: %s", nsQuery.ToRequestParam())
|
klog.V(4).Infof("Getting list of events in namespace: %s", nsQuery.ToRequestParam())
|
||||||
|
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
EventList: common.GetEventListChannel(client, nsQuery, 2),
|
EventList: common.GetEventListChannel(client, nsQuery, 2),
|
||||||
|
|
|
@ -29,14 +29,14 @@ type ScaleTargetRef struct {
|
||||||
|
|
||||||
type HorizontalPodAutoscalerCell autoscaling.HorizontalPodAutoscaler
|
type HorizontalPodAutoscalerCell autoscaling.HorizontalPodAutoscaler
|
||||||
|
|
||||||
func (self HorizontalPodAutoscalerCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in HorizontalPodAutoscalerCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,11 +16,11 @@ package horizontalpodautoscaler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
autoscaling "k8s.io/api/autoscaling/v1"
|
autoscaling "k8s.io/api/autoscaling/v1"
|
||||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// HorizontalPodAutoscalerDetail provides the presentation layer view of Kubernetes Horizontal Pod Autoscaler resource.
|
// HorizontalPodAutoscalerDetail provides the presentation layer view of Kubernetes Horizontal Pod Autoscaler resource.
|
||||||
|
@ -35,7 +35,7 @@ type HorizontalPodAutoscalerDetail struct {
|
||||||
|
|
||||||
// GetHorizontalPodAutoscalerDetail returns detailed information about a horizontal pod autoscaler
|
// GetHorizontalPodAutoscalerDetail returns detailed information about a horizontal pod autoscaler
|
||||||
func GetHorizontalPodAutoscalerDetail(client client.Interface, namespace string, name string) (*HorizontalPodAutoscalerDetail, error) {
|
func GetHorizontalPodAutoscalerDetail(client client.Interface, namespace string, name string) (*HorizontalPodAutoscalerDetail, error) {
|
||||||
log.Printf("Getting details of %s horizontal pod autoscaler", name)
|
klog.V(4).Infof("Getting details of %s horizontal pod autoscaler", name)
|
||||||
|
|
||||||
rawHorizontalPodAutoscaler, err := client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(context.TODO(), name, v1.GetOptions{})
|
rawHorizontalPodAutoscaler, err := client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(context.TODO(), name, v1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
|
|
||||||
type IngressCell v1.Ingress
|
type IngressCell v1.Ingress
|
||||||
|
|
||||||
func (self IngressCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in IngressCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,11 +16,11 @@ package ingress
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/networking/v1"
|
v1 "k8s.io/api/networking/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressDetail API resource provides mechanisms to inject containers with configuration data while keeping
|
// IngressDetail API resource provides mechanisms to inject containers with configuration data while keeping
|
||||||
|
@ -41,7 +41,7 @@ type IngressDetail struct {
|
||||||
|
|
||||||
// GetIngressDetail returns detailed information about an ingress
|
// GetIngressDetail returns detailed information about an ingress
|
||||||
func GetIngressDetail(client client.Interface, namespace, name string) (*IngressDetail, error) {
|
func GetIngressDetail(client client.Interface, namespace, name string) (*IngressDetail, error) {
|
||||||
log.Printf("Getting details of %s ingress in %s namespace", name, namespace)
|
klog.V(4).Infof("Getting details of %s ingress in %s namespace", name, namespace)
|
||||||
|
|
||||||
rawIngress, err := client.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
rawIngress, err := client.NetworkingV1().Ingresses(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
|
|
||||||
|
|
|
@ -37,10 +37,10 @@ func ingressMatchesServiceName(ingress networkingv1.Ingress, serviceName string)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, rule := range spec.Rules {
|
for _, rule := range spec.Rules {
|
||||||
if rule.IngressRuleValue.HTTP == nil {
|
if rule.HTTP == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, path := range rule.IngressRuleValue.HTTP.Paths {
|
for _, path := range rule.HTTP.Paths {
|
||||||
if ingressBackendMatchesServiceName(&path.Backend, serviceName) {
|
if ingressBackendMatchesServiceName(&path.Backend, serviceName) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
|
|
||||||
type IngressClassCell networkingv1.IngressClass
|
type IngressClassCell networkingv1.IngressClass
|
||||||
|
|
||||||
func (self IngressClassCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in IngressClassCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,11 +16,11 @@ package ingressclass
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IngressClassDetail provides the presentation layer view of Ingress Class resource.
|
// IngressClassDetail provides the presentation layer view of Ingress Class resource.
|
||||||
|
@ -32,7 +32,7 @@ type IngressClassDetail struct {
|
||||||
|
|
||||||
// GetIngressClass returns Storage Class resource.
|
// GetIngressClass returns Storage Class resource.
|
||||||
func GetIngressClass(client kubernetes.Interface, name string) (*IngressClassDetail, error) {
|
func GetIngressClass(client kubernetes.Interface, name string) (*IngressClassDetail, error) {
|
||||||
log.Printf("Getting details of %s ingress class", name)
|
klog.V(4).Infof("Getting details of %s ingress class", name)
|
||||||
|
|
||||||
ic, err := client.NetworkingV1().IngressClasses().Get(context.TODO(), name, metaV1.GetOptions{})
|
ic, err := client.NetworkingV1().IngressClasses().Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -15,10 +15,9 @@
|
||||||
package ingressclass
|
package ingressclass
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
networkingv1 "k8s.io/api/networking/v1"
|
networkingv1 "k8s.io/api/networking/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -45,7 +44,7 @@ type IngressClass struct {
|
||||||
// GetIngressClassList returns a list of all Ingress class objects in the cluster.
|
// GetIngressClassList returns a list of all Ingress class objects in the cluster.
|
||||||
func GetIngressClassList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (
|
func GetIngressClassList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (
|
||||||
*IngressClassList, error) {
|
*IngressClassList, error) {
|
||||||
log.Print("Getting list of ingress classes in the cluster")
|
klog.V(4).Infof("Getting list of ingress classes in the cluster")
|
||||||
|
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
IngressClassList: common.GetIngressClassListChannel(client, 1),
|
IngressClassList: common.GetIngressClassListChannel(client, 1),
|
||||||
|
|
|
@ -28,26 +28,26 @@ import (
|
||||||
|
|
||||||
type JobCell batch.Job
|
type JobCell batch.Job
|
||||||
|
|
||||||
func (self JobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in JobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self JobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
func (in JobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||||
return &metricapi.ResourceSelector{
|
return &metricapi.ResourceSelector{
|
||||||
Namespace: self.ObjectMeta.Namespace,
|
Namespace: in.Namespace,
|
||||||
ResourceType: types.ResourceKindJob,
|
ResourceType: types.ResourceKindJob,
|
||||||
ResourceName: self.ObjectMeta.Name,
|
ResourceName: in.Name,
|
||||||
UID: self.UID,
|
UID: in.UID,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,10 @@
|
||||||
package job
|
package job
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
|
|
||||||
batch "k8s.io/api/batch/v1"
|
batch "k8s.io/api/batch/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
|
@ -89,7 +88,7 @@ type Job struct {
|
||||||
// GetJobList returns a list of all Jobs in the cluster.
|
// GetJobList returns a list of all Jobs in the cluster.
|
||||||
func GetJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
func GetJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
||||||
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*JobList, error) {
|
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*JobList, error) {
|
||||||
log.Print("Getting list of all jobs in the cluster")
|
klog.V(4).Infof("Getting list of all jobs in the cluster")
|
||||||
|
|
||||||
channels := &common.ResourceChannels{
|
channels := &common.ResourceChannels{
|
||||||
JobList: common.GetJobListChannel(client, nsQuery, 1),
|
JobList: common.GetJobListChannel(client, nsQuery, 1),
|
||||||
|
|
|
@ -16,7 +16,6 @@ package job
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
batch "k8s.io/api/batch/v1"
|
batch "k8s.io/api/batch/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
@ -24,6 +23,8 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/fields"
|
"k8s.io/apimachinery/pkg/fields"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -35,7 +36,7 @@ import (
|
||||||
// GetJobPods return list of pods targeting job.
|
// GetJobPods return list of pods targeting job.
|
||||||
func GetJobPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
func GetJobPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||||
dsQuery *dataselect.DataSelectQuery, namespace string, jobName string) (*pod.PodList, error) {
|
dsQuery *dataselect.DataSelectQuery, namespace string, jobName string) (*pod.PodList, error) {
|
||||||
log.Printf("Getting replication controller %s pods in namespace %s", jobName, namespace)
|
klog.V(4).Infof("Getting replication controller %s pods in namespace %s", jobName, namespace)
|
||||||
|
|
||||||
pods, err := getRawJobPods(client, jobName, namespace)
|
pods, err := getRawJobPods(client, jobName, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -151,23 +151,23 @@ type LogTimestamp string
|
||||||
|
|
||||||
// SelectLogs returns selected part of LogLines as required by logSelector, moreover it returns IDs of first and last
|
// SelectLogs returns selected part of LogLines as required by logSelector, moreover it returns IDs of first and last
|
||||||
// of returned lines and the information of the resulting logView.
|
// of returned lines and the information of the resulting logView.
|
||||||
func (self LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp, LogTimestamp, Selection, bool) {
|
func (in LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp, LogTimestamp, Selection, bool) {
|
||||||
requestedNumItems := logSelection.OffsetTo - logSelection.OffsetFrom
|
requestedNumItems := logSelection.OffsetTo - logSelection.OffsetFrom
|
||||||
referenceLineIndex := self.getLineIndex(&logSelection.ReferencePoint)
|
referenceLineIndex := in.getLineIndex(&logSelection.ReferencePoint)
|
||||||
if referenceLineIndex == LineIndexNotFound || requestedNumItems <= 0 || len(self) == 0 {
|
if referenceLineIndex == LineIndexNotFound || requestedNumItems <= 0 || len(in) == 0 {
|
||||||
// Requested reference line could not be found, probably it's already gone or requested no logs. Return no logs.
|
// Requested reference line could not be found, probably it's already gone or requested no logs. Return no logs.
|
||||||
return LogLines{}, "", "", Selection{}, false
|
return LogLines{}, "", "", Selection{}, false
|
||||||
}
|
}
|
||||||
fromIndex := referenceLineIndex + logSelection.OffsetFrom
|
fromIndex := referenceLineIndex + logSelection.OffsetFrom
|
||||||
toIndex := referenceLineIndex + logSelection.OffsetTo
|
toIndex := referenceLineIndex + logSelection.OffsetTo
|
||||||
lastPage := false
|
lastPage := false
|
||||||
if requestedNumItems > len(self) {
|
if requestedNumItems > len(in) {
|
||||||
fromIndex = 0
|
fromIndex = 0
|
||||||
toIndex = len(self)
|
toIndex = len(in)
|
||||||
lastPage = true
|
lastPage = true
|
||||||
} else if toIndex > len(self) {
|
} else if toIndex > len(in) {
|
||||||
fromIndex -= toIndex - len(self)
|
fromIndex -= toIndex - len(in)
|
||||||
toIndex = len(self)
|
toIndex = len(in)
|
||||||
lastPage = logSelection.LogFilePosition == Beginning
|
lastPage = logSelection.LogFilePosition == Beginning
|
||||||
} else if fromIndex < 0 {
|
} else if fromIndex < 0 {
|
||||||
toIndex += -fromIndex
|
toIndex += -fromIndex
|
||||||
|
@ -177,32 +177,32 @@ func (self LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp
|
||||||
|
|
||||||
// set the middle of log array as a reference point, this part of array should not be affected by log deletion/addition.
|
// set the middle of log array as a reference point, this part of array should not be affected by log deletion/addition.
|
||||||
newSelection := Selection{
|
newSelection := Selection{
|
||||||
ReferencePoint: *self.createLogLineId(len(self) / 2),
|
ReferencePoint: *in.createLogLineId(len(in) / 2),
|
||||||
OffsetFrom: fromIndex - len(self)/2,
|
OffsetFrom: fromIndex - len(in)/2,
|
||||||
OffsetTo: toIndex - len(self)/2,
|
OffsetTo: toIndex - len(in)/2,
|
||||||
LogFilePosition: logSelection.LogFilePosition,
|
LogFilePosition: logSelection.LogFilePosition,
|
||||||
}
|
}
|
||||||
return self[fromIndex:toIndex], self[fromIndex].Timestamp, self[toIndex-1].Timestamp, newSelection, lastPage
|
return in[fromIndex:toIndex], in[fromIndex].Timestamp, in[toIndex-1].Timestamp, newSelection, lastPage
|
||||||
}
|
}
|
||||||
|
|
||||||
// getLineIndex returns the index of the line (referenced from beginning of log array) with provided logLineId.
|
// getLineIndex returns the index of the line (referenced from beginning of log array) with provided logLineId.
|
||||||
func (self LogLines) getLineIndex(logLineId *LogLineId) int {
|
func (in LogLines) getLineIndex(logLineId *LogLineId) int {
|
||||||
if logLineId == nil || logLineId.LogTimestamp == NewestTimestamp || len(self) == 0 || logLineId.LogTimestamp == "" {
|
if logLineId == nil || logLineId.LogTimestamp == NewestTimestamp || len(in) == 0 || logLineId.LogTimestamp == "" {
|
||||||
// if no line id provided return index of last item.
|
// if no line id provided return index of last item.
|
||||||
return len(self) - 1
|
return len(in) - 1
|
||||||
} else if logLineId.LogTimestamp == OldestTimestamp {
|
} else if logLineId.LogTimestamp == OldestTimestamp {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
logTimestamp := logLineId.LogTimestamp
|
logTimestamp := logLineId.LogTimestamp
|
||||||
|
|
||||||
matchingStartedAt := 0
|
matchingStartedAt := 0
|
||||||
matchingStartedAt = sort.Search(len(self), func(i int) bool {
|
matchingStartedAt = sort.Search(len(in), func(i int) bool {
|
||||||
return self[i].Timestamp >= logTimestamp
|
return in[i].Timestamp >= logTimestamp
|
||||||
})
|
})
|
||||||
|
|
||||||
linesMatched := 0
|
linesMatched := 0
|
||||||
if matchingStartedAt < len(self) && self[matchingStartedAt].Timestamp == logTimestamp { // match found
|
if matchingStartedAt < len(in) && in[matchingStartedAt].Timestamp == logTimestamp { // match found
|
||||||
for (matchingStartedAt+linesMatched) < len(self) && self[matchingStartedAt+linesMatched].Timestamp == logTimestamp {
|
for (matchingStartedAt+linesMatched) < len(in) && in[matchingStartedAt+linesMatched].Timestamp == logTimestamp {
|
||||||
linesMatched += 1
|
linesMatched += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -220,22 +220,22 @@ func (self LogLines) getLineIndex(logLineId *LogLineId) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
// createLogLineId returns ID of the line with provided lineIndex.
|
// createLogLineId returns ID of the line with provided lineIndex.
|
||||||
func (self LogLines) createLogLineId(lineIndex int) *LogLineId {
|
func (in LogLines) createLogLineId(lineIndex int) *LogLineId {
|
||||||
logTimestamp := self[lineIndex].Timestamp
|
logTimestamp := in[lineIndex].Timestamp
|
||||||
// determine whether to use negative or positive indexing
|
// determine whether to use negative or positive indexing
|
||||||
// check whether last line has the same index as requested line. If so, we can only use positive referencing
|
// check whether last line has the same index as requested line. If so, we can only use positive referencing
|
||||||
// as more lines may appear at the end.
|
// as more lines may appear at the end.
|
||||||
// negative referencing is preferred as higher indices disappear later.
|
// negative referencing is preferred as higher indices disappear later.
|
||||||
var step int
|
var step int
|
||||||
if self[len(self)-1].Timestamp == logTimestamp {
|
if in[len(in)-1].Timestamp == logTimestamp {
|
||||||
// use positive referencing
|
// use positive referencing
|
||||||
step = 1
|
step = 1
|
||||||
} else {
|
} else {
|
||||||
step = -1
|
step = -1
|
||||||
}
|
}
|
||||||
offset := step
|
offset := step
|
||||||
for ; 0 <= lineIndex-offset && lineIndex-offset < len(self); offset += step {
|
for ; 0 <= lineIndex-offset && lineIndex-offset < len(in); offset += step {
|
||||||
if self[lineIndex-offset].Timestamp != logTimestamp {
|
if in[lineIndex-offset].Timestamp != logTimestamp {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,11 +16,13 @@ package namespace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
api "k8s.io/api/core/v1"
|
api "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/dashboard/api/pkg/args"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +34,7 @@ type NamespaceSpec struct {
|
||||||
|
|
||||||
// CreateNamespace creates namespace based on given specification.
|
// CreateNamespace creates namespace based on given specification.
|
||||||
func CreateNamespace(spec *NamespaceSpec, client kubernetes.Interface) error {
|
func CreateNamespace(spec *NamespaceSpec, client kubernetes.Interface) error {
|
||||||
log.Printf("Creating namespace %s", spec.Name)
|
klog.V(args.LogLevelVerbose).Infof("Creating namespace %s", spec.Name)
|
||||||
|
|
||||||
namespace := &api.Namespace{
|
namespace := &api.Namespace{
|
||||||
ObjectMeta: metaV1.ObjectMeta{
|
ObjectMeta: metaV1.ObjectMeta{
|
||||||
|
@ -48,14 +50,14 @@ func CreateNamespace(spec *NamespaceSpec, client kubernetes.Interface) error {
|
||||||
|
|
||||||
type NamespaceCell api.Namespace
|
type NamespaceCell api.Namespace
|
||||||
|
|
||||||
func (self NamespaceCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in NamespaceCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -16,11 +16,11 @@ package namespace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
k8sClient "k8s.io/client-go/kubernetes"
|
k8sClient "k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/limitrange"
|
"k8s.io/dashboard/api/pkg/resource/limitrange"
|
||||||
rq "k8s.io/dashboard/api/pkg/resource/resourcequota"
|
rq "k8s.io/dashboard/api/pkg/resource/resourcequota"
|
||||||
|
@ -47,7 +47,7 @@ type NamespaceDetail struct {
|
||||||
|
|
||||||
// GetNamespaceDetail gets namespace details.
|
// GetNamespaceDetail gets namespace details.
|
||||||
func GetNamespaceDetail(client k8sClient.Interface, name string) (*NamespaceDetail, error) {
|
func GetNamespaceDetail(client k8sClient.Interface, name string) (*NamespaceDetail, error) {
|
||||||
log.Printf("Getting details of %s namespace\n", name)
|
klog.V(4).Infof("Getting details of %s namespace\n", name)
|
||||||
|
|
||||||
namespace, err := client.CoreV1().Namespaces().Get(context.TODO(), name, metaV1.GetOptions{})
|
namespace, err := client.CoreV1().Namespaces().Get(context.TODO(), name, metaV1.GetOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -16,10 +16,10 @@ package namespace
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/common"
|
"k8s.io/dashboard/api/pkg/resource/common"
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
|
@ -64,7 +64,7 @@ func GetNamespaceListFromChannels(channels *common.ResourceChannels, dsQuery *da
|
||||||
|
|
||||||
// GetNamespaceList returns a list of all namespaces in the cluster.
|
// GetNamespaceList returns a list of all namespaces in the cluster.
|
||||||
func GetNamespaceList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*NamespaceList, error) {
|
func GetNamespaceList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*NamespaceList, error) {
|
||||||
log.Println("Getting list of namespaces")
|
klog.V(4).Info("Getting list of namespaces")
|
||||||
namespaces, err := client.CoreV1().Namespaces().List(context.TODO(), helpers.ListEverything)
|
namespaces, err := client.CoreV1().Namespaces().List(context.TODO(), helpers.ListEverything)
|
||||||
|
|
||||||
nonCriticalErrors, criticalError := errors.ExtractErrors(err)
|
nonCriticalErrors, criticalError := errors.ExtractErrors(err)
|
||||||
|
|
|
@ -16,19 +16,20 @@ package networkpolicy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
v1 "k8s.io/api/networking/v1"
|
v1 "k8s.io/api/networking/v1"
|
||||||
|
|
||||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServiceAccountCell v1.NetworkPolicy
|
type ServiceAccountCell v1.NetworkPolicy
|
||||||
|
|
||||||
func (self ServiceAccountCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
func (in ServiceAccountCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||||
switch name {
|
switch name {
|
||||||
case dataselect.NameProperty:
|
case dataselect.NameProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
return dataselect.StdComparableString(in.Name)
|
||||||
case dataselect.CreationTimestampProperty:
|
case dataselect.CreationTimestampProperty:
|
||||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||||
case dataselect.NamespaceProperty:
|
case dataselect.NamespaceProperty:
|
||||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
return dataselect.StdComparableString(in.Namespace)
|
||||||
default:
|
default:
|
||||||
// If name is not supported then just return a constant dummy value, sort will have no effect.
|
// If name is not supported then just return a constant dummy value, sort will have no effect.
|
||||||
return nil
|
return nil
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue