Compare commits
No commits in common. "master" and "web/v1.5.0" have entirely different histories.
master
...
web/v1.5.0
|
@ -48,15 +48,15 @@ jobs:
|
|||
type=raw,value=latest
|
||||
type=match,pattern=\d+\.\d+\.\d+
|
||||
type=sha
|
||||
- uses: docker/setup-qemu-action@v3.6.0
|
||||
- uses: docker/setup-buildx-action@v3.10.0
|
||||
- uses: docker/setup-qemu-action@v3.2.0
|
||||
- uses: docker/setup-buildx-action@v3.7.1
|
||||
with:
|
||||
config: .github/buildkitd.toml
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
|||
type=raw,value=latest
|
||||
type=match,pattern=\d+\.\d+\.\d+
|
||||
type=sha
|
||||
- uses: docker/setup-qemu-action@v3.6.0
|
||||
- uses: docker/setup-buildx-action@v3.10.0
|
||||
- uses: docker/setup-qemu-action@v3.2.0
|
||||
- uses: docker/setup-buildx-action@v3.7.1
|
||||
with:
|
||||
config: .github/buildkitd.toml
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -30,13 +30,13 @@ jobs:
|
|||
- uses: actions/checkout@v4.1.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: azure/setup-helm@v4.3.0
|
||||
- uses: azure/setup-helm@v4.2.0
|
||||
with:
|
||||
version: v3.12.1
|
||||
- uses: helm/chart-testing-action@v2.7.0
|
||||
- uses: helm/kind-action@v1.12.0
|
||||
- uses: helm/chart-testing-action@v2.6.1
|
||||
- uses: helm/kind-action@v1.10.0
|
||||
with:
|
||||
node_image: kindest/node:v1.32.0
|
||||
node_image: kindest/node:v1.30.2
|
||||
- run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
||||
|
||||
release:
|
||||
|
@ -57,7 +57,7 @@ jobs:
|
|||
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4.3.0
|
||||
uses: azure/setup-helm@v4.2.0
|
||||
with:
|
||||
version: v3.12.1
|
||||
|
||||
|
@ -69,7 +69,7 @@ jobs:
|
|||
helm repo add kong https://charts.konghq.com
|
||||
|
||||
- name: Run chart-releaser
|
||||
uses: helm/chart-releaser-action@v1.7.0
|
||||
uses: helm/chart-releaser-action@v1.6.0
|
||||
with:
|
||||
skip_existing: true
|
||||
mark_as_latest: true
|
||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
|||
type=raw,value=latest
|
||||
type=match,pattern=\d+\.\d+\.\d+
|
||||
type=sha
|
||||
- uses: docker/setup-qemu-action@v3.6.0
|
||||
- uses: docker/setup-buildx-action@v3.10.0
|
||||
- uses: docker/setup-qemu-action@v3.2.0
|
||||
- uses: docker/setup-buildx-action@v3.7.1
|
||||
with:
|
||||
config: .github/buildkitd.toml
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -48,15 +48,15 @@ jobs:
|
|||
type=raw,value=latest
|
||||
type=match,pattern=\d+\.\d+\.\d+
|
||||
type=sha
|
||||
- uses: docker/setup-qemu-action@v3.6.0
|
||||
- uses: docker/setup-buildx-action@v3.10.0
|
||||
- uses: docker/setup-qemu-action@v3.2.0
|
||||
- uses: docker/setup-buildx-action@v3.7.1
|
||||
with:
|
||||
config: .github/buildkitd.toml
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_RELEASE_USER }}
|
||||
password: ${{ secrets.DOCKER_RELEASE_PASS }}
|
||||
- uses: docker/login-action@v3.4.0
|
||||
- uses: docker/login-action@v3.3.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
|
|
|
@ -23,31 +23,24 @@ jobs:
|
|||
name: Lint and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4.1.1
|
||||
- uses: actions/checkout@v4.1.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4.3.0
|
||||
- uses: azure/setup-helm@v4.2.0
|
||||
with:
|
||||
version: v3.12.1
|
||||
- name: Set up Chart Testing CLI
|
||||
uses: helm/chart-testing-action@v2.7.0
|
||||
- name: Change Detection
|
||||
id: list-changed
|
||||
- uses: helm/chart-testing-action@v2.6.1
|
||||
- id: list-changed
|
||||
run: |
|
||||
changed=$(ct list-changed --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }})
|
||||
if [[ -n "$changed" ]]; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Lint Chart
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }} --check-version-increment=false
|
||||
- name: Set up Kind
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
uses: helm/kind-action@v1.12.0
|
||||
- if: steps.list-changed.outputs.changed == 'true'
|
||||
run: ct lint --config=.ct.yml --target-branch ${{ github.event.repository.default_branch }}
|
||||
- if: steps.list-changed.outputs.changed == 'true'
|
||||
uses: helm/kind-action@v1.10.0
|
||||
with:
|
||||
node_image: kindest/node:v1.32.0
|
||||
- name: Install Chart
|
||||
if: steps.list-changed.outputs.changed == 'true'
|
||||
node_image: kindest/node:v1.30.2
|
||||
- if: steps.list-changed.outputs.changed == 'true'
|
||||
run: ct install --target-branch ${{ github.event.repository.default_branch }}
|
||||
|
|
|
@ -64,7 +64,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5.5.0
|
||||
- uses: actions/setup-go@v5.0.2
|
||||
with:
|
||||
go-version-file: modules/api/go.mod
|
||||
check-latest: true
|
||||
|
@ -81,7 +81,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5.5.0
|
||||
- uses: actions/setup-go@v5.0.2
|
||||
with:
|
||||
go-version-file: modules/api/go.mod
|
||||
check-latest: true
|
||||
|
@ -99,7 +99,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5.5.0
|
||||
- uses: actions/setup-go@v5.0.2
|
||||
with:
|
||||
go-version-file: modules/api/go.mod
|
||||
check-latest: true
|
||||
|
@ -116,63 +116,6 @@ jobs:
|
|||
fetch-depth: 0
|
||||
- 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:
|
||||
name: Unit tests with coverage
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -180,7 +123,7 @@ jobs:
|
|||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-go@v5.5.0
|
||||
- uses: actions/setup-go@v5.0.2
|
||||
with:
|
||||
go-version-file: modules/go.work
|
||||
check-latest: true
|
||||
|
@ -190,7 +133,7 @@ jobs:
|
|||
- working-directory: modules/web
|
||||
run: yarn
|
||||
- run: PATH=$PATH:$GOPATH/bin make coverage
|
||||
- uses: codecov/codecov-action@v5.4.2
|
||||
- uses: codecov/codecov-action@v4.6.0
|
||||
with:
|
||||
directory: ./.tmp
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
@ -205,8 +148,8 @@ jobs:
|
|||
# fetch-depth: 0
|
||||
# - uses: helm/kind-action@v1.9.0
|
||||
# with:
|
||||
# node_image: kindest/node:v1.32.0
|
||||
# - uses: actions/setup-go@v5.5.0
|
||||
# node_image: kindest/node:v1.30.2
|
||||
# - uses: actions/setup-go@v5.0.2
|
||||
# with:
|
||||
# go-version-file: modules/api/go.mod
|
||||
# check-latest: true
|
||||
|
|
|
@ -11,41 +11,28 @@
|
|||
# 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.
|
||||
|
||||
version: "2"
|
||||
#
|
||||
run:
|
||||
modules-download-mode: readonly
|
||||
allow-parallel-runners: true
|
||||
timeout: 30m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
allow-parallel-runners: true
|
||||
linters:
|
||||
default: none
|
||||
disable-all: true
|
||||
enable:
|
||||
# default linters
|
||||
- errcheck
|
||||
- errorlint
|
||||
- gocyclo
|
||||
- gosimple
|
||||
- govet
|
||||
- ineffassign
|
||||
- misspell
|
||||
- staticcheck
|
||||
- typecheck
|
||||
- unused
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gocyclo
|
||||
|
||||
# additional linters
|
||||
- errorlint
|
||||
- errname
|
||||
- goimports
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
- misspell
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
dependencies:
|
||||
- name: ingress-nginx
|
||||
repository: https://kubernetes.github.io/ingress-nginx
|
||||
version: 4.12.0
|
||||
version: 4.10.1
|
||||
- name: cert-manager
|
||||
repository: https://charts.jetstack.io
|
||||
version: v1.16.2
|
||||
version: v1.14.5
|
||||
- name: metrics-server
|
||||
repository: https://kubernetes-sigs.github.io/metrics-server/
|
||||
version: 3.12.2
|
||||
version: 3.12.1
|
||||
- name: kong
|
||||
repository: https://charts.konghq.com
|
||||
version: 2.46.0
|
||||
digest: sha256:fa0fa7ff7e237c3db88016a57704d0f2c9f7dae9ac9b041a32112b6df35f8e23
|
||||
generated: "2025-01-10T12:28:39.253786876+01:00"
|
||||
version: 2.38.0
|
||||
digest: sha256:ef535931f6d08b3b4b242cba567d0c02a072cf7cf68431f58a0d8d283b3b72b5
|
||||
generated: "2024-06-04T11:32:45.155515532+02:00"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
apiVersion: v2
|
||||
name: kubernetes-dashboard
|
||||
version: 7.13.0
|
||||
version: 7.7.0
|
||||
description: General-purpose web UI for Kubernetes clusters
|
||||
keywords:
|
||||
- kubernetes
|
||||
|
@ -32,18 +32,18 @@ kubeVersion: ">=1.21.0-0"
|
|||
dependencies:
|
||||
- name: ingress-nginx
|
||||
alias: nginx
|
||||
version: 4.12.0
|
||||
version: 4.10.1
|
||||
repository: https://kubernetes.github.io/ingress-nginx
|
||||
condition: nginx.enabled
|
||||
- name: cert-manager
|
||||
version: v1.16.2
|
||||
version: v1.14.5
|
||||
repository: https://charts.jetstack.io
|
||||
condition: cert-manager.enabled
|
||||
- name: metrics-server
|
||||
version: 3.12.2
|
||||
version: 3.12.1
|
||||
repository: https://kubernetes-sigs.github.io/metrics-server/
|
||||
condition: metrics-server.enabled
|
||||
- name: kong
|
||||
version: 2.46.0
|
||||
version: 2.38.0
|
||||
repository: https://charts.konghq.com
|
||||
condition: kong.enabled
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
Congratulations! You have just installed Kubernetes Dashboard in your cluster.
|
||||
{{ if not (.Values.nginx.enabled) }}
|
||||
To access Dashboard run:
|
||||
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ .Release.Name }}-kong-proxy 8443:443
|
||||
kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-kong-proxy 8443:443
|
||||
|
||||
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:
|
||||
|
@ -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) }}
|
||||
To access Dashboard run:
|
||||
kubectl -n {{ .Release.Namespace }} port-forward svc/{{ .Release.Name }}-nginx-controller 8443:443
|
||||
kubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard-nginx-controller 8443:443
|
||||
|
||||
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:
|
||||
|
|
|
@ -75,14 +75,14 @@ spec:
|
|||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.cpu
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
{{- if .Values.api.containers.resources.limits.memory }}
|
||||
- name: GOMEMLIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.memory
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.api.containers.env }}
|
||||
|
|
|
@ -76,14 +76,14 @@ spec:
|
|||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.cpu
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
{{- if .Values.auth.containers.resources.limits.memory }}
|
||||
- name: GOMEMLIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.memory
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.auth.containers.env }}
|
||||
|
|
|
@ -68,14 +68,14 @@ spec:
|
|||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.cpu
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
{{- if .Values.metricsScraper.containers.resources.limits.memory }}
|
||||
- name: GOMEMLIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.memory
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.metricsScraper.containers.env }}
|
||||
|
|
|
@ -70,14 +70,14 @@ spec:
|
|||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.cpu
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
{{- if .Values.web.containers.resources.limits.memory }}
|
||||
- name: GOMEMLIMIT
|
||||
valueFrom:
|
||||
resourceFieldRef:
|
||||
resource: limits.memory
|
||||
divisor: "1"
|
||||
divisor: 1
|
||||
{{- end }}
|
||||
|
||||
{{- with .Values.web.containers.env }}
|
||||
|
|
|
@ -15,12 +15,6 @@
|
|||
{{- if and .Values.app.ingress.enabled (eq .Values.app.mode "dashboard")}}
|
||||
{{- 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
|
||||
apiVersion: networking.k8s.io/v1
|
||||
metadata:
|
||||
|
@ -79,7 +73,7 @@ spec:
|
|||
service:
|
||||
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
||||
port:
|
||||
number: {{ $servicePort }}
|
||||
number: {{ $.Values.kong.proxy.tls.servicePort }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
- http:
|
||||
|
@ -90,6 +84,6 @@ spec:
|
|||
service:
|
||||
name: {{ template "kong.fullname" (index $.Subcharts "kong") }}-proxy
|
||||
port:
|
||||
number: {{ $servicePort }}
|
||||
number: {{ $.Values.kong.proxy.tls.servicePort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
|
|
@ -30,19 +30,11 @@ metadata:
|
|||
{{- end }}
|
||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.api.role }}
|
||||
spec:
|
||||
type: {{ .Values.api.service.type }}
|
||||
ports:
|
||||
{{- range $port := .Values.api.containers.ports }}
|
||||
- name: {{ $port.name }}
|
||||
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 }}
|
||||
- name: {{ .Values.api.role }}
|
||||
{{- with (index .Values.api.containers.ports 0) }}
|
||||
port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{ with .Values.api.service.extraSpec }}
|
||||
{{ . | toYaml | nindent 2 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.api.role }}
|
||||
|
|
|
@ -32,19 +32,11 @@ metadata:
|
|||
{{- end }}
|
||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.auth.role }}
|
||||
spec:
|
||||
type: {{ .Values.auth.service.type }}
|
||||
ports:
|
||||
{{- range $port := .Values.auth.containers.ports }}
|
||||
- name: {{ $port.name }}
|
||||
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 }}
|
||||
- name: {{ .Values.auth.role }}
|
||||
{{- with (index .Values.auth.containers.ports 0) }}
|
||||
port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{ with .Values.auth.service.extraSpec }}
|
||||
{{ . | toYaml | nindent 2 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.auth.role }}
|
||||
|
|
|
@ -32,20 +32,10 @@ metadata:
|
|||
{{- end }}
|
||||
name: {{ template "kubernetes-dashboard.metrics-scraper.name" . }}
|
||||
spec:
|
||||
type: {{ .Values.metricsScraper.service.type }}
|
||||
ports:
|
||||
{{- range $port := .Values.metricsScraper.containers.ports }}
|
||||
# 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 }}
|
||||
{{- with (index .Values.metricsScraper.containers.ports 0) }}
|
||||
- port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{ with .Values.metricsScraper.service.extraSpec }}
|
||||
{{ . | toYaml | nindent 2 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.metricsScraper.role }}
|
||||
|
|
|
@ -32,19 +32,11 @@ metadata:
|
|||
{{- end }}
|
||||
name: {{ template "kubernetes-dashboard.fullname" . }}-{{ .Values.web.role }}
|
||||
spec:
|
||||
type: {{ .Values.web.service.type }}
|
||||
ports:
|
||||
{{- range $port := .Values.web.containers.ports }}
|
||||
- name: {{ $port.name }}
|
||||
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 }}
|
||||
- name: {{ .Values.web.role }}
|
||||
{{- with (index .Values.web.containers.ports 0) }}
|
||||
port: {{ .containerPort }}
|
||||
{{- end }}
|
||||
{{ with .Values.web.service.extraSpec }}
|
||||
{{ . | toYaml | nindent 2 }}
|
||||
{{- end }}
|
||||
selector:
|
||||
{{- include "kubernetes-dashboard.matchLabels" . | nindent 4 }}
|
||||
app.kubernetes.io/name: {{ template "kubernetes-dashboard.name" . }}-{{ .Values.web.role }}
|
||||
|
|
|
@ -23,7 +23,7 @@ app:
|
|||
pullSecrets: []
|
||||
scheduling:
|
||||
# Node labels for pod assignment
|
||||
# Ref: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/
|
||||
# Ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
nodeSelector: {}
|
||||
security:
|
||||
# Allow overriding csrfKey used by API/Auth containers.
|
||||
|
@ -84,8 +84,6 @@ app:
|
|||
# resourceAutoRefreshTimeInterval: 10
|
||||
# # Hide all access denied warnings in the notification panel
|
||||
# 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.
|
||||
# defaultNamespace: default
|
||||
# # List of namespaces that should be presented to user without namespace list privileges.
|
||||
|
@ -145,13 +143,10 @@ auth:
|
|||
role: auth
|
||||
image:
|
||||
repository: docker.io/kubernetesui/dashboard-auth
|
||||
tag: 1.3.0
|
||||
tag: 1.1.3
|
||||
scaling:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
service:
|
||||
type: ClusterIP
|
||||
extraSpec: ~
|
||||
containers:
|
||||
ports:
|
||||
- name: auth
|
||||
|
@ -187,13 +182,10 @@ api:
|
|||
role: api
|
||||
image:
|
||||
repository: docker.io/kubernetesui/dashboard-api
|
||||
tag: 1.13.0
|
||||
tag: 1.8.1
|
||||
scaling:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
service:
|
||||
type: ClusterIP
|
||||
extraSpec: ~
|
||||
containers:
|
||||
ports:
|
||||
- name: api
|
||||
|
@ -247,13 +239,10 @@ web:
|
|||
role: web
|
||||
image:
|
||||
repository: docker.io/kubernetesui/dashboard-web
|
||||
tag: 1.7.0
|
||||
tag: 1.4.0
|
||||
scaling:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
service:
|
||||
type: ClusterIP
|
||||
extraSpec: ~
|
||||
containers:
|
||||
ports:
|
||||
- name: web
|
||||
|
@ -310,13 +299,10 @@ metricsScraper:
|
|||
role: metrics-scraper
|
||||
image:
|
||||
repository: docker.io/kubernetesui/dashboard-metrics-scraper
|
||||
tag: 1.2.2
|
||||
tag: 1.1.1
|
||||
scaling:
|
||||
replicas: 1
|
||||
revisionHistoryLimit: 10
|
||||
service:
|
||||
type: ClusterIP
|
||||
extraSpec: ~
|
||||
containers:
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
|
|
|
@ -3,81 +3,65 @@
|
|||
Dashboard containers accept multiple arguments that can be used to customize them.
|
||||
|
||||
## API module arguments
|
||||
|
||||
| Argument name | Default value | Description |
|
||||
|------------------------------|--------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| disable-csrf-protection | false | Allows disabling CSRF protection. |
|
||||
| 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-port | 9000 | The port to listen to for incoming HTTP requests. |
|
||||
| port | 9001 | 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). |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| metrics-provider | sidecar | Select provider type for metrics. 'none' will not check metrics. |
|
||||
| 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. |
|
||||
| metric-client-check-period | 30 | Time in seconds that defines how often configured metric client health check should be run. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||
| 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) | |
|
||||
|
||||
## Auth module arguments
|
||||
|
||||
| Argument name | Default value | Description |
|
||||
|---------------------------|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| apiserver-skip-tls-verify | false | Enable if connection with remote Kubernetes API should skip TLS verify. |
|
||||
| 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). |
|
||||
| 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
|
||||
| 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). |
|
||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||
| 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
|
||||
|
||||
| Argument name | Default value | Description |
|
||||
|-------------------|-----------------|---------------------------------------------------------------------------|
|
||||
| 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. |
|
||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||
| db-file | /tmp/metrics.db | What file to use as a SQLite3 database. |
|
||||
| namespaces | - | Namespaces to use for all metric calls. When provided, skip node metrics. |
|
||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||
| 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-duration | 15m | The duration after which metrics are purged from the database. |
|
||||
| logtostderr | true | Log to standard error. |
|
||||
| namespace | - | The namespace to use for all metric calls. When provided, skip node metrics. |
|
||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||
|
||||
## Web module arguments
|
||||
|
||||
| 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. |
|
||||
| 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). |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 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`. |
|
||||
| locale-config | ./locale_conf.json | File containing the configuration of locales. |
|
||||
| kubeconfig | - | Path to `kubeconfig` file. |
|
||||
| v | 1 | Number for the log level verbosity (default 1) | |
|
||||
|
||||
----
|
||||
_Copyright 2019 [The Kubernetes Dashboard Authors](https://github.com/kubernetes/dashboard/graphs/contributors)_
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
This guide is for anyone interested in contributing design work themselves or contributing in a way that is impacted by design.
|
||||
|
||||
## 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.
|
||||
* Dashboard is based on Google’s [Material](https://material.io/guidelines/) design system. Refer to their spec for guidance.
|
||||
|
||||
|
|
|
@ -1,104 +0,0 @@
|
|||
# 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.
Before Width: | Height: | Size: 62 KiB |
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
Binary file not shown.
Before Width: | Height: | Size: 72 KiB |
Binary file not shown.
Before 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:
|
||||
|
||||
```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.
|
||||
|
|
|
@ -54,7 +54,6 @@ services:
|
|||
command:
|
||||
--kubeconfig=${KUBECONFIG:?}
|
||||
--sidecar-host=${SIDECAR_HOST:?}
|
||||
--v=4
|
||||
volumes:
|
||||
- ${PWD}/modules/common:/workspace/common # Required - Common 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
|
||||
# Kind
|
||||
KIND_CLUSTER_NAME := kubernetes-dashboard
|
||||
KIND_CLUSTER_VERSION := 1.32.0
|
||||
KIND_CLUSTER_VERSION := 1.29.0
|
||||
KIND_CLUSTER_IMAGE := docker.io/kindest/node:v${KIND_CLUSTER_VERSION}
|
||||
KIND_CLUSTER_INTERNAL_KUBECONFIG_PATH := $(TMP_DIRECTORY)/kubeconfig
|
||||
KIND_CLUSTER_KUBECONFIG_CONTEXT := kind-$(KIND_CLUSTER_NAME)
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM alpine:3.21 AS user
|
||||
FROM alpine:3.19 as user
|
||||
|
||||
ENV USER=nonroot
|
||||
ENV UID=10001
|
||||
|
@ -27,7 +27,7 @@ RUN adduser \
|
|||
--uid "${UID}" \
|
||||
"${USER}"
|
||||
|
||||
FROM golang:1.23-alpine3.21 AS builder
|
||||
FROM golang:1.23-alpine3.19 as builder
|
||||
|
||||
ARG TARGETARCH
|
||||
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 .
|
||||
|
||||
# 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
|
||||
|
||||
|
|
|
@ -14,11 +14,11 @@
|
|||
|
||||
# ! Context expected to be set to "modules" dir !
|
||||
|
||||
FROM golang:1.23-alpine3.21 AS AIR
|
||||
FROM golang:1.23-alpine3.19 as AIR
|
||||
|
||||
RUN go install github.com/air-verse/air@latest
|
||||
|
||||
FROM golang:1.23-alpine3.21
|
||||
FROM golang:1.23-alpine3.19
|
||||
|
||||
# Copy air binary
|
||||
COPY --from=AIR $GOPATH/bin/air $GOPATH/bin/air
|
||||
|
|
|
@ -4,18 +4,17 @@ go 1.23.0
|
|||
|
||||
require (
|
||||
github.com/distribution/reference v0.6.0
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.11.0
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2
|
||||
github.com/emicklei/go-restful/v3 v3.12.1
|
||||
github.com/go-openapi/spec v0.21.0
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/samber/lo v1.47.0
|
||||
github.com/prometheus/client_golang v1.20.4
|
||||
github.com/spf13/pflag v1.0.5
|
||||
golang.org/x/net v0.40.0
|
||||
golang.org/x/net v0.30.0
|
||||
gopkg.in/igm/sockjs-go.v2 v2.1.0
|
||||
k8s.io/api v0.32.0
|
||||
k8s.io/apiextensions-apiserver v0.32.0
|
||||
k8s.io/apimachinery v0.32.0
|
||||
k8s.io/client-go v0.32.0
|
||||
k8s.io/api v0.31.1
|
||||
k8s.io/apiextensions-apiserver v0.31.1
|
||||
k8s.io/apimachinery v0.31.1
|
||||
k8s.io/client-go v0.31.1
|
||||
k8s.io/dashboard/certificates v0.0.0-00010101000000-000000000000
|
||||
k8s.io/dashboard/client v0.0.0-00010101000000-000000000000
|
||||
k8s.io/dashboard/csrf v0.0.0-00010101000000-000000000000
|
||||
|
@ -23,100 +22,100 @@ require (
|
|||
k8s.io/dashboard/helpers v0.0.0-00010101000000-000000000000
|
||||
k8s.io/dashboard/types v0.0.0-00010101000000-000000000000
|
||||
k8s.io/klog/v2 v2.130.1
|
||||
k8s.io/kubectl v0.32.0
|
||||
k8s.io/kubectl v0.31.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // 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/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bytedance/sonic v1.12.7 // indirect
|
||||
github.com/bytedance/sonic/loader v0.2.2 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
github.com/bytedance/sonic/loader v0.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.3 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // 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/evanphx/json-patch/v5 v5.9.0 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 // indirect
|
||||
github.com/gin-contrib/sse v1.0.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/gin-gonic/gin v1.10.0 // indirect
|
||||
github.com/go-errors/errors v1.5.1 // indirect
|
||||
github.com/go-errors/errors 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/jsonreference v0.21.0 // indirect
|
||||
github.com/go-openapi/swag v0.23.0 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.23.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/gobuffalo/flect v1.0.3 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/btree v1.1.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.9 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.17.11 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/klauspost/compress v1.17.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/mailru/easyjson v0.9.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/moby/spdystream v0.5.0 // indirect
|
||||
github.com/moby/term v0.5.2 // indirect
|
||||
github.com/moby/spdystream v0.4.0 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.61.0 // indirect
|
||||
github.com/prometheus/common v0.55.0 // 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/samber/lo v1.47.0 // indirect
|
||||
github.com/spf13/cobra v1.8.1 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
github.com/zeebo/xxh3 v1.0.2 // indirect
|
||||
golang.org/x/arch v0.13.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/oauth2 v0.25.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.29.0 // indirect
|
||||
google.golang.org/protobuf v1.36.2 // indirect
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
golang.org/x/arch v0.8.0 // indirect
|
||||
golang.org/x/crypto v0.28.0 // indirect
|
||||
golang.org/x/oauth2 v0.21.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/sys v0.26.0 // indirect
|
||||
golang.org/x/term v0.25.0 // indirect
|
||||
golang.org/x/text v0.19.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/protobuf v1.34.2 // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // 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
|
||||
k8s.io/cli-runtime v0.32.0 // indirect
|
||||
k8s.io/component-base v0.32.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 // indirect
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.18.0 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
|
||||
k8s.io/cli-runtime v0.31.1 // indirect
|
||||
k8s.io/component-base v0.31.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.17.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
|
||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||
)
|
||||
|
||||
|
|
|
@ -1,26 +1,31 @@
|
|||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c h1:udKWzYgxTojEKWjV8V+WSxDXJ4NFATAsZjh8iIbsQIg=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20250102033503-faa5f7b0171c/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
|
||||
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/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/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
|
||||
github.com/bytedance/sonic v1.12.7 h1:CQU8pxOy9HToxhndH0Kx/S1qU/CuS9GnKYrGioDcU1Q=
|
||||
github.com/bytedance/sonic v1.12.7/go.mod h1:tnbal4mxOMju17EGfknm2XyYcpyCnIROYOEYuemj13I=
|
||||
github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0=
|
||||
github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
|
||||
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.2.2 h1:jxAJuN9fOot/cyz5Q6dUuMJF5OqQ6+5GfA8FjjQ0R4o=
|
||||
github.com/bytedance/sonic/loader v0.2.2/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
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/chai2010/gettext-go v1.0.3 h1:9liNh8t+u26xl5ddmWLmsOsdNLwkdRTg5AG+JnTiM80=
|
||||
github.com/chai2010/gettext-go v1.0.3/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
|
||||
github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
|
||||
github.com/chai2010/gettext-go v1.0.2/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/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/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
|
@ -32,25 +37,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/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/emicklei/go-restful-openapi/v2 v2.11.0 h1:Ur+yGxoOH/7KRmcj/UoMFqC3VeNc9VOe+/XidumxTvk=
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.11.0/go.mod h1:4CTuOXHFg3jkvCpnXN+Wkw5prVUnP8hIACssJTYorWo=
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2 h1:RfxWvGmASIwVoZIEncvXLi5HxYQ0S8rNBkPresDMt1c=
|
||||
github.com/emicklei/go-restful-openapi/v2 v2.10.2/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.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU=
|
||||
github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg=
|
||||
github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E=
|
||||
github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8=
|
||||
github.com/gin-contrib/sse v1.0.0 h1:y3bT1mUWUxDpW4JLQg/HnTqV4rozuW4tC9eFKTxYI9E=
|
||||
github.com/gin-contrib/sse v1.0.0/go.mod h1:zNuFdwarAygJBht0NTKiSi3jRf6RbqeILZ9Sp6Slhe0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
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/go-errors/errors v1.5.1 h1:ZwEMSLRCapFLflTpT7NKaAc7ukJ8ZPEjzlxt8rPN8bk=
|
||||
github.com/go-errors/errors v1.5.1/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
|
@ -73,39 +78,57 @@ 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/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/validator/v10 v10.23.0 h1:/PwmTwZhS0dPkav3cdK9kV1FsAmrL8sThn8IHr/sO+o=
|
||||
github.com/go-playground/validator/v10 v10.23.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
|
||||
github.com/go-playground/validator/v10 v10.20.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/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4=
|
||||
github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
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/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/google/btree v1.1.3 h1:CVpQJjYgC4VbzxeGVHfvZrv1ctoYCAI8vbl07Fcxlyg=
|
||||
github.com/google/btree v1.1.3/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4=
|
||||
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
|
||||
github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
|
||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
||||
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.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
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.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db h1:097atOisP2aRj7vFgYQBbFN4U4JNXUNYpxael3UzMyo=
|
||||
github.com/google/pprof v0.0.0-20241029153458-d1b30febd7db/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM=
|
||||
github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
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.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA=
|
||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/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-20180305231024-9cad4c3443a7/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/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
|
@ -114,11 +137,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/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
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.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
|
@ -136,16 +159,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-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4=
|
||||
github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
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/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
|
||||
github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
|
||||
github.com/moby/spdystream v0.5.0 h1:7r0J1Si3QO/kjRitvSLVVFUjxMEb/YLj6S9FF62JBCU=
|
||||
github.com/moby/spdystream v0.5.0/go.mod h1:xBAYlnt/ay+11ShkdFKNAG7LsyK/tmNBVvVOwrfMgdI=
|
||||
github.com/moby/term v0.5.2 h1:6qk3FJAFDs6i/q3W/pQ97SX192qKfZgGjCQqfCJkgzQ=
|
||||
github.com/moby/term v0.5.2/go.mod h1:d3djjFCrjnB+fl8NJux+EJzu0msscUP+f8it8hPkFLc=
|
||||
github.com/moby/spdystream v0.4.0 h1:Vy79D6mHeJJjiPdFEL2yku1kl0chZpJfZcPpb16BRl8=
|
||||
github.com/moby/spdystream v0.4.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.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
@ -158,14 +181,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/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0 h1:7rg/4f3rB88pb5obDgNZrNHrQ4e6WpjonchcpuBRnZM=
|
||||
github.com/onsi/ginkgo/v2 v2.21.0/go.mod h1:7Du3c42kxCUegi0IImZ1wUQzMBVecgIHjR1C+NkhLQo=
|
||||
github.com/onsi/gomega v1.35.1 h1:Cwbd75ZBPxFSuZ6T+rN/WCb/gOc6YgFBXLlZLhC7Ds4=
|
||||
github.com/onsi/gomega v1.35.1/go.mod h1:PvZbdDc8J6XJEpDK4HCuRBm8a6Fzp9/DmhC9C7yFlog=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA=
|
||||
github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
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/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
|
||||
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/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
|
@ -173,16 +196,17 @@ 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.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.20.4 h1:Tgh3Yr67PaOv/uTqloMsCEdeuFTatm5zIq5+qNN23vI=
|
||||
github.com/prometheus/client_golang v1.20.4/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/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
||||
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
||||
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||
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/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
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/samber/lo v1.47.0 h1:z7RynLwP5nbyRscyvcD043DWYoOcYRv3mV8lBeqOCLc=
|
||||
|
@ -205,8 +229,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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.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/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
|
@ -217,63 +241,98 @@ github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ=
|
|||
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.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
|
||||
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.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY=
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/arch v0.13.0 h1:KCkqVVV1kGg0X87TFysjCJ8MxtZEIU4Ja/yXGeoECdA=
|
||||
golang.org/x/arch v0.13.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
|
||||
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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
|
||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
|
||||
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.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-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-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.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
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-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.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-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-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-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-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.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24=
|
||||
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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
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-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.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE=
|
||||
golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.2 h1:R8FeyR1/eLmkutZOM5CWghmo5itiG9z0ktFlTVLuTmU=
|
||||
google.golang.org/protobuf v1.36.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/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 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -286,39 +345,44 @@ 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/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.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.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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.32.0 h1:OL9JpbvAU5ny9ga2fb24X8H6xQlVp+aJMFlgtQjR9CE=
|
||||
k8s.io/api v0.32.0/go.mod h1:4LEwHZEf6Q/cG96F3dqR965sYOfmPM7rq81BLgsE0p0=
|
||||
k8s.io/apiextensions-apiserver v0.32.0 h1:S0Xlqt51qzzqjKPxfgX1xh4HBZE+p8KKBq+k2SWNOE0=
|
||||
k8s.io/apiextensions-apiserver v0.32.0/go.mod h1:86hblMvN5yxMvZrZFX2OhIHAuFIMJIZ19bTvzkP+Fmw=
|
||||
k8s.io/apimachinery v0.32.0 h1:cFSE7N3rmEEtv4ei5X6DaJPHHX0C+upp+v5lVPiEwpg=
|
||||
k8s.io/apimachinery v0.32.0/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
||||
k8s.io/cli-runtime v0.32.0 h1:dP+OZqs7zHPpGQMCGAhectbHU2SNCuZtIimRKTv2T1c=
|
||||
k8s.io/cli-runtime v0.32.0/go.mod h1:Mai8ht2+esoDRK5hr861KRy6z0zHsSTYttNVJXgP3YQ=
|
||||
k8s.io/client-go v0.32.0 h1:DimtMcnN/JIKZcrSrstiwvvZvLjG0aSxy8PxN8IChp8=
|
||||
k8s.io/client-go v0.32.0/go.mod h1:boDWvdM1Drk4NJj/VddSLnx59X3OPgwrOo0vGbtq9+8=
|
||||
k8s.io/component-base v0.32.0 h1:d6cWHZkCiiep41ObYQS6IcgzOUQUNpywm39KVYaUqzU=
|
||||
k8s.io/component-base v0.32.0/go.mod h1:JLG2W5TUxUu5uDyKiH2R/7NnxJo1HlPoRIIbVLkK5eM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU=
|
||||
k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI=
|
||||
k8s.io/apiextensions-apiserver v0.31.1 h1:L+hwULvXx+nvTYX/MKM3kKMZyei+UiSXQWciX/N6E40=
|
||||
k8s.io/apiextensions-apiserver v0.31.1/go.mod h1:tWMPR3sgW+jsl2xm9v7lAyRF1rYEK71i9G5dRtkknoQ=
|
||||
k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U=
|
||||
k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo=
|
||||
k8s.io/cli-runtime v0.31.1 h1:/ZmKhmZ6hNqDM+yf9s3Y4KEYakNXUn5sod2LWGGwCuk=
|
||||
k8s.io/cli-runtime v0.31.1/go.mod h1:pKv1cDIaq7ehWGuXQ+A//1OIF+7DI+xudXtExMCbe9U=
|
||||
k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0=
|
||||
k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg=
|
||||
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/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7 h1:hcha5B1kVACrLujCKLbr8XWMxCxzQx42DY8QKYJrDLg=
|
||||
k8s.io/kube-openapi v0.0.0-20241212222426-2c72e554b1e7/go.mod h1:GewRfANuJ70iYzvn+i4lezLDAFzvjxZYK1gn1lWcfas=
|
||||
k8s.io/kubectl v0.32.0 h1:rpxl+ng9qeG79YA4Em9tLSfX0G8W0vfaiPVrc/WR7Xw=
|
||||
k8s.io/kubectl v0.32.0/go.mod h1:qIjSX+QgPQUgdy8ps6eKsYNF+YmFOAO3WygfucIqFiE=
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
|
||||
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
||||
k8s.io/kubectl v0.31.1 h1:ih4JQJHxsEggFqDJEHSOdJ69ZxZftgeZvYo7M/cpp24=
|
||||
k8s.io/kubectl v0.31.1/go.mod h1:aNuQoR43W6MLAtXQ/Bu4GDmoHlbhHKuyD49lmTC8eJM=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A=
|
||||
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE=
|
||||
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg=
|
||||
sigs.k8s.io/kustomize/api v0.18.0 h1:hTzp67k+3NEVInwz5BHyzc9rGxIauoXferXyjv5lWPo=
|
||||
sigs.k8s.io/kustomize/api v0.18.0/go.mod h1:f8isXnX+8b+SGLHQ6yO4JG1rdkZlvhaCf/uZbLVMb0U=
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1 h1:WvBo56Wzw3fjS+7vBjN6TeivvpbW9GmRaWZ9CIVmt4E=
|
||||
sigs.k8s.io/kustomize/kyaml v0.18.1/go.mod h1:C3L2BFVU1jgcddNBE1TxuVLgS46TjObMwW5FT9FcjYo=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
|
||||
sigs.k8s.io/kustomize/api v0.17.2 h1:E7/Fjk7V5fboiuijoZHgs4aHuexi5Y2loXlVOAVAG5g=
|
||||
sigs.k8s.io/kustomize/api v0.17.2/go.mod h1:UWTz9Ct+MvoeQsHcJ5e+vziRRkwimm3HytpZgIYqye0=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1 h1:TnxYQxFXzbmNG6gOINgGWQt09GghzgTP6mIurOgrLCQ=
|
||||
sigs.k8s.io/kustomize/kyaml v0.17.1/go.mod h1:9V0mCjIEYjlXuCdYsSXvyoy2BTsLESH7TlGV81S282U=
|
||||
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.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
|
||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
|
||||
|
|
|
@ -23,8 +23,6 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
// Load client args
|
||||
_ "k8s.io/dashboard/client/args"
|
||||
"k8s.io/dashboard/csrf"
|
||||
"k8s.io/dashboard/helpers"
|
||||
)
|
||||
|
@ -39,41 +37,26 @@ const (
|
|||
LogLevelTrace = klog.Level(5)
|
||||
)
|
||||
|
||||
const (
|
||||
defaultInsecurePort = 8000
|
||||
defaultPort = 8001
|
||||
defaultProfilerPort = 8070
|
||||
defaultPrometheusPort = 8080
|
||||
|
||||
defaultProfilerPath = "/debug/pprof/"
|
||||
defaultPrometheusPath = "/metrics"
|
||||
)
|
||||
|
||||
var (
|
||||
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'")
|
||||
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")
|
||||
|
||||
argInsecurePort = pflag.Int("insecure-port", 8000, "port to listen to for incoming HTTP requests")
|
||||
argPort = pflag.Int("port", 8001, "secure port to listen to for incoming HTTPS requests")
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
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")
|
||||
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() {
|
||||
|
@ -90,14 +73,6 @@ func init() {
|
|||
if IsCSRFProtectionEnabled() {
|
||||
csrf.Ensure()
|
||||
}
|
||||
|
||||
if *argProfiler {
|
||||
initProfiler()
|
||||
}
|
||||
|
||||
if *argPrometheusEnabled {
|
||||
initPrometheus()
|
||||
}
|
||||
}
|
||||
|
||||
func Address() string {
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
// 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)
|
||||
}
|
||||
}()
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
// 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,23 +77,14 @@ func formatRequestLog(request *restful.Request) string {
|
|||
content = "{ content hidden }"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(
|
||||
RequestLogString,
|
||||
request.Request.Proto,
|
||||
request.Request.Method,
|
||||
uri,
|
||||
getRemoteAddr(request.Request),
|
||||
content,
|
||||
)
|
||||
return fmt.Sprintf(RequestLogString, time.Now().Format(time.RFC3339), request.Request.Proto,
|
||||
request.Request.Method, uri, getRemoteAddr(request.Request), content)
|
||||
}
|
||||
|
||||
// formatResponseLog formats response log string.
|
||||
func formatResponseLog(response *restful.Response, request *restful.Request) string {
|
||||
return fmt.Sprintf(
|
||||
ResponseLogString,
|
||||
getRemoteAddr(request.Request),
|
||||
response.StatusCode(),
|
||||
)
|
||||
return fmt.Sprintf(ResponseLogString, time.Now().Format(time.RFC3339),
|
||||
getRemoteAddr(request.Request), response.StatusCode())
|
||||
}
|
||||
|
||||
// checkSensitiveUrl checks if a string matches against a sensitive URL
|
||||
|
|
|
@ -19,7 +19,6 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
)
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
@ -32,9 +33,6 @@ import (
|
|||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/args"
|
||||
)
|
||||
|
||||
const END_OF_TRANSMISSION = "\u0004"
|
||||
|
@ -166,7 +164,7 @@ func (sm *SessionMap) Close(sessionId string, status uint32, reason string) {
|
|||
ses := sm.Sessions[sessionId]
|
||||
err := ses.sockJSSession.Close(status, reason)
|
||||
if err != nil {
|
||||
klog.Error(err)
|
||||
log.Println(err)
|
||||
}
|
||||
close(ses.sizeChan)
|
||||
delete(sm.Sessions, sessionId)
|
||||
|
@ -184,22 +182,22 @@ func handleTerminalSession(session sockjs.Session) {
|
|||
)
|
||||
|
||||
if buf, err = session.Recv(); err != nil {
|
||||
klog.Errorf("handleTerminalSession: can't Recv: %v", err)
|
||||
log.Printf("handleTerminalSession: can't Recv: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = json.Unmarshal([]byte(buf), &msg); err != nil {
|
||||
klog.Errorf("handleTerminalSession: can't UnMarshal (%v): %s", err, buf)
|
||||
log.Printf("handleTerminalSession: can't UnMarshal (%v): %s", err, buf)
|
||||
return
|
||||
}
|
||||
|
||||
if msg.Op != "bind" {
|
||||
klog.V(args.LogLevelVerbose).Infof("handleTerminalSession: expected 'bind' message, got: %s", buf)
|
||||
log.Printf("handleTerminalSession: expected 'bind' message, got: %s", buf)
|
||||
return
|
||||
}
|
||||
|
||||
if terminalSession = terminalSessions.Get(msg.SessionID); terminalSession.id == "" {
|
||||
klog.V(args.LogLevelVerbose).Infof("handleTerminalSession: can't find session '%s'", msg.SessionID)
|
||||
log.Printf("handleTerminalSession: can't find session '%s'", msg.SessionID)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -33,16 +33,16 @@ type Handler struct {
|
|||
//
|
||||
// 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`.
|
||||
func (in Handler) Install(ws *restful.WebService) {
|
||||
func (self Handler) Install(ws *restful.WebService) {
|
||||
ws.Route(
|
||||
ws.GET("/integration/{name}/state").
|
||||
To(in.handleGetState).
|
||||
To(self.handleGetState).
|
||||
Writes(api.IntegrationState{}))
|
||||
}
|
||||
|
||||
func (in Handler) handleGetState(request *restful.Request, response *restful.Response) {
|
||||
func (self Handler) handleGetState(request *restful.Request, response *restful.Response) {
|
||||
integrationName := request.PathParameter("name")
|
||||
state, err := in.manager.GetState(api.IntegrationID(integrationName))
|
||||
state, err := self.manager.GetState(api.IntegrationID(integrationName))
|
||||
if err != nil {
|
||||
response.AddHeader("Content-Type", "text/plain")
|
||||
_ = 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.
|
||||
// Might depend on dependencies version how they are constructed.
|
||||
func normalize(msg string) string {
|
||||
return strings.ReplaceAll(msg, "\"", "")
|
||||
return strings.Replace(msg, "\"", "", -1)
|
||||
}
|
||||
|
||||
func TestNewIntegrationManager(t *testing.T) {
|
||||
|
@ -82,6 +82,6 @@ func TestIntegrationManager_GetState(t *testing.T) {
|
|||
func TestIntegrationManager_Metric(t *testing.T) {
|
||||
metricManager := integration.NewIntegrationManager().Metric()
|
||||
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.
|
||||
type Label map[types.ResourceKind][]apimachinery.UID
|
||||
|
||||
// AddMetricLabel returns a unique combined Label of in and other resource.
|
||||
// AddMetricLabel returns a unique combined Label of self and other resource.
|
||||
// New label describes both resources.
|
||||
func (in Label) AddMetricLabel(other Label) Label {
|
||||
func (self Label) AddMetricLabel(other Label) Label {
|
||||
if other == nil {
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
uniqueMap := map[apimachinery.UID]bool{}
|
||||
for _, v := range in {
|
||||
for _, v := range self {
|
||||
for _, t := range v {
|
||||
uniqueMap[t] = true
|
||||
}
|
||||
|
@ -144,11 +144,11 @@ func (in Label) AddMetricLabel(other Label) Label {
|
|||
for k, v := range other {
|
||||
for _, t := range v {
|
||||
if _, exists := uniqueMap[t]; !exists {
|
||||
in[k] = append(in[k], t)
|
||||
self[k] = append(self[k], t)
|
||||
}
|
||||
}
|
||||
}
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func (in *Metric) AddMetricPoint(item MetricPoint) []MetricPoint {
|
||||
in.MetricPoints = append(in.MetricPoints, item)
|
||||
return in.MetricPoints
|
||||
func (metric *Metric) AddMetricPoint(item MetricPoint) []MetricPoint {
|
||||
metric.MetricPoints = append(metric.MetricPoints, item)
|
||||
return metric.MetricPoints
|
||||
}
|
||||
|
||||
// String implements stringer interface to allow easy printing
|
||||
func (in Metric) String() string {
|
||||
return "{\nDataPoints: " + fmt.Sprintf("%v", in.DataPoints) +
|
||||
"\nMetricPoints: " + fmt.Sprintf("%v", in.MetricPoints) +
|
||||
"\nMetricName: " + in.MetricName +
|
||||
"\nLabel: " + fmt.Sprintf("%v", in.Label) +
|
||||
"\nAggregate: " + fmt.Sprintf("%v", in.Aggregate)
|
||||
func (self Metric) String() string {
|
||||
return "{\nDataPoints: " + fmt.Sprintf("%v", self.DataPoints) +
|
||||
"\nMetricPoints: " + fmt.Sprintf("%v", self.MetricPoints) +
|
||||
"\nMetricName: " + self.MetricName +
|
||||
"\nLabel: " + fmt.Sprintf("%v", self.Label) +
|
||||
"\nAggregate: " + fmt.Sprintf("%v", self.Aggregate)
|
||||
}
|
||||
|
||||
// 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)
|
||||
func (in MetricPromise) GetMetric() (*Metric, error) {
|
||||
err := <-in.Error
|
||||
func (self MetricPromise) GetMetric() (*Metric, error) {
|
||||
err := <-self.Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return <-in.Metric, nil
|
||||
return <-self.Metric, nil
|
||||
}
|
||||
|
||||
// NewMetricPromise creates a MetricPromise structure with both channels of length 1.
|
||||
|
@ -231,10 +231,10 @@ type MetricPromises []MetricPromise
|
|||
|
||||
// GetMetrics returns all metrics from MetricPromises.
|
||||
// In case of no metrics were downloaded it does not initialise []Metric and returns nil.
|
||||
func (in MetricPromises) GetMetrics() ([]Metric, error) {
|
||||
func (self MetricPromises) GetMetrics() ([]Metric, error) {
|
||||
result := make([]Metric, 0)
|
||||
|
||||
for _, metricPromise := range in {
|
||||
for _, metricPromise := range self {
|
||||
metric, err := metricPromise.GetMetric()
|
||||
if err != nil {
|
||||
// Do not fail when cannot resolve one of the metrics promises and return what can be resolved.
|
||||
|
@ -252,8 +252,8 @@ func (in MetricPromises) GetMetrics() ([]Metric, error) {
|
|||
}
|
||||
|
||||
// PutMetrics forwards provided list of metrics to all channels. If provided err is not nil, error will be forwarded.
|
||||
func (in MetricPromises) PutMetrics(metrics []Metric, err error) {
|
||||
for i, metricPromise := range in {
|
||||
func (self MetricPromises) PutMetrics(metrics []Metric, err error) {
|
||||
for i, metricPromise := range self {
|
||||
if err != nil {
|
||||
metricPromise.Metric <- nil
|
||||
} else {
|
||||
|
|
|
@ -52,39 +52,39 @@ type metricManager struct {
|
|||
}
|
||||
|
||||
// AddClient implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) AddClient(client metricapi.MetricClient) MetricManager {
|
||||
func (self *metricManager) AddClient(client metricapi.MetricClient) MetricManager {
|
||||
if client != nil {
|
||||
in.clients[client.ID()] = client
|
||||
self.clients[client.ID()] = client
|
||||
}
|
||||
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
// Client implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) Client() metricapi.MetricClient {
|
||||
return in.active
|
||||
func (self *metricManager) Client() metricapi.MetricClient {
|
||||
return self.active
|
||||
}
|
||||
|
||||
// Enable implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) Enable(id integrationapi.IntegrationID) error {
|
||||
metricClient, exists := in.clients[id]
|
||||
func (self *metricManager) Enable(id integrationapi.IntegrationID) error {
|
||||
metricClient, exists := self.clients[id]
|
||||
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()
|
||||
if err != nil {
|
||||
return fmt.Errorf("health check failed: %s", err.Error())
|
||||
return fmt.Errorf("Health check failed: %s", err.Error())
|
||||
}
|
||||
|
||||
in.active = metricClient
|
||||
self.active = metricClient
|
||||
return nil
|
||||
}
|
||||
|
||||
// EnableWithRetry implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) EnableWithRetry(id integrationapi.IntegrationID, period time.Duration) {
|
||||
func (self *metricManager) EnableWithRetry(id integrationapi.IntegrationID, period time.Duration) {
|
||||
go wait.Forever(func() {
|
||||
metricClient, exists := in.clients[id]
|
||||
metricClient, exists := self.clients[id]
|
||||
if !exists {
|
||||
klog.V(5).InfoS("Metric client does not exist", "clientID", id)
|
||||
return
|
||||
|
@ -92,22 +92,22 @@ func (in *metricManager) EnableWithRetry(id integrationapi.IntegrationID, period
|
|||
|
||||
err := metricClient.HealthCheck()
|
||||
if err != nil {
|
||||
in.active = nil
|
||||
self.active = nil
|
||||
klog.Errorf("Metric client health check failed: %s. Retrying in %d seconds.", err, period)
|
||||
return
|
||||
}
|
||||
|
||||
if in.active == nil {
|
||||
if self.active == nil {
|
||||
klog.V(1).Infof("Successful request to %s", id)
|
||||
in.active = metricClient
|
||||
self.active = metricClient
|
||||
}
|
||||
}, period*time.Second)
|
||||
}
|
||||
|
||||
// List implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) List() []integrationapi.Integration {
|
||||
func (self *metricManager) List() []integrationapi.Integration {
|
||||
result := make([]integrationapi.Integration, 0)
|
||||
for _, c := range in.clients {
|
||||
for _, c := range self.clients {
|
||||
result = append(result, c.(integrationapi.Integration))
|
||||
}
|
||||
|
||||
|
@ -115,16 +115,16 @@ func (in *metricManager) List() []integrationapi.Integration {
|
|||
}
|
||||
|
||||
// ConfigureSidecar implements metric manager interface. See MetricManager for more information.
|
||||
func (in *metricManager) ConfigureSidecar(host string) MetricManager {
|
||||
func (self *metricManager) ConfigureSidecar(host string) MetricManager {
|
||||
inClusterClient := client.InClusterClient()
|
||||
metricClient, err := sidecar.CreateSidecarClient(host, inClusterClient)
|
||||
if err != nil {
|
||||
klog.Errorf("There was an error during sidecar client creation: %s", err.Error())
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
in.clients[metricClient.ID()] = metricClient
|
||||
return in
|
||||
self.clients[metricClient.ID()] = metricClient
|
||||
return self
|
||||
}
|
||||
|
||||
// NewMetricManager creates metric manager.
|
||||
|
|
|
@ -33,25 +33,25 @@ func (FakeMetricClient) ID() integrationapi.IntegrationID {
|
|||
return fakeMetricClientID
|
||||
}
|
||||
|
||||
func (in FakeMetricClient) HealthCheck() error {
|
||||
if in.healthOk {
|
||||
func (self FakeMetricClient) HealthCheck() error {
|
||||
if self.healthOk {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.NewInvalid("test-error")
|
||||
}
|
||||
|
||||
func (in FakeMetricClient) DownloadMetric(selectors []api.ResourceSelector, metricName string,
|
||||
func (self FakeMetricClient) DownloadMetric(selectors []api.ResourceSelector, metricName string,
|
||||
cachedResources *api.CachedResources) api.MetricPromises {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (in FakeMetricClient) DownloadMetrics(selectors []api.ResourceSelector, metricNames []string,
|
||||
func (self FakeMetricClient) DownloadMetrics(selectors []api.ResourceSelector, metricNames []string,
|
||||
cachedResources *api.CachedResources) api.MetricPromises {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (in FakeMetricClient) AggregateMetrics(metrics api.MetricPromises, metricName string,
|
||||
func (self FakeMetricClient) AggregateMetrics(metrics api.MetricPromises, metricName string,
|
||||
aggregations api.AggregationModes) api.MetricPromises {
|
||||
return nil
|
||||
}
|
||||
|
@ -95,7 +95,7 @@ func TestMetricManager_Enable(t *testing.T) {
|
|||
client api.MetricClient
|
||||
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},
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
@ -40,56 +41,56 @@ type sidecarClient struct {
|
|||
// Implement Integration interface.
|
||||
|
||||
// HealthCheck implements integration app interface. See Integration interface for more information.
|
||||
func (in sidecarClient) HealthCheck() error {
|
||||
if in.client == nil {
|
||||
return errors.New("sidecar not configured")
|
||||
func (self sidecarClient) HealthCheck() error {
|
||||
if self.client == nil {
|
||||
return errors.New("Sidecar not configured")
|
||||
}
|
||||
|
||||
return in.client.HealthCheck()
|
||||
return self.client.HealthCheck()
|
||||
}
|
||||
|
||||
// ID implements integration app interface. See Integration interface for more information.
|
||||
func (in sidecarClient) ID() integrationapi.IntegrationID {
|
||||
func (self sidecarClient) ID() integrationapi.IntegrationID {
|
||||
return integrationapi.SidecarIntegrationID
|
||||
}
|
||||
|
||||
// Implement MetricClient interface
|
||||
|
||||
// DownloadMetrics implements metric client interface. See MetricClient for more information.
|
||||
func (in sidecarClient) DownloadMetrics(selectors []metricapi.ResourceSelector,
|
||||
func (self sidecarClient) DownloadMetrics(selectors []metricapi.ResourceSelector,
|
||||
metricNames []string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
||||
result := metricapi.MetricPromises{}
|
||||
for _, metricName := range metricNames {
|
||||
collectedMetrics := in.DownloadMetric(selectors, metricName, cachedResources)
|
||||
collectedMetrics := self.DownloadMetric(selectors, metricName, cachedResources)
|
||||
result = append(result, collectedMetrics...)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// DownloadMetric implements metric client interface. See MetricClient for more information.
|
||||
func (in sidecarClient) DownloadMetric(selectors []metricapi.ResourceSelector,
|
||||
func (self sidecarClient) DownloadMetric(selectors []metricapi.ResourceSelector,
|
||||
metricName string, cachedResources *metricapi.CachedResources) metricapi.MetricPromises {
|
||||
sidecarSelectors := getSidecarSelectors(selectors, cachedResources)
|
||||
|
||||
// Downloads metric in the fastest possible way by first compressing SidecarSelectors and later unpacking the result to separate boxes.
|
||||
compressedSelectors, reverseMapping := compress(sidecarSelectors)
|
||||
return in.downloadMetric(sidecarSelectors, compressedSelectors, reverseMapping, metricName)
|
||||
return self.downloadMetric(sidecarSelectors, compressedSelectors, reverseMapping, metricName)
|
||||
}
|
||||
|
||||
// AggregateMetrics implements metric client interface. See MetricClient for more information.
|
||||
func (in sidecarClient) AggregateMetrics(metrics metricapi.MetricPromises, metricName string,
|
||||
func (self sidecarClient) AggregateMetrics(metrics metricapi.MetricPromises, metricName string,
|
||||
aggregations metricapi.AggregationModes) metricapi.MetricPromises {
|
||||
return common.AggregateMetricPromises(metrics, metricName, aggregations, nil)
|
||||
}
|
||||
|
||||
func (in sidecarClient) downloadMetric(sidecarSelectors []sidecarSelector,
|
||||
func (self sidecarClient) downloadMetric(sidecarSelectors []sidecarSelector,
|
||||
compressedSelectors []sidecarSelector, reverseMapping map[string][]int,
|
||||
metricName string) metricapi.MetricPromises {
|
||||
// collect all the required data (as promises)
|
||||
unassignedResourcePromisesList := make([]metricapi.MetricPromises, len(compressedSelectors))
|
||||
for selectorId, compressedSelector := range compressedSelectors {
|
||||
unassignedResourcePromisesList[selectorId] =
|
||||
in.downloadMetricForEachTargetResource(compressedSelector, metricName)
|
||||
self.downloadMetricForEachTargetResource(compressedSelector, metricName)
|
||||
}
|
||||
// prepare final result
|
||||
result := metricapi.NewMetricPromises(len(sidecarSelectors))
|
||||
|
@ -134,28 +135,28 @@ func (in sidecarClient) downloadMetric(sidecarSelectors []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 in.Resources.
|
||||
func (in sidecarClient) downloadMetricForEachTargetResource(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||
// 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.
|
||||
func (self sidecarClient) downloadMetricForEachTargetResource(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||
var notAggregatedMetrics metricapi.MetricPromises
|
||||
if SidecarAllInOneDownloadConfig[selector.TargetResourceType] {
|
||||
notAggregatedMetrics = in.allInOneDownload(selector, metricName)
|
||||
notAggregatedMetrics = self.allInOneDownload(selector, metricName)
|
||||
} else {
|
||||
notAggregatedMetrics = metricapi.MetricPromises{}
|
||||
for i := range selector.Resources {
|
||||
notAggregatedMetrics = append(notAggregatedMetrics, in.ithResourceDownload(selector, metricName, i))
|
||||
notAggregatedMetrics = append(notAggregatedMetrics, self.ithResourceDownload(selector, metricName, i))
|
||||
}
|
||||
}
|
||||
return notAggregatedMetrics
|
||||
}
|
||||
|
||||
// ithResourceDownload downloads metric for ith resource in in.Resources. Use only in case all in 1 download is not supported
|
||||
// ithResourceDownload downloads metric for ith resource in self.Resources. Use only in case all in 1 download is not supported
|
||||
// for this resource type.
|
||||
func (in sidecarClient) ithResourceDownload(selector sidecarSelector, metricName string,
|
||||
func (self sidecarClient) ithResourceDownload(selector sidecarSelector, metricName string,
|
||||
i int) metricapi.MetricPromise {
|
||||
result := metricapi.NewMetricPromise()
|
||||
go func() {
|
||||
rawResult := metricapi.SidecarMetricResultList{}
|
||||
err := in.unmarshalType(selector.Path+selector.Resources[i]+"/metrics/"+metricName, &rawResult)
|
||||
err := self.unmarshalType(selector.Path+selector.Resources[i]+"/metrics/"+metricName, &rawResult)
|
||||
if err != nil {
|
||||
result.Metric <- nil
|
||||
result.Error <- err
|
||||
|
@ -185,9 +186,9 @@ func (in sidecarClient) ithResourceDownload(selector sidecarSelector, metricName
|
|||
return result
|
||||
}
|
||||
|
||||
// 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 in.Resources is preserved.
|
||||
func (in sidecarClient) allInOneDownload(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||
// allInOneDownload downloads metrics for all resources present in self.Resources in one request.
|
||||
// returns a list of metric promises - one promise for each resource. Order of self.Resources is preserved.
|
||||
func (self sidecarClient) allInOneDownload(selector sidecarSelector, metricName string) metricapi.MetricPromises {
|
||||
result := metricapi.NewMetricPromises(len(selector.Resources))
|
||||
go func() {
|
||||
if len(selector.Resources) == 0 {
|
||||
|
@ -195,7 +196,7 @@ func (in sidecarClient) allInOneDownload(selector sidecarSelector, metricName st
|
|||
}
|
||||
rawResults := metricapi.SidecarMetricResultList{}
|
||||
|
||||
err := in.unmarshalType(selector.Path+strings.Join(selector.Resources, ",")+"/metrics/"+metricName, &rawResults)
|
||||
err := self.unmarshalType(selector.Path+strings.Join(selector.Resources, ",")+"/metrics/"+metricName, &rawResults)
|
||||
|
||||
if err != nil {
|
||||
result.PutMetrics(nil, err)
|
||||
|
@ -203,7 +204,7 @@ func (in sidecarClient) allInOneDownload(selector sidecarSelector, metricName st
|
|||
}
|
||||
|
||||
if len(result) != len(rawResults.Items) {
|
||||
klog.V(args.LogLevelVerbose).Infof(`received %d resources from sidecar instead of %d`, len(rawResults.Items), len(result))
|
||||
log.Printf(`received %d resources from sidecar instead of %d`, len(rawResults.Items), len(result))
|
||||
}
|
||||
|
||||
// rawResult.Items have indefinite order.
|
||||
|
@ -248,8 +249,8 @@ func (in sidecarClient) allInOneDownload(selector sidecarSelector, metricName st
|
|||
|
||||
// unmarshalType performs sidecar GET request to the specifies path and transfers
|
||||
// the data to the interface provided.
|
||||
func (in sidecarClient) unmarshalType(path string, v interface{}) error {
|
||||
rawData, err := in.client.Get("/api/v1/dashboard/" + path).DoRaw(context.TODO())
|
||||
func (self sidecarClient) unmarshalType(path string, v interface{}) error {
|
||||
rawData, err := self.client.Get("/api/v1/dashboard/" + path).DoRaw(context.TODO())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -43,7 +44,7 @@ func areErrorsEqual(err1, err2 error) bool {
|
|||
// Removes all quote signs that might have been added to the message.
|
||||
// Might depend on dependencies version how they are constructed.
|
||||
func normalize(msg string) string {
|
||||
return strings.ReplaceAll(msg, "\"", "")
|
||||
return strings.Replace(msg, "\"", "", -1)
|
||||
}
|
||||
|
||||
type GlobalCounter int32
|
||||
|
@ -76,27 +77,28 @@ type FakeRequest struct {
|
|||
type PodData map[string][]metricapi.MetricPoint
|
||||
type NodeData map[string][]metricapi.MetricPoint
|
||||
|
||||
func (in FakeSidecar) Get(path string) RequestInterface {
|
||||
return FakeRequest{in.PodData, in.NodeData, path}
|
||||
func (self FakeSidecar) Get(path string) RequestInterface {
|
||||
return FakeRequest{self.PodData, self.NodeData, path}
|
||||
}
|
||||
|
||||
func (in FakeSidecar) GetNumberOfRequestsMade() int {
|
||||
func (self FakeSidecar) GetNumberOfRequestsMade() int {
|
||||
num := int(_NumRequests.get())
|
||||
_NumRequests.set(0)
|
||||
return num
|
||||
}
|
||||
|
||||
func (in FakeSidecar) HealthCheck() error {
|
||||
func (self FakeSidecar) HealthCheck() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (in FakeSidecar) ID() integrationapi.IntegrationID {
|
||||
func (self FakeSidecar) ID() integrationapi.IntegrationID {
|
||||
return "fakeSidecar"
|
||||
}
|
||||
|
||||
func (in FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
||||
func (self FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
||||
_NumRequests.increment()
|
||||
path := in.Path
|
||||
log.Println("Performing req...")
|
||||
path := self.Path
|
||||
time.Sleep(50 * time.Millisecond) // simulate response delay of 0.05 seconds
|
||||
if strings.Contains(path, "/pod-list/") {
|
||||
r, _ := regexp.Compile(`\/pod\-list\/(.+)\/metrics\/`)
|
||||
|
@ -115,9 +117,10 @@ func (in FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
|||
|
||||
items := metricapi.SidecarMetricResultList{}
|
||||
for _, pod := range requestedPods {
|
||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: in.PodData[pod+"/"+namespace], UIDs: []string{pod}})
|
||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: self.PodData[pod+"/"+namespace], UIDs: []string{pod}})
|
||||
}
|
||||
x, err := json.Marshal(items)
|
||||
log.Println("Got you:", string(x))
|
||||
return x, err
|
||||
|
||||
} else if strings.Contains(path, "/nodes/") {
|
||||
|
@ -129,16 +132,17 @@ func (in FakeRequest) DoRaw(ctx context.Context) ([]byte, error) {
|
|||
requestedNode := submatch[1]
|
||||
|
||||
items := metricapi.SidecarMetricResultList{}
|
||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: in.NodeData[requestedNode], UIDs: []string{requestedNode}})
|
||||
items.Items = append(items.Items, metricapi.SidecarMetric{MetricPoints: self.NodeData[requestedNode], UIDs: []string{requestedNode}})
|
||||
|
||||
x, err := json.Marshal(items)
|
||||
log.Println("Got you:", string(x))
|
||||
return x, err
|
||||
} else {
|
||||
return nil, fmt.Errorf("Invalid request url %s", path)
|
||||
}
|
||||
}
|
||||
|
||||
func (in FakeRequest) AbsPath(segments ...string) *rest.Request {
|
||||
func (self FakeRequest) AbsPath(segments ...string) *rest.Request {
|
||||
return &rest.Request{}
|
||||
}
|
||||
|
||||
|
@ -290,6 +294,7 @@ func TestDownloadMetric(t *testing.T) {
|
|||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
log.Println("-----------\n\n\n", testCase.Info, int(_NumRequests.get()))
|
||||
hClient := sidecarClient{fakeSidecarClient}
|
||||
promises := hClient.DownloadMetric(testCase.Selectors, "",
|
||||
&metricapi.CachedResources{})
|
||||
|
|
|
@ -56,8 +56,8 @@ func (c inClusterSidecarClient) Get(path string) RequestInterface {
|
|||
|
||||
// HealthCheck does a health check of the application.
|
||||
// Returns nil if connection to application can be established, error object otherwise.
|
||||
func (in inClusterSidecarClient) HealthCheck() error {
|
||||
_, err := in.client.Get().
|
||||
func (self inClusterSidecarClient) HealthCheck() error {
|
||||
_, err := self.client.Get().
|
||||
Namespace(args.Namespace()).
|
||||
Resource("services").
|
||||
Name(args.MetricsScraperServiceName()).
|
||||
|
@ -80,7 +80,7 @@ func (c remoteSidecarClient) Get(path string) RequestInterface {
|
|||
|
||||
// HealthCheck does a health check of the application.
|
||||
// Returns nil if connection to application can be established, error object otherwise.
|
||||
func (in remoteSidecarClient) HealthCheck() error {
|
||||
_, err := in.Get("healthz").AbsPath("/").DoRaw(context.TODO())
|
||||
func (self remoteSidecarClient) HealthCheck() error {
|
||||
_, err := self.Get("healthz").AbsPath("/").DoRaw(context.TODO())
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@ package sidecar
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/emicklei/go-restful/v3/log"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apimachinery "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/helpers"
|
||||
|
@ -39,7 +39,7 @@ func getSidecarSelectors(selectors []metricapi.ResourceSelector,
|
|||
for i, selector := range selectors {
|
||||
sidecarSelector, err := getSidecarSelector(selector, cachedResources)
|
||||
if err != nil {
|
||||
klog.Errorf("There was an error during transformation to sidecar selector: %s", err.Error())
|
||||
log.Printf("There was an error during transformation to sidecar selector: %s", err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ func getSidecarSelector(selector metricapi.ResourceSelector,
|
|||
selector.Namespace, podListToNameList(myPods), podListToUIDList(myPods))
|
||||
}
|
||||
// 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.
|
||||
|
@ -76,11 +76,11 @@ func getSidecarSelector(selector metricapi.ResourceSelector,
|
|||
func getMyPodsFromCache(selector metricapi.ResourceSelector, cachedPods []v1.Pod) (matchingPods []v1.Pod, err error) {
|
||||
switch {
|
||||
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)
|
||||
case selector.ResourceType == types.ResourceKindDeployment:
|
||||
for _, pod := range cachedPods {
|
||||
if pod.Namespace == selector.Namespace && helpers.IsSelectorMatching(selector.Selector, pod.Labels) {
|
||||
if pod.ObjectMeta.Namespace == selector.Namespace && helpers.IsSelectorMatching(selector.Selector, pod.Labels) {
|
||||
matchingPods = append(matchingPods, pod)
|
||||
}
|
||||
}
|
||||
|
@ -104,23 +104,22 @@ func getMyPodsFromCache(selector metricapi.ResourceSelector, cachedPods []v1.Pod
|
|||
func newSidecarSelectorFromNativeResource(resourceType types.ResourceKind, namespace string,
|
||||
resourceNames []string, resourceUIDs []apimachinery.UID) (sidecarSelector, error) {
|
||||
// Here we have 2 possibilities because this module allows downloading Nodes and Pods from sidecar
|
||||
switch resourceType {
|
||||
case types.ResourceKindPod:
|
||||
if resourceType == types.ResourceKindPod {
|
||||
return sidecarSelector{
|
||||
TargetResourceType: types.ResourceKindPod,
|
||||
Path: `namespaces/` + namespace + `/pod-list/`,
|
||||
Resources: resourceNames,
|
||||
Label: metricapi.Label{resourceType: resourceUIDs},
|
||||
}, nil
|
||||
case types.ResourceKindNode:
|
||||
} else if resourceType == types.ResourceKindNode {
|
||||
return sidecarSelector{
|
||||
TargetResourceType: types.ResourceKindNode,
|
||||
Path: `nodes/`,
|
||||
Resources: resourceNames,
|
||||
Label: metricapi.Label{resourceType: resourceUIDs},
|
||||
}, nil
|
||||
default:
|
||||
return sidecarSelector{}, fmt.Errorf(`resource "%s" is not a native sidecar resource type or is not supported`, resourceType)
|
||||
} else {
|
||||
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
|
||||
|
||||
func (in RoleCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self RoleCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
package clusterrole
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -39,7 +40,7 @@ type ClusterRole struct {
|
|||
}
|
||||
|
||||
func GetClusterRoleList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleList, error) {
|
||||
klog.V(4).Info("Getting list of RBAC roles")
|
||||
log.Println("Getting list of RBAC roles")
|
||||
channels := &common.ResourceChannels{
|
||||
ClusterRoleList: common.GetClusterRoleListChannel(client, 1),
|
||||
}
|
||||
|
|
|
@ -22,14 +22,14 @@ import (
|
|||
|
||||
type ClusterRoleBindingCell ClusterRoleBinding
|
||||
|
||||
func (in ClusterRoleBindingCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self ClusterRoleBindingCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
package clusterrolebinding
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -43,7 +44,7 @@ type ClusterRoleBinding struct {
|
|||
|
||||
// GetClusterRoleBindingList returns a list of all ClusterRoleBindings in the cluster.
|
||||
func GetClusterRoleBindingList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*ClusterRoleBindingList, error) {
|
||||
klog.V(4).Infof("Getting list of all clusterRoleBindings in the cluster")
|
||||
log.Print("Getting list of all clusterRoleBindings in the cluster")
|
||||
channels := &common.ResourceChannels{
|
||||
ClusterRoleBindingList: common.GetClusterRoleBindingListChannel(client, 1),
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import (
|
|||
batch "k8s.io/api/batch/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
policyv1 "k8s.io/api/policy/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
|
@ -125,8 +124,6 @@ type ResourceChannels struct {
|
|||
|
||||
// List and error channels to ClusterRoleBindings
|
||||
ClusterRoleBindingList ClusterRoleBindingListChannel
|
||||
|
||||
PodDisruptionBudget PodDisruptionBudgetListChannel
|
||||
}
|
||||
|
||||
// ServiceListChannel is a list and error channels to Services.
|
||||
|
@ -148,7 +145,7 @@ func GetServiceListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
|||
list, err := client.CoreV1().Services(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []v1.Service
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -181,7 +178,7 @@ func GetIngressListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
|||
list, err := client.NetworkingV1().Ingresses(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []networkingv1.Ingress
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -298,7 +295,7 @@ func GetEventListChannelWithOptions(client client.Interface,
|
|||
list, err := client.CoreV1().Events(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
||||
var filteredItems []v1.Event
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +365,7 @@ func GetPodListChannelWithOptions(client client.Interface, nsQuery *NamespaceQue
|
|||
list, err := client.CoreV1().Pods(nsQuery.ToRequestParam()).List(context.TODO(), options)
|
||||
var filteredItems []v1.Pod
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -404,7 +401,7 @@ func GetReplicationControllerListChannel(client client.Interface,
|
|||
List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []v1.ReplicationController
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -439,7 +436,7 @@ func GetDeploymentListChannel(client client.Interface,
|
|||
List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []apps.Deployment
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +477,7 @@ func GetReplicaSetListChannelWithOptions(client client.Interface, nsQuery *Names
|
|||
List(context.TODO(), options)
|
||||
var filteredItems []apps.ReplicaSet
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -512,7 +509,7 @@ func GetDaemonSetListChannel(client client.Interface, nsQuery *NamespaceQuery, n
|
|||
list, err := client.AppsV1().DaemonSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []apps.DaemonSet
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -544,7 +541,7 @@ func GetJobListChannel(client client.Interface,
|
|||
list, err := client.BatchV1().Jobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []batch.Job
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -575,7 +572,7 @@ func GetCronJobListChannel(client client.Interface, nsQuery *NamespaceQuery, num
|
|||
list, err := client.BatchV1().CronJobs(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []batch.CronJob
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -608,7 +605,7 @@ func GetStatefulSetListChannel(client client.Interface,
|
|||
statefulSets, err := client.AppsV1().StatefulSets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []apps.StatefulSet
|
||||
for _, item := range statefulSets.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +639,7 @@ func GetConfigMapListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
|||
list, err := client.CoreV1().ConfigMaps(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []v1.ConfigMap
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -676,7 +673,7 @@ func GetSecretListChannel(client client.Interface, nsQuery *NamespaceQuery,
|
|||
list, err := client.CoreV1().Secrets(nsQuery.ToRequestParam()).List(context.TODO(), helpers.ListEverything)
|
||||
var filteredItems []v1.Secret
|
||||
for _, item := range list.Items {
|
||||
if nsQuery.Matches(item.Namespace) {
|
||||
if nsQuery.Matches(item.ObjectMeta.Namespace) {
|
||||
filteredItems = append(filteredItems, item)
|
||||
}
|
||||
}
|
||||
|
@ -844,30 +841,6 @@ func GetPersistentVolumeClaimListChannel(client client.Interface, nsQuery *Names
|
|||
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.
|
||||
type CustomResourceDefinitionChannelV1 struct {
|
||||
List chan *apiextensions.CustomResourceDefinitionList
|
||||
|
|
|
@ -27,7 +27,7 @@ func FilterNamespacedServicesBySelector(services []v1.Service, namespace string,
|
|||
|
||||
var matchingServices []v1.Service
|
||||
for _, service := range services {
|
||||
if service.Namespace == namespace &&
|
||||
if service.ObjectMeta.Namespace == namespace &&
|
||||
helpers.IsSelectorMatching(service.Spec.Selector, resourceSelector) {
|
||||
matchingServices = append(matchingServices, service)
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
|
||||
type ConfigMapCell api.ConfigMap
|
||||
|
||||
func (in ConfigMapCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self ConfigMapCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -16,11 +16,11 @@ package configmap
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// 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
|
||||
func GetConfigMapDetail(client kubernetes.Interface, namespace, name string) (*ConfigMapDetail, error) {
|
||||
klog.V(4).Infof("Getting details of %s config map in %s namespace", name, namespace)
|
||||
log.Printf("Getting details of %s config map in %s namespace", name, namespace)
|
||||
|
||||
rawConfigMap, err := client.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
package configmap
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -46,7 +47,7 @@ type ConfigMap struct {
|
|||
|
||||
// GetConfigMapList returns a list of all ConfigMaps in the cluster.
|
||||
func GetConfigMapList(client kubernetes.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*ConfigMapList, error) {
|
||||
klog.V(4).Infof("Getting list config maps in the namespace %s", nsQuery.ToRequestParam())
|
||||
log.Printf("Getting list config maps in the namespace %s", nsQuery.ToRequestParam())
|
||||
channels := &common.ResourceChannels{
|
||||
ConfigMapList: common.GetConfigMapListChannel(client, nsQuery, 1),
|
||||
}
|
||||
|
|
|
@ -112,46 +112,46 @@ func NewResourceController(ref meta.OwnerReference, namespace string, client cli
|
|||
type JobController batch.Job
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in JobController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsForJob(batch.Job(in), allPods)
|
||||
podInfo := common.GetPodInfo(in.Status.Active, in.Spec.Completions, matchingPods)
|
||||
func (self JobController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsForJob(batch.Job(self), allPods)
|
||||
podInfo := common.GetPodInfo(self.Status.Active, self.Spec.Completions, matchingPods)
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindJob),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in JobController) UID() apimachinery.UID {
|
||||
return batch.Job(in).UID
|
||||
func (self JobController) UID() apimachinery.UID {
|
||||
return batch.Job(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in JobController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsForJob(batch.Job(in), allPods)
|
||||
func (self JobController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsForJob(batch.Job(self), allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
type PodController v1.Pod
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
podInfo := common.GetPodInfo(int32(len(matchingPods)), nil, matchingPods) // Pods should not desire any Pods
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindPod),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetNonduplicateContainerImages(matchingPods),
|
||||
InitContainerImages: common.GetNonduplicateInitContainerImages(matchingPods),
|
||||
|
@ -159,13 +159,13 @@ func (in PodController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwne
|
|||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in PodController) UID() apimachinery.UID {
|
||||
return v1.Pod(in).UID
|
||||
func (self PodController) UID() apimachinery.UID {
|
||||
return v1.Pod(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetNonduplicateContainerNames(controlledPods),
|
||||
|
@ -178,32 +178,32 @@ func (in PodController) GetLogSources(allPods []v1.Pod) LogSources {
|
|||
type ReplicaSetController apps.ReplicaSet
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in ReplicaSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||
func (self ReplicaSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicaSet),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in ReplicaSetController) UID() apimachinery.UID {
|
||||
return apps.ReplicaSet(in).UID
|
||||
func (self ReplicaSetController) UID() apimachinery.UID {
|
||||
return apps.ReplicaSet(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,33 +212,33 @@ func (in ReplicaSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
|||
type ReplicationControllerController v1.ReplicationController
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in ReplicationControllerController) Get(allPods []v1.Pod,
|
||||
func (self ReplicationControllerController) Get(allPods []v1.Pod,
|
||||
allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindReplicationController),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in ReplicationControllerController) UID() apimachinery.UID {
|
||||
return v1.ReplicationController(in).UID
|
||||
func (self ReplicationControllerController) UID() apimachinery.UID {
|
||||
return v1.ReplicationController(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,33 +247,33 @@ func (in ReplicationControllerController) GetLogSources(allPods []v1.Pod) LogSou
|
|||
type DaemonSetController apps.DaemonSet
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in DaemonSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
podInfo := common.GetPodInfo(in.Status.CurrentNumberScheduled,
|
||||
&in.Status.DesiredNumberScheduled, matchingPods)
|
||||
func (self DaemonSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
podInfo := common.GetPodInfo(self.Status.CurrentNumberScheduled,
|
||||
&self.Status.DesiredNumberScheduled, matchingPods)
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindDaemonSet),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in DaemonSetController) UID() apimachinery.UID {
|
||||
return apps.DaemonSet(in).UID
|
||||
func (self DaemonSetController) UID() apimachinery.UID {
|
||||
return apps.DaemonSet(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,32 +282,32 @@ func (in DaemonSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
|||
type StatefulSetController apps.StatefulSet
|
||||
|
||||
// Get is an implementation of Get method from ResourceController interface.
|
||||
func (in StatefulSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
podInfo := common.GetPodInfo(in.Status.Replicas, in.Spec.Replicas, matchingPods)
|
||||
func (self StatefulSetController) Get(allPods []v1.Pod, allEvents []v1.Event) ResourceOwner {
|
||||
matchingPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
podInfo := common.GetPodInfo(self.Status.Replicas, self.Spec.Replicas, matchingPods)
|
||||
podInfo.Warnings = event.GetPodsEventWarnings(allEvents, matchingPods)
|
||||
|
||||
return ResourceOwner{
|
||||
TypeMeta: types.NewTypeMeta(types.ResourceKindStatefulSet),
|
||||
ObjectMeta: types.NewObjectMeta(in.ObjectMeta),
|
||||
ObjectMeta: types.NewObjectMeta(self.ObjectMeta),
|
||||
Pods: podInfo,
|
||||
ContainerImages: common.GetContainerImages(&in.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&in.Spec.Template.Spec),
|
||||
ContainerImages: common.GetContainerImages(&self.Spec.Template.Spec),
|
||||
InitContainerImages: common.GetInitContainerImages(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
// UID is an implementation of UID method from ResourceController interface.
|
||||
func (in StatefulSetController) UID() apimachinery.UID {
|
||||
return apps.StatefulSet(in).UID
|
||||
func (self StatefulSetController) UID() apimachinery.UID {
|
||||
return apps.StatefulSet(self).UID
|
||||
}
|
||||
|
||||
// GetLogSources is an implementation of the GetLogSources method from ResourceController interface.
|
||||
func (in StatefulSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&in, allPods)
|
||||
func (self StatefulSetController) GetLogSources(allPods []v1.Pod) LogSources {
|
||||
controlledPods := common.FilterPodsByControllerRef(&self, allPods)
|
||||
return LogSources{
|
||||
PodNames: getPodNames(controlledPods),
|
||||
ContainerNames: common.GetContainerNames(&in.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&in.Spec.Template.Spec),
|
||||
ContainerNames: common.GetContainerNames(&self.Spec.Template.Spec),
|
||||
InitContainerNames: common.GetInitContainerNames(&self.Spec.Template.Spec),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,26 +27,26 @@ import (
|
|||
|
||||
type CronJobCell batch.CronJob
|
||||
|
||||
func (in CronJobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self CronJobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (in CronJobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
func (self CronJobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
return &metricapi.ResourceSelector{
|
||||
Namespace: in.Namespace,
|
||||
Namespace: self.ObjectMeta.Namespace,
|
||||
ResourceType: types.ResourceKindCronJob,
|
||||
ResourceName: in.Name,
|
||||
UID: in.UID,
|
||||
ResourceName: self.ObjectMeta.Name,
|
||||
UID: self.UID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -114,11 +114,16 @@ func TriggerCronJob(client client.Interface,
|
|||
|
||||
jobToCreate := &batch.Job{
|
||||
ObjectMeta: meta.ObjectMeta{
|
||||
Name: newJobName,
|
||||
Namespace: namespace,
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
OwnerReferences: []meta.OwnerReference{*meta.NewControllerRef(cronJob, batch.SchemeGroupVersion.WithKind("CronJob"))},
|
||||
Name: newJobName,
|
||||
Namespace: namespace,
|
||||
Annotations: annotations,
|
||||
Labels: labels,
|
||||
OwnerReferences: []meta.OwnerReference{{
|
||||
APIVersion: CronJobAPIVersion,
|
||||
Kind: CronJobKindName,
|
||||
Name: cronJob.Name,
|
||||
UID: cronJob.UID,
|
||||
}},
|
||||
},
|
||||
Spec: cronJob.Spec.JobTemplate.Spec,
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
package cronjob
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
batch "k8s.io/api/batch/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -54,7 +55,7 @@ type CronJob struct {
|
|||
// GetCronJobList returns a list of all CronJobs in the cluster.
|
||||
func GetCronJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
||||
dsQuery *dataselect.DataSelectQuery) (*CronJobList, error) {
|
||||
klog.V(4).Infof("Getting list of all cron jobs in the cluster")
|
||||
log.Print("Getting list of all cron jobs in the cluster")
|
||||
|
||||
channels := &common.ResourceChannels{
|
||||
CronJobList: common.GetCronJobListChannel(client, nsQuery, 1),
|
||||
|
|
|
@ -48,6 +48,20 @@ func GetExtensionsAPIVersion(client apiextensionsclientset.Interface) (string, e
|
|||
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) {
|
||||
version, err := GetExtensionsAPIVersion(client)
|
||||
if err != nil {
|
||||
|
|
|
@ -82,7 +82,7 @@ func (r *CustomResourceObject) UnmarshalJSON(data []byte) error {
|
|||
return err
|
||||
}
|
||||
|
||||
r.TypeMeta = types.NewTypeMeta(types.ResourceKind(tempStruct.Kind))
|
||||
r.TypeMeta = types.NewTypeMeta(types.ResourceKind(tempStruct.TypeMeta.Kind))
|
||||
r.ObjectMeta = types.NewObjectMeta(tempStruct.ObjectMeta)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -25,12 +25,12 @@ import (
|
|||
|
||||
type CustomResourceDefinitionCell apiextensions.CustomResourceDefinition
|
||||
|
||||
func (in CustomResourceDefinitionCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self CustomResourceDefinitionCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
@ -58,14 +58,14 @@ func fromCells(cells []dataselect.DataCell) []apiextensions.CustomResourceDefini
|
|||
// The code below allows to perform complex data section on CustomResourceObject.
|
||||
type CustomResourceObjectCell types.CustomResourceObject
|
||||
|
||||
func (in CustomResourceObjectCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self CustomResourceObjectCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.ObjectMeta.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.ObjectMeta.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -67,26 +67,26 @@ func GetServicesForDSDeletion(client client.Interface, labelSelector labels.Sele
|
|||
|
||||
type DaemonSetCell apps.DaemonSet
|
||||
|
||||
func (in DaemonSetCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self DaemonSetCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (in DaemonSetCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
func (self DaemonSetCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
return &metricapi.ResourceSelector{
|
||||
Namespace: in.Namespace,
|
||||
Namespace: self.ObjectMeta.Namespace,
|
||||
ResourceType: types.ResourceKindDaemonSet,
|
||||
ResourceName: in.Name,
|
||||
UID: in.UID,
|
||||
ResourceName: self.ObjectMeta.Name,
|
||||
UID: self.UID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,10 @@ package daemonset
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
)
|
||||
|
@ -40,7 +39,7 @@ type DaemonSetDetail struct {
|
|||
func GetDaemonSetDetail(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||
namespace, name string) (*DaemonSetDetail, error) {
|
||||
|
||||
klog.V(4).Infof("Getting details of %s daemon set in %s namespace", name, namespace)
|
||||
log.Printf("Getting details of %s daemon set in %s namespace", name, namespace)
|
||||
daemonSet, err := client.AppsV1().DaemonSets(namespace).Get(context.TODO(), name, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -106,7 +106,7 @@ func TestGetDaemonSetListFromChannels(t *testing.T) {
|
|||
Labels: map[string]string{"key": "value"},
|
||||
CreationTimestamp: metaV1.Unix(111, 222),
|
||||
},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
||||
Pods: common.PodInfo{
|
||||
Current: 0,
|
||||
Failed: 0,
|
||||
|
@ -351,7 +351,7 @@ func TestToDaemonSetList(t *testing.T) {
|
|||
Namespace: "namespace-1",
|
||||
UID: "uid-1",
|
||||
},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
||||
ContainerImages: []string{"my-container-image-1"},
|
||||
InitContainerImages: []string{"my-init-container-image-1"},
|
||||
Pods: common.PodInfo{
|
||||
|
@ -367,7 +367,7 @@ func TestToDaemonSetList(t *testing.T) {
|
|||
Name: "my-app-2",
|
||||
Namespace: "namespace-2",
|
||||
},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
||||
ContainerImages: []string{"my-container-image-2"},
|
||||
InitContainerImages: []string{"my-init-container-image-2"},
|
||||
Pods: common.PodInfo{
|
||||
|
@ -379,7 +379,7 @@ func TestToDaemonSetList(t *testing.T) {
|
|||
Name: "my-app-3",
|
||||
Namespace: "namespace-3",
|
||||
},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet, Restartable: true},
|
||||
TypeMeta: types.TypeMeta{Kind: types.ResourceKindDaemonSet},
|
||||
ContainerImages: []string{"my-container-image-3"},
|
||||
InitContainerImages: []string{"my-init-container-image-3"},
|
||||
Pods: common.PodInfo{
|
||||
|
|
|
@ -16,12 +16,11 @@ package daemonset
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -33,7 +32,7 @@ import (
|
|||
// GetDaemonSetPods return list of pods targeting daemon set.
|
||||
func GetDaemonSetPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||
dsQuery *dataselect.DataSelectQuery, daemonSetName, namespace string) (*pod.PodList, error) {
|
||||
klog.V(4).Infof("Getting replication controller %s pods in namespace %s", daemonSetName, namespace)
|
||||
log.Printf("Getting replication controller %s pods in namespace %s", daemonSetName, namespace)
|
||||
|
||||
pods, err := getRawDaemonSetPods(client, daemonSetName, namespace)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,43 +0,0 @@
|
|||
// 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,7 +19,6 @@ import (
|
|||
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/args"
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/errors"
|
||||
)
|
||||
|
@ -44,9 +43,9 @@ type MetricDataCell interface {
|
|||
|
||||
// ComparableValue hold any value that can be compared to its own kind.
|
||||
type ComparableValue interface {
|
||||
// Compares in with other value. Returns 1 if other value is smaller, 0 if they are the same, -1 if other is larger.
|
||||
// Compares self with other value. Returns 1 if other value is smaller, 0 if they are the same, -1 if other is larger.
|
||||
Compare(ComparableValue) int
|
||||
// Returns true if in value contains or is equal to other value, false otherwise.
|
||||
// Returns true if self value contains or is equal to other value, false otherwise.
|
||||
Contains(ComparableValue) bool
|
||||
}
|
||||
|
||||
|
@ -72,18 +71,18 @@ type DataSelector struct {
|
|||
// 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.
|
||||
func (in DataSelector) Len() int { return len(in.GenericDataList) }
|
||||
func (self DataSelector) Len() int { return len(self.GenericDataList) }
|
||||
|
||||
// Swap swaps 2 indices inside SelectableData.
|
||||
func (in DataSelector) Swap(i, j int) {
|
||||
in.GenericDataList[i], in.GenericDataList[j] = in.GenericDataList[j], in.GenericDataList[i]
|
||||
func (self DataSelector) Swap(i, j int) {
|
||||
self.GenericDataList[i], self.GenericDataList[j] = self.GenericDataList[j], self.GenericDataList[i]
|
||||
}
|
||||
|
||||
// Less compares 2 indices inside SelectableData and returns true if first index is larger.
|
||||
func (in DataSelector) Less(i, j int) bool {
|
||||
for _, sortBy := range in.DataSelectQuery.SortQuery.SortByList {
|
||||
a := in.GenericDataList[i].GetProperty(sortBy.Property)
|
||||
b := in.GenericDataList[j].GetProperty(sortBy.Property)
|
||||
func (self DataSelector) Less(i, j int) bool {
|
||||
for _, sortBy := range self.DataSelectQuery.SortQuery.SortByList {
|
||||
a := self.GenericDataList[i].GetProperty(sortBy.Property)
|
||||
b := self.GenericDataList[j].GetProperty(sortBy.Property)
|
||||
// ignore sort completely if property name not found
|
||||
if a == nil || b == nil {
|
||||
break
|
||||
|
@ -98,19 +97,19 @@ func (in DataSelector) Less(i, j int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// Sort sorts the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||
func (in *DataSelector) Sort() *DataSelector {
|
||||
sort.Sort(*in)
|
||||
return in
|
||||
// Sort sorts the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
||||
func (self *DataSelector) Sort() *DataSelector {
|
||||
sort.Sort(*self)
|
||||
return self
|
||||
}
|
||||
|
||||
// Filter the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||
func (in *DataSelector) Filter() *DataSelector {
|
||||
// Filter the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
||||
func (self *DataSelector) Filter() *DataSelector {
|
||||
filteredList := []DataCell{}
|
||||
|
||||
for _, c := range in.GenericDataList {
|
||||
for _, c := range self.GenericDataList {
|
||||
matches := true
|
||||
for _, filterBy := range in.DataSelectQuery.FilterQuery.FilterByList {
|
||||
for _, filterBy := range self.DataSelectQuery.FilterQuery.FilterByList {
|
||||
v := c.GetProperty(filterBy.Property)
|
||||
if v == nil || !v.Contains(filterBy.Value) {
|
||||
matches = false
|
||||
|
@ -122,11 +121,11 @@ func (in *DataSelector) Filter() *DataSelector {
|
|||
}
|
||||
}
|
||||
|
||||
in.GenericDataList = filteredList
|
||||
return in
|
||||
self.GenericDataList = filteredList
|
||||
return self
|
||||
}
|
||||
|
||||
func (in *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
||||
func (self *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
||||
[]metricapi.MetricPromises, error) {
|
||||
metricPromises := make([]metricapi.MetricPromises, 0)
|
||||
|
||||
|
@ -134,13 +133,13 @@ func (in *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
|||
return metricPromises, nil
|
||||
}
|
||||
|
||||
metricNames := in.DataSelectQuery.MetricQuery.MetricNames
|
||||
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
|
||||
if metricNames == nil {
|
||||
return metricPromises, errors.NewInternal("No metrics specified. Skipping metrics.")
|
||||
}
|
||||
|
||||
selectors := make([]metricapi.ResourceSelector, len(in.GenericDataList))
|
||||
for i, dataCell := range in.GenericDataList {
|
||||
selectors := make([]metricapi.ResourceSelector, len(self.GenericDataList))
|
||||
for i, dataCell := range self.GenericDataList {
|
||||
// make sure data cells support metrics
|
||||
metricDataCell, ok := dataCell.(MetricDataCell)
|
||||
if !ok {
|
||||
|
@ -152,24 +151,24 @@ func (in *DataSelector) getMetrics(metricClient metricapi.MetricClient) (
|
|||
}
|
||||
|
||||
for _, metricName := range metricNames {
|
||||
promises := metricClient.DownloadMetric(selectors, metricName, in.CachedResources)
|
||||
promises := metricClient.DownloadMetric(selectors, metricName, self.CachedResources)
|
||||
metricPromises = append(metricPromises, promises)
|
||||
}
|
||||
|
||||
return metricPromises, nil
|
||||
}
|
||||
|
||||
// GetMetrics downloads metrics for data cells currently present in in.GenericDataList as instructed
|
||||
// by MetricQuery and inserts resulting MetricPromises to in.MetricsPromises.
|
||||
func (in *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||
metricPromisesList, err := in.getMetrics(metricClient)
|
||||
// GetMetrics downloads metrics for data cells currently present in self.GenericDataList as instructed
|
||||
// by MetricQuery and inserts resulting MetricPromises to self.MetricsPromises.
|
||||
func (self *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||
metricPromisesList, err := self.getMetrics(metricClient)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "error during getting metrics")
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
if len(metricPromisesList) == 0 {
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
metricPromises := make(metricapi.MetricPromises, 0)
|
||||
|
@ -177,30 +176,30 @@ func (in *DataSelector) GetMetrics(metricClient metricapi.MetricClient) *DataSel
|
|||
metricPromises = append(metricPromises, promises...)
|
||||
}
|
||||
|
||||
in.MetricsPromises = metricPromises
|
||||
return in
|
||||
self.MetricsPromises = metricPromises
|
||||
return self
|
||||
}
|
||||
|
||||
// GetCumulativeMetrics downloads and aggregates metrics for data cells currently present in in.GenericDataList as instructed
|
||||
// by MetricQuery and inserts resulting MetricPromises to in.CumulativeMetricsPromises.
|
||||
func (in *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||
metricPromisesList, err := in.getMetrics(metricClient)
|
||||
// GetCumulativeMetrics downloads and aggregates metrics for data cells currently present in self.GenericDataList as instructed
|
||||
// by MetricQuery and inserts resulting MetricPromises to self.CumulativeMetricsPromises.
|
||||
func (self *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient) *DataSelector {
|
||||
metricPromisesList, err := self.getMetrics(metricClient)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "error during getting metrics")
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
if len(metricPromisesList) == 0 {
|
||||
return in
|
||||
return self
|
||||
}
|
||||
|
||||
metricNames := in.DataSelectQuery.MetricQuery.MetricNames
|
||||
metricNames := self.DataSelectQuery.MetricQuery.MetricNames
|
||||
if metricNames == nil {
|
||||
klog.V(args.LogLevelVerbose).Info("Metrics names not provided. Skipping.")
|
||||
return in
|
||||
klog.V(1).Info("Metrics names not provided. Skipping.")
|
||||
return self
|
||||
}
|
||||
|
||||
aggregations := in.DataSelectQuery.MetricQuery.Aggregations
|
||||
aggregations := self.DataSelectQuery.MetricQuery.Aggregations
|
||||
if aggregations == nil {
|
||||
aggregations = metricapi.OnlyDefaultAggregation
|
||||
}
|
||||
|
@ -211,28 +210,28 @@ func (in *DataSelector) GetCumulativeMetrics(metricClient metricapi.MetricClient
|
|||
metricPromises = append(metricPromises, promises...)
|
||||
}
|
||||
|
||||
in.CumulativeMetricsPromises = metricPromises
|
||||
return in
|
||||
self.CumulativeMetricsPromises = metricPromises
|
||||
return self
|
||||
}
|
||||
|
||||
// Paginates the data inside as instructed by DataSelectQuery and returns itin to allow method chaining.
|
||||
func (in *DataSelector) Paginate() *DataSelector {
|
||||
pQuery := in.DataSelectQuery.PaginationQuery
|
||||
dataList := in.GenericDataList
|
||||
// Paginates the data inside as instructed by DataSelectQuery and returns itself to allow method chaining.
|
||||
func (self *DataSelector) Paginate() *DataSelector {
|
||||
pQuery := self.DataSelectQuery.PaginationQuery
|
||||
dataList := self.GenericDataList
|
||||
startIndex, endIndex := pQuery.GetPaginationSettings(len(dataList))
|
||||
|
||||
// Return all items if provided settings do not meet requirements
|
||||
if !pQuery.IsValidPagination() {
|
||||
return in
|
||||
return self
|
||||
}
|
||||
// Return no items if requested page does not exist
|
||||
if !pQuery.IsPageAvailable(len(in.GenericDataList), startIndex) {
|
||||
in.GenericDataList = []DataCell{}
|
||||
return in
|
||||
if !pQuery.IsPageAvailable(len(self.GenericDataList), startIndex) {
|
||||
self.GenericDataList = []DataCell{}
|
||||
return self
|
||||
}
|
||||
|
||||
in.GenericDataList = dataList[startIndex:endIndex]
|
||||
return in
|
||||
self.GenericDataList = dataList[startIndex:endIndex]
|
||||
return self
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func (in TestDataCell) GetProperty(name PropertyName) ComparableValue {
|
||||
func (self TestDataCell) GetProperty(name PropertyName) ComparableValue {
|
||||
switch name {
|
||||
case NameProperty:
|
||||
return StdComparableString(in.Name)
|
||||
return StdComparableString(self.Name)
|
||||
case CreationTimestampProperty:
|
||||
return StdComparableInt(in.Id)
|
||||
return StdComparableInt(self.Id)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -119,12 +119,11 @@ func NewSortQuery(sortByListRaw []string) *SortQuery {
|
|||
// parse order option
|
||||
var ascending bool
|
||||
orderOption := sortByListRaw[i]
|
||||
switch orderOption {
|
||||
case "a":
|
||||
if orderOption == "a" {
|
||||
ascending = true
|
||||
case "d":
|
||||
} else if orderOption == "d" {
|
||||
ascending = false
|
||||
default:
|
||||
} else {
|
||||
// Invalid order option. Only ascending (a), descending (d) options are supported
|
||||
return NoSort
|
||||
}
|
||||
|
|
|
@ -23,60 +23,60 @@ import (
|
|||
// These types specify how given value should be compared
|
||||
// They all implement ComparableValueInterface
|
||||
// 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 yourin :)
|
||||
// If you can't find your type compare here you will have to implement it yourself :)
|
||||
|
||||
type StdComparableInt int
|
||||
|
||||
func (in StdComparableInt) Compare(otherV ComparableValue) int {
|
||||
func (self StdComparableInt) Compare(otherV ComparableValue) int {
|
||||
other := otherV.(StdComparableInt)
|
||||
return intsCompare(int(in), int(other))
|
||||
return intsCompare(int(self), int(other))
|
||||
}
|
||||
|
||||
func (in StdComparableInt) Contains(otherV ComparableValue) bool {
|
||||
return in.Compare(otherV) == 0
|
||||
func (self StdComparableInt) Contains(otherV ComparableValue) bool {
|
||||
return self.Compare(otherV) == 0
|
||||
}
|
||||
|
||||
type StdComparableString string
|
||||
|
||||
func (in StdComparableString) Compare(otherV ComparableValue) int {
|
||||
func (self StdComparableString) Compare(otherV ComparableValue) int {
|
||||
other := otherV.(StdComparableString)
|
||||
return strings.Compare(string(in), string(other))
|
||||
return strings.Compare(string(self), string(other))
|
||||
}
|
||||
|
||||
func (in StdComparableString) Contains(otherV ComparableValue) bool {
|
||||
func (self StdComparableString) Contains(otherV ComparableValue) bool {
|
||||
other := otherV.(StdComparableString)
|
||||
return strings.Contains(string(in), string(other))
|
||||
return strings.Contains(string(self), string(other))
|
||||
}
|
||||
|
||||
// StdComparableRFC3339Timestamp takes RFC3339 Timestamp strings and compares them as TIMES. In case of time parsing error compares values as strings.
|
||||
type StdComparableRFC3339Timestamp string
|
||||
|
||||
func (in StdComparableRFC3339Timestamp) Compare(otherV ComparableValue) int {
|
||||
func (self StdComparableRFC3339Timestamp) Compare(otherV ComparableValue) int {
|
||||
other := otherV.(StdComparableRFC3339Timestamp)
|
||||
// try to compare as timestamp (earlier = smaller)
|
||||
inTime, err1 := time.Parse(time.RFC3339, string(in))
|
||||
selfTime, err1 := time.Parse(time.RFC3339, string(self))
|
||||
otherTime, err2 := time.Parse(time.RFC3339, string(other))
|
||||
|
||||
if err1 != nil || err2 != nil {
|
||||
// in case of timestamp parsing failure just compare as strings
|
||||
return strings.Compare(string(in), string(other))
|
||||
return strings.Compare(string(self), string(other))
|
||||
}
|
||||
return ints64Compare(inTime.Unix(), otherTime.Unix())
|
||||
return ints64Compare(selfTime.Unix(), otherTime.Unix())
|
||||
}
|
||||
|
||||
func (in StdComparableRFC3339Timestamp) Contains(otherV ComparableValue) bool {
|
||||
return in.Compare(otherV) == 0
|
||||
func (self StdComparableRFC3339Timestamp) Contains(otherV ComparableValue) bool {
|
||||
return self.Compare(otherV) == 0
|
||||
}
|
||||
|
||||
type StdComparableTime time.Time
|
||||
|
||||
func (in StdComparableTime) Compare(otherV ComparableValue) int {
|
||||
func (self StdComparableTime) Compare(otherV ComparableValue) int {
|
||||
other := otherV.(StdComparableTime)
|
||||
return ints64Compare(time.Time(in).Unix(), time.Time(other).Unix())
|
||||
return ints64Compare(time.Time(self).Unix(), time.Time(other).Unix())
|
||||
}
|
||||
|
||||
func (in StdComparableTime) Contains(otherV ComparableValue) bool {
|
||||
return in.Compare(otherV) == 0
|
||||
func (self StdComparableTime) Contains(otherV ComparableValue) bool {
|
||||
return self.Compare(otherV) == 0
|
||||
}
|
||||
|
||||
// Int comparison functions. Similar to strings.Compare.
|
||||
|
|
|
@ -30,27 +30,27 @@ import (
|
|||
type DeploymentCell apps.Deployment
|
||||
|
||||
// GetProperty is used to get property of the deployment
|
||||
func (in DeploymentCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self DeploymentCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (in DeploymentCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
func (self DeploymentCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
return &metricapi.ResourceSelector{
|
||||
Namespace: in.Namespace,
|
||||
Namespace: self.ObjectMeta.Namespace,
|
||||
ResourceType: types.ResourceKindDeployment,
|
||||
ResourceName: in.Name,
|
||||
Selector: in.Spec.Selector.MatchLabels,
|
||||
UID: in.UID,
|
||||
ResourceName: self.ObjectMeta.Name,
|
||||
Selector: self.Spec.Selector.MatchLabels,
|
||||
UID: self.UID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
apps "k8s.io/api/apps/v1"
|
||||
|
@ -34,9 +35,7 @@ import (
|
|||
"k8s.io/client-go/dynamic"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/args"
|
||||
derrors "k8s.io/dashboard/errors"
|
||||
)
|
||||
|
||||
|
@ -162,7 +161,7 @@ type Protocols struct {
|
|||
// client. App deployment consists of a deployment and an optional service. Both of them
|
||||
// share common labels.
|
||||
func DeployApp(spec *AppDeploymentSpec, client client.Interface) error {
|
||||
klog.V(args.LogLevelVerbose).Infof("Deploying %s application into %s namespace", spec.Name, spec.Namespace)
|
||||
log.Printf("Deploying %s application into %s namespace", spec.Name, spec.Namespace)
|
||||
|
||||
annotations := map[string]string{}
|
||||
if spec.Description != nil {
|
||||
|
@ -305,7 +304,7 @@ func getLabelsMap(labels []Label) map[string]string {
|
|||
// DeployAppFromFile deploys an app based on the given yaml or json file.
|
||||
func DeployAppFromFile(cfg *rest.Config, spec *AppDeploymentFromFileSpec) (bool, error) {
|
||||
reader := strings.NewReader(spec.Content)
|
||||
klog.V(args.LogLevelVerbose).Infof("Namespace for deploy from file: %s\n", spec.Namespace)
|
||||
log.Printf("Namespace for deploy from file: %s\n", spec.Namespace)
|
||||
d := yaml.NewYAMLOrJSONDecoder(reader, 4096)
|
||||
for {
|
||||
data := &unstructured.Unstructured{}
|
||||
|
|
|
@ -16,13 +16,12 @@ package deployment
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
apps "k8s.io/api/apps/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/errors"
|
||||
)
|
||||
|
@ -83,7 +82,7 @@ type DeploymentDetail struct {
|
|||
// GetDeploymentDetail returns model object of deployment and error, if any.
|
||||
func GetDeploymentDetail(client client.Interface, namespace string, deploymentName string) (*DeploymentDetail, error) {
|
||||
|
||||
klog.V(4).Infof("Getting details of %s deployment in %s namespace", deploymentName, namespace)
|
||||
log.Printf("Getting details of %s deployment in %s namespace", deploymentName, namespace)
|
||||
|
||||
deployment, err := client.AppsV1().Deployments(namespace).Get(context.TODO(), deploymentName, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
package deployment
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
apps "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
|
@ -63,7 +64,7 @@ type Deployment struct {
|
|||
// GetDeploymentList returns a list of all Deployments in the cluster.
|
||||
func GetDeploymentList(client client.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery,
|
||||
metricClient metricapi.MetricClient) (*DeploymentList, error) {
|
||||
klog.V(4).Infof("Getting list of all deployments in the cluster")
|
||||
log.Print("Getting list of all deployments in the cluster")
|
||||
|
||||
channels := &common.ResourceChannels{
|
||||
DeploymentList: common.GetDeploymentListChannel(client, nsQuery, 1),
|
||||
|
|
|
@ -47,7 +47,7 @@ func RollbackDeployment(client client.Interface, rolloutSpec *RolloutSpec, names
|
|||
}
|
||||
currRevision := deployment.Annotations[RevisionAnnotationKey]
|
||||
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)
|
||||
if err != nil {
|
||||
|
@ -66,7 +66,7 @@ func RollbackDeployment(client client.Interface, rolloutSpec *RolloutSpec, names
|
|||
}, 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
|
||||
|
@ -83,7 +83,7 @@ func PauseDeployment(client client.Interface, namespace, name string) (*v1.Deplo
|
|||
}
|
||||
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
|
||||
|
@ -100,7 +100,7 @@ func ResumeDeployment(client client.Interface, namespace, name string) (*v1.Depl
|
|||
}
|
||||
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`.
|
||||
|
@ -110,10 +110,10 @@ func RestartDeployment(client client.Interface, namespace, name string) (*Rollou
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if deployment.Spec.Template.Annotations == nil {
|
||||
deployment.Spec.Template.Annotations = map[string]string{}
|
||||
if deployment.Spec.Template.ObjectMeta.Annotations == nil {
|
||||
deployment.Spec.Template.ObjectMeta.Annotations = map[string]string{}
|
||||
}
|
||||
deployment.Spec.Template.Annotations[RestartedAtAnnotationKey] = time.Now().Format(time.RFC3339)
|
||||
deployment.Spec.Template.ObjectMeta.Annotations[RestartedAtAnnotationKey] = time.Now().Format(time.RFC3339)
|
||||
res, err := client.AppsV1().Deployments(namespace).Update(context.TODO(), deployment, metaV1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
package endpoint
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
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/types"
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ func GetServiceEndpoints(client k8sClient.Interface, namespace, name string) (*E
|
|||
}
|
||||
|
||||
endpointList = toEndpointList(serviceEndpoints)
|
||||
klog.V(args.LogLevelVerbose).Infof("Found %d endpoints related to %s service in %s namespace", len(endpointList.Endpoints), name, namespace)
|
||||
log.Printf("Found %d endpoints related to %s service in %s namespace", len(endpointList.Endpoints), name, namespace)
|
||||
return endpointList, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -244,20 +244,20 @@ func CreateEventList(events []v1.Event, dsQuery *dataselect.DataSelectQuery) com
|
|||
|
||||
type EventCell v1.Event
|
||||
|
||||
func (in EventCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self EventCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.FirstSeenProperty:
|
||||
return dataselect.StdComparableTime(in.FirstTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.FirstTimestamp.Time)
|
||||
case dataselect.LastSeenProperty:
|
||||
return dataselect.StdComparableTime(in.LastTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.LastTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
case dataselect.ReasonProperty:
|
||||
return dataselect.StdComparableString(in.Reason)
|
||||
return dataselect.StdComparableString(self.Reason)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
package event
|
||||
|
||||
import (
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
"log"
|
||||
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
"k8s.io/dashboard/errors"
|
||||
|
@ -25,7 +25,7 @@ import (
|
|||
|
||||
func GetEventList(client k8sClient.Interface, nsQuery *common.NamespaceQuery,
|
||||
dsQuery *dataselect.DataSelectQuery) (*common.EventList, error) {
|
||||
klog.V(4).Infof("Getting list of events in namespace: %s", nsQuery.ToRequestParam())
|
||||
log.Printf("Getting list of events in namespace: %s", nsQuery.ToRequestParam())
|
||||
|
||||
channels := &common.ResourceChannels{
|
||||
EventList: common.GetEventListChannel(client, nsQuery, 2),
|
||||
|
|
|
@ -29,14 +29,14 @@ type ScaleTargetRef struct {
|
|||
|
||||
type HorizontalPodAutoscalerCell autoscaling.HorizontalPodAutoscaler
|
||||
|
||||
func (in HorizontalPodAutoscalerCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self HorizontalPodAutoscalerCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -16,11 +16,11 @@ package horizontalpodautoscaler
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
autoscaling "k8s.io/api/autoscaling/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// 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
|
||||
func GetHorizontalPodAutoscalerDetail(client client.Interface, namespace string, name string) (*HorizontalPodAutoscalerDetail, error) {
|
||||
klog.V(4).Infof("Getting details of %s horizontal pod autoscaler", name)
|
||||
log.Printf("Getting details of %s horizontal pod autoscaler", name)
|
||||
|
||||
rawHorizontalPodAutoscaler, err := client.AutoscalingV1().HorizontalPodAutoscalers(namespace).Get(context.TODO(), name, v1.GetOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
|
||||
type IngressCell v1.Ingress
|
||||
|
||||
func (in IngressCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self IngressCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -16,11 +16,11 @@ package ingress
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/networking/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// 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
|
||||
func GetIngressDetail(client client.Interface, namespace, name string) (*IngressDetail, error) {
|
||||
klog.V(4).Infof("Getting details of %s ingress in %s namespace", name, namespace)
|
||||
log.Printf("Getting details of %s ingress in %s namespace", name, namespace)
|
||||
|
||||
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 {
|
||||
if rule.HTTP == nil {
|
||||
if rule.IngressRuleValue.HTTP == nil {
|
||||
continue
|
||||
}
|
||||
for _, path := range rule.HTTP.Paths {
|
||||
for _, path := range rule.IngressRuleValue.HTTP.Paths {
|
||||
if ingressBackendMatchesServiceName(&path.Backend, serviceName) {
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
|
||||
type IngressClassCell networkingv1.IngressClass
|
||||
|
||||
func (in IngressClassCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self IngressClassCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -16,11 +16,11 @@ package ingressclass
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// IngressClassDetail provides the presentation layer view of Ingress Class resource.
|
||||
|
@ -32,7 +32,7 @@ type IngressClassDetail struct {
|
|||
|
||||
// GetIngressClass returns Storage Class resource.
|
||||
func GetIngressClass(client kubernetes.Interface, name string) (*IngressClassDetail, error) {
|
||||
klog.V(4).Infof("Getting details of %s ingress class", name)
|
||||
log.Printf("Getting details of %s ingress class", name)
|
||||
|
||||
ic, err := client.NetworkingV1().IngressClasses().Get(context.TODO(), name, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -15,9 +15,10 @@
|
|||
package ingressclass
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
networkingv1 "k8s.io/api/networking/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -44,7 +45,7 @@ type IngressClass struct {
|
|||
// GetIngressClassList returns a list of all Ingress class objects in the cluster.
|
||||
func GetIngressClassList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (
|
||||
*IngressClassList, error) {
|
||||
klog.V(4).Infof("Getting list of ingress classes in the cluster")
|
||||
log.Print("Getting list of ingress classes in the cluster")
|
||||
|
||||
channels := &common.ResourceChannels{
|
||||
IngressClassList: common.GetIngressClassListChannel(client, 1),
|
||||
|
|
|
@ -28,26 +28,26 @@ import (
|
|||
|
||||
type JobCell batch.Job
|
||||
|
||||
func (in JobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self JobCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (in JobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
func (self JobCell) GetResourceSelector() *metricapi.ResourceSelector {
|
||||
return &metricapi.ResourceSelector{
|
||||
Namespace: in.Namespace,
|
||||
Namespace: self.ObjectMeta.Namespace,
|
||||
ResourceType: types.ResourceKindJob,
|
||||
ResourceName: in.Name,
|
||||
UID: in.UID,
|
||||
ResourceName: self.ObjectMeta.Name,
|
||||
UID: self.UID,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
package job
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
batch "k8s.io/api/batch/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
client "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
|
@ -88,7 +89,7 @@ type Job struct {
|
|||
// GetJobList returns a list of all Jobs in the cluster.
|
||||
func GetJobList(client client.Interface, nsQuery *common.NamespaceQuery,
|
||||
dsQuery *dataselect.DataSelectQuery, metricClient metricapi.MetricClient) (*JobList, error) {
|
||||
klog.V(4).Infof("Getting list of all jobs in the cluster")
|
||||
log.Print("Getting list of all jobs in the cluster")
|
||||
|
||||
channels := &common.ResourceChannels{
|
||||
JobList: common.GetJobListChannel(client, nsQuery, 1),
|
||||
|
|
|
@ -16,6 +16,7 @@ package job
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
batch "k8s.io/api/batch/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
|
@ -23,8 +24,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
metricapi "k8s.io/dashboard/api/pkg/integration/metric/api"
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
|
@ -36,7 +35,7 @@ import (
|
|||
// GetJobPods return list of pods targeting job.
|
||||
func GetJobPods(client k8sClient.Interface, metricClient metricapi.MetricClient,
|
||||
dsQuery *dataselect.DataSelectQuery, namespace string, jobName string) (*pod.PodList, error) {
|
||||
klog.V(4).Infof("Getting replication controller %s pods in namespace %s", jobName, namespace)
|
||||
log.Printf("Getting replication controller %s pods in namespace %s", jobName, namespace)
|
||||
|
||||
pods, err := getRawJobPods(client, jobName, namespace)
|
||||
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
|
||||
// of returned lines and the information of the resulting logView.
|
||||
func (in LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp, LogTimestamp, Selection, bool) {
|
||||
func (self LogLines) SelectLogs(logSelection *Selection) (LogLines, LogTimestamp, LogTimestamp, Selection, bool) {
|
||||
requestedNumItems := logSelection.OffsetTo - logSelection.OffsetFrom
|
||||
referenceLineIndex := in.getLineIndex(&logSelection.ReferencePoint)
|
||||
if referenceLineIndex == LineIndexNotFound || requestedNumItems <= 0 || len(in) == 0 {
|
||||
referenceLineIndex := self.getLineIndex(&logSelection.ReferencePoint)
|
||||
if referenceLineIndex == LineIndexNotFound || requestedNumItems <= 0 || len(self) == 0 {
|
||||
// Requested reference line could not be found, probably it's already gone or requested no logs. Return no logs.
|
||||
return LogLines{}, "", "", Selection{}, false
|
||||
}
|
||||
fromIndex := referenceLineIndex + logSelection.OffsetFrom
|
||||
toIndex := referenceLineIndex + logSelection.OffsetTo
|
||||
lastPage := false
|
||||
if requestedNumItems > len(in) {
|
||||
if requestedNumItems > len(self) {
|
||||
fromIndex = 0
|
||||
toIndex = len(in)
|
||||
toIndex = len(self)
|
||||
lastPage = true
|
||||
} else if toIndex > len(in) {
|
||||
fromIndex -= toIndex - len(in)
|
||||
toIndex = len(in)
|
||||
} else if toIndex > len(self) {
|
||||
fromIndex -= toIndex - len(self)
|
||||
toIndex = len(self)
|
||||
lastPage = logSelection.LogFilePosition == Beginning
|
||||
} else if fromIndex < 0 {
|
||||
toIndex += -fromIndex
|
||||
|
@ -177,32 +177,32 @@ func (in 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.
|
||||
newSelection := Selection{
|
||||
ReferencePoint: *in.createLogLineId(len(in) / 2),
|
||||
OffsetFrom: fromIndex - len(in)/2,
|
||||
OffsetTo: toIndex - len(in)/2,
|
||||
ReferencePoint: *self.createLogLineId(len(self) / 2),
|
||||
OffsetFrom: fromIndex - len(self)/2,
|
||||
OffsetTo: toIndex - len(self)/2,
|
||||
LogFilePosition: logSelection.LogFilePosition,
|
||||
}
|
||||
return in[fromIndex:toIndex], in[fromIndex].Timestamp, in[toIndex-1].Timestamp, newSelection, lastPage
|
||||
return self[fromIndex:toIndex], self[fromIndex].Timestamp, self[toIndex-1].Timestamp, newSelection, lastPage
|
||||
}
|
||||
|
||||
// getLineIndex returns the index of the line (referenced from beginning of log array) with provided logLineId.
|
||||
func (in LogLines) getLineIndex(logLineId *LogLineId) int {
|
||||
if logLineId == nil || logLineId.LogTimestamp == NewestTimestamp || len(in) == 0 || logLineId.LogTimestamp == "" {
|
||||
func (self LogLines) getLineIndex(logLineId *LogLineId) int {
|
||||
if logLineId == nil || logLineId.LogTimestamp == NewestTimestamp || len(self) == 0 || logLineId.LogTimestamp == "" {
|
||||
// if no line id provided return index of last item.
|
||||
return len(in) - 1
|
||||
return len(self) - 1
|
||||
} else if logLineId.LogTimestamp == OldestTimestamp {
|
||||
return 0
|
||||
}
|
||||
logTimestamp := logLineId.LogTimestamp
|
||||
|
||||
matchingStartedAt := 0
|
||||
matchingStartedAt = sort.Search(len(in), func(i int) bool {
|
||||
return in[i].Timestamp >= logTimestamp
|
||||
matchingStartedAt = sort.Search(len(self), func(i int) bool {
|
||||
return self[i].Timestamp >= logTimestamp
|
||||
})
|
||||
|
||||
linesMatched := 0
|
||||
if matchingStartedAt < len(in) && in[matchingStartedAt].Timestamp == logTimestamp { // match found
|
||||
for (matchingStartedAt+linesMatched) < len(in) && in[matchingStartedAt+linesMatched].Timestamp == logTimestamp {
|
||||
if matchingStartedAt < len(self) && self[matchingStartedAt].Timestamp == logTimestamp { // match found
|
||||
for (matchingStartedAt+linesMatched) < len(self) && self[matchingStartedAt+linesMatched].Timestamp == logTimestamp {
|
||||
linesMatched += 1
|
||||
}
|
||||
}
|
||||
|
@ -220,22 +220,22 @@ func (in LogLines) getLineIndex(logLineId *LogLineId) int {
|
|||
}
|
||||
|
||||
// createLogLineId returns ID of the line with provided lineIndex.
|
||||
func (in LogLines) createLogLineId(lineIndex int) *LogLineId {
|
||||
logTimestamp := in[lineIndex].Timestamp
|
||||
func (self LogLines) createLogLineId(lineIndex int) *LogLineId {
|
||||
logTimestamp := self[lineIndex].Timestamp
|
||||
// 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
|
||||
// as more lines may appear at the end.
|
||||
// negative referencing is preferred as higher indices disappear later.
|
||||
var step int
|
||||
if in[len(in)-1].Timestamp == logTimestamp {
|
||||
if self[len(self)-1].Timestamp == logTimestamp {
|
||||
// use positive referencing
|
||||
step = 1
|
||||
} else {
|
||||
step = -1
|
||||
}
|
||||
offset := step
|
||||
for ; 0 <= lineIndex-offset && lineIndex-offset < len(in); offset += step {
|
||||
if in[lineIndex-offset].Timestamp != logTimestamp {
|
||||
for ; 0 <= lineIndex-offset && lineIndex-offset < len(self); offset += step {
|
||||
if self[lineIndex-offset].Timestamp != logTimestamp {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,11 @@ package namespace
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
api "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/args"
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
)
|
||||
|
||||
|
@ -34,7 +32,7 @@ type NamespaceSpec struct {
|
|||
|
||||
// CreateNamespace creates namespace based on given specification.
|
||||
func CreateNamespace(spec *NamespaceSpec, client kubernetes.Interface) error {
|
||||
klog.V(args.LogLevelVerbose).Infof("Creating namespace %s", spec.Name)
|
||||
log.Printf("Creating namespace %s", spec.Name)
|
||||
|
||||
namespace := &api.Namespace{
|
||||
ObjectMeta: metaV1.ObjectMeta{
|
||||
|
@ -50,14 +48,14 @@ func CreateNamespace(spec *NamespaceSpec, client kubernetes.Interface) error {
|
|||
|
||||
type NamespaceCell api.Namespace
|
||||
|
||||
func (in NamespaceCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self NamespaceCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// if name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
|
@ -16,11 +16,11 @@ package namespace
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8sClient "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/limitrange"
|
||||
rq "k8s.io/dashboard/api/pkg/resource/resourcequota"
|
||||
|
@ -47,7 +47,7 @@ type NamespaceDetail struct {
|
|||
|
||||
// GetNamespaceDetail gets namespace details.
|
||||
func GetNamespaceDetail(client k8sClient.Interface, name string) (*NamespaceDetail, error) {
|
||||
klog.V(4).Infof("Getting details of %s namespace\n", name)
|
||||
log.Printf("Getting details of %s namespace\n", name)
|
||||
|
||||
namespace, err := client.CoreV1().Namespaces().Get(context.TODO(), name, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
|
|
|
@ -16,10 +16,10 @@ package namespace
|
|||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/common"
|
||||
"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.
|
||||
func GetNamespaceList(client kubernetes.Interface, dsQuery *dataselect.DataSelectQuery) (*NamespaceList, error) {
|
||||
klog.V(4).Info("Getting list of namespaces")
|
||||
log.Println("Getting list of namespaces")
|
||||
namespaces, err := client.CoreV1().Namespaces().List(context.TODO(), helpers.ListEverything)
|
||||
|
||||
nonCriticalErrors, criticalError := errors.ExtractErrors(err)
|
||||
|
|
|
@ -16,20 +16,19 @@ package networkpolicy
|
|||
|
||||
import (
|
||||
v1 "k8s.io/api/networking/v1"
|
||||
|
||||
"k8s.io/dashboard/api/pkg/resource/dataselect"
|
||||
)
|
||||
|
||||
type ServiceAccountCell v1.NetworkPolicy
|
||||
|
||||
func (in ServiceAccountCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
func (self ServiceAccountCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue {
|
||||
switch name {
|
||||
case dataselect.NameProperty:
|
||||
return dataselect.StdComparableString(in.Name)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Name)
|
||||
case dataselect.CreationTimestampProperty:
|
||||
return dataselect.StdComparableTime(in.CreationTimestamp.Time)
|
||||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time)
|
||||
case dataselect.NamespaceProperty:
|
||||
return dataselect.StdComparableString(in.Namespace)
|
||||
return dataselect.StdComparableString(self.ObjectMeta.Namespace)
|
||||
default:
|
||||
// If name is not supported then just return a constant dummy value, sort will have no effect.
|
||||
return nil
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue