mirror of
https://github.com/replicatedhq/troubleshoot.git
synced 2026-08-27 00:37:20 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4623d9404 | ||
|
|
bc4856869e | ||
|
|
f6373f3e36 | ||
|
|
7038da85b1 | ||
|
|
a7bb9ea31e | ||
|
|
08c3fcf3df | ||
|
|
1d2c1191e2 | ||
|
|
66e070a07d | ||
|
|
7528c57e83 | ||
|
|
42fc4f06de | ||
|
|
312e467160 | ||
|
|
5e280d0652 | ||
|
|
15cfdb9eee | ||
|
|
15a4802cd2 | ||
|
|
0d4d305ae6 | ||
|
|
de7112fed2 | ||
|
|
73a2d882d7 | ||
|
|
461cc994ef | ||
|
|
1bdf87e8cd | ||
|
|
32b0e1a890 | ||
|
|
cc56522571 | ||
|
|
e3adc1cb35 | ||
|
|
359475ba87 | ||
|
|
f3d49c657f | ||
|
|
7f3808b8d7 | ||
|
|
f44d077756 | ||
|
|
e34742f3cc | ||
|
|
fd29012624 | ||
|
|
be5e66cbca | ||
|
|
c079d96efe | ||
|
|
7b797b3725 | ||
|
|
6cbe188abe | ||
|
|
86279b4ec4 | ||
|
|
514c86d891 | ||
|
|
b9f4fc4390 | ||
|
|
53813502de | ||
|
|
597fb2996b | ||
|
|
e44aff4100 | ||
|
|
d0d6f00c0f | ||
|
|
4460e8c639 | ||
|
|
c166d46af4 | ||
|
|
ded1f42b5a | ||
|
|
32176178a8 | ||
|
|
949b645336 | ||
|
|
1f50fe3163 | ||
|
|
24c6278e5d | ||
|
|
8d527ead8c | ||
|
|
1dedbcd67a | ||
|
|
ff03bfa9cd | ||
|
|
b7d5a9876c | ||
|
|
96c482a1f5 | ||
|
|
543931631b | ||
|
|
d730be0fae | ||
|
|
38ff340883 | ||
|
|
04f69b3f8c | ||
|
|
57b988b100 | ||
|
|
6972789bea | ||
|
|
17cbc16e05 | ||
|
|
87404982fe | ||
|
|
5bb4358f7a | ||
|
|
39314ef200 | ||
|
|
73c7dba0e1 | ||
|
|
a8f8bf9257 | ||
|
|
08c37c7333 | ||
|
|
8f20b665f9 | ||
|
|
638d99eaad | ||
|
|
25ddcf4388 | ||
|
|
31ccbf696c | ||
|
|
a068561af4 | ||
|
|
f3777bef69 | ||
|
|
addc2ce925 | ||
|
|
247c60afd2 | ||
|
|
8237ac991c | ||
|
|
73201c0304 | ||
|
|
531edf42e2 | ||
|
|
f69ae77bc3 | ||
|
|
b02d12ff1e | ||
|
|
24822b7f95 |
@@ -1,4 +0,0 @@
|
||||
version: 3
|
||||
|
||||
project:
|
||||
id: github.com/replicatedhq/troubleshoot
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
|
||||
- name: setup env
|
||||
run: |
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: make test
|
||||
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
|
||||
- name: setup env
|
||||
run: |
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: replicatedhq/action-k3s@main
|
||||
id: k3s
|
||||
with:
|
||||
@@ -68,13 +68,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
- name: setup env
|
||||
run: |
|
||||
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: make check-schemas
|
||||
@@ -84,13 +84,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
- name: setup env
|
||||
run: |
|
||||
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: make generate preflight
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: compile-preflight
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: replicatedhq/action-k3s@main
|
||||
id: k3s
|
||||
with:
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
run-examples:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: make run-examples
|
||||
|
||||
compile-supportbundle:
|
||||
@@ -173,13 +173,13 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
- name: setup env
|
||||
run: |
|
||||
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- run: make generate support-bundle
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: compile-supportbundle
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: replicatedhq/action-k3s@main
|
||||
id: k3s
|
||||
with:
|
||||
@@ -209,7 +209,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
needs: compile-supportbundle
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- uses: replicatedhq/action-k3s@main
|
||||
id: k3s
|
||||
with:
|
||||
@@ -222,18 +222,39 @@ jobs:
|
||||
- run: chmod +x bin/support-bundle
|
||||
- run: make support-bundle-e2e-test
|
||||
|
||||
compile-collect:
|
||||
validate-supportbundle-e2e-go-test:
|
||||
runs-on: ubuntu-latest
|
||||
needs: compile-supportbundle
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
- name: setup env
|
||||
run: |
|
||||
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Download support bundle binary
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: support-bundle
|
||||
path: bin/
|
||||
- run: chmod +x bin/support-bundle
|
||||
- run: make support-bundle-e2e-go-test
|
||||
|
||||
compile-collect:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.20"
|
||||
- name: setup env
|
||||
run: |
|
||||
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
|
||||
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
|
||||
shell: bash
|
||||
- uses: actions/checkout@v4
|
||||
- run: make generate collect
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
@@ -250,18 +271,20 @@ jobs:
|
||||
include:
|
||||
- goarch: arm
|
||||
goos: linux
|
||||
- goarch: riscv64
|
||||
goos: linux
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
uses: goreleaser/goreleaser-action@v5
|
||||
with:
|
||||
version: "v0.183.0"
|
||||
args: build --rm-dist --snapshot --config deploy/.goreleaser.yaml --single-target
|
||||
@@ -278,7 +301,7 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
@@ -289,7 +312,7 @@ jobs:
|
||||
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.19"
|
||||
go-version: "1.20"
|
||||
|
||||
- uses: sigstore/cosign-installer@v3
|
||||
with:
|
||||
@@ -310,7 +333,7 @@ jobs:
|
||||
COSIGN_KEY: ${{ secrets.COSIGN_KEY }}
|
||||
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v4
|
||||
uses: goreleaser/goreleaser-action@v5
|
||||
with:
|
||||
version: "v1.x" # Binary version to install
|
||||
args: release --rm-dist --config deploy/.goreleaser.yaml
|
||||
|
||||
@@ -10,7 +10,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run Trivy vulnerability scanner in repo mode
|
||||
uses: aquasecurity/trivy-action@master
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
name: FOSSA license scan
|
||||
|
||||
on:
|
||||
pull_request_target: # this is safe as these scans do not execute provided code
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- go.sum
|
||||
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
fossa-scan-pr:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: refs/pull/${{ github.event.number }}/merge
|
||||
- name: "Install FOSSA"
|
||||
uses: replicatedhq/action-fossa/install@main
|
||||
- name: "Run FOSSA Scan"
|
||||
uses: replicatedhq/action-fossa/scan@main
|
||||
with:
|
||||
api-key: ${{ secrets.FOSSA_API_KEY }}
|
||||
diff: true
|
||||
diff-ref: ${{ github.event.pull_request.base.sha }}
|
||||
debug: true
|
||||
|
||||
fossa-scan-merge:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- id: previous
|
||||
run: echo "sha=$(git rev-parse HEAD~1)" >> "${GITHUB_OUTPUT}"
|
||||
- name: "Install FOSSA"
|
||||
uses: replicatedhq/action-fossa/install@main
|
||||
- name: "Run FOSSA Scan"
|
||||
uses: replicatedhq/action-fossa/scan@main
|
||||
with:
|
||||
api-key: ${{ secrets.FOSSA_API_KEY }}
|
||||
diff: true
|
||||
diff-ref: ${{ steps.previous.outputs.sha }}
|
||||
debug: true
|
||||
@@ -0,0 +1,42 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
TRIVY_VERSION: 0.44.1
|
||||
|
||||
name: License scan
|
||||
|
||||
jobs:
|
||||
license:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
|
||||
- name: Install Go deps
|
||||
run: go mod download
|
||||
|
||||
- name: Install trivy
|
||||
run: |
|
||||
wget https://github.com/aquasecurity/trivy/releases/download/v${TRIVY_VERSION}/trivy_${TRIVY_VERSION}_Linux-64bit.deb
|
||||
sudo dpkg -i trivy_${TRIVY_VERSION}_Linux-64bit.deb
|
||||
|
||||
- name: Create license report artifact
|
||||
run: trivy fs --scanners license --skip-dirs ".github" . | tee license-report.txt
|
||||
|
||||
- name: Upload license report artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: license-report
|
||||
path: license-report.txt
|
||||
|
||||
- name: Check for unknown licenses
|
||||
run: trivy fs --scanners license --skip-dirs ".github" --exit-code 1 --severity UNKNOWN . || echo "::warning::Unknown licenses found, please verify"
|
||||
|
||||
- name: Check for forbidden licenses and fail
|
||||
run: trivy fs --scanners license --skip-dirs ".github" --exit-code 1 --severity CRITICAL,HIGH .
|
||||
@@ -7,7 +7,10 @@
|
||||
*.dylib
|
||||
bin
|
||||
.DS_Store
|
||||
|
||||
# npm generated files
|
||||
node_modules/
|
||||
package*.json
|
||||
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
+12
-1
@@ -21,7 +21,7 @@ When implementing a new feature please review the [design principles](./docs/des
|
||||
|
||||
To get started we recommend:
|
||||
|
||||
1. Go (v1.19 or later)
|
||||
1. Go (v1.20 or later)
|
||||
2. A Kubernetes cluster (we recommend <https://k3d.io/>. This requires Docker v20.10.5 or later)
|
||||
3. Fork and clone the repo to $GOPATH/src/github.com/replicatedhq/
|
||||
4. Run `make support-bundle preflight` to generate binaries
|
||||
@@ -32,6 +32,11 @@ To get started we recommend:
|
||||
|
||||
6. Install [golangci-lint] linter and run `make lint` to execute additional code linters.
|
||||
|
||||
### Build automatically on save with `watch`
|
||||
|
||||
1. Install `npm`
|
||||
2. Run `make watch` to build binaries automatically on saving. Note: you may still have to run `make schemas` if you've added API changes, like a new collector or analyzer type.
|
||||
|
||||
### Syncing to a test cluster with `watchrsync`
|
||||
|
||||
1. Install `npm`
|
||||
@@ -89,6 +94,12 @@ go tool pprof -http=":8000" cpu.prof
|
||||
go tool pprof -http=":8001" mem.prof
|
||||
```
|
||||
|
||||
**Additional flags for memory profiling**
|
||||
- `inuse_space`: Amount of memory allocated and not released yet (default).
|
||||
- `inuse_objects`: Amount of objects allocated and not released yet.
|
||||
- `alloc_space`: Total amount of memory allocated (regardless of released).
|
||||
- `alloc_objects`: Total amount of objects allocated (regardless of released).
|
||||
|
||||
More on profiling please visit https://go.dev/doc/diagnostics#profiling
|
||||
|
||||
## Contribution workflow
|
||||
|
||||
@@ -36,9 +36,11 @@ endef
|
||||
|
||||
BUILDFLAGS = -tags "netgo containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" -installsuffix netgo
|
||||
BUILDPATHS = ./pkg/... ./cmd/... ./internal/...
|
||||
E2EPATHS = ./test/e2e/...
|
||||
TESTFLAGS ?= -v -coverprofile cover.out
|
||||
|
||||
all: test support-bundle preflight collect analyze
|
||||
.DEFAULT: all
|
||||
all: test build
|
||||
|
||||
.PHONY: ffi
|
||||
ffi: fmt vet
|
||||
@@ -70,11 +72,22 @@ run-examples:
|
||||
support-bundle-e2e-test:
|
||||
./test/validate-support-bundle-e2e.sh
|
||||
|
||||
.PHONY: support-bundle-e2e-go-test
|
||||
support-bundle-e2e-go-test:
|
||||
if [ -n $(RUN) ]; then \
|
||||
go test ${BUILDFLAGS} ${E2EPATHS} -v -run $(RUN); \
|
||||
else \
|
||||
go test ${BUILDFLAGS} ${E2EPATHS} -v; \
|
||||
fi
|
||||
|
||||
# Build all binaries in parallel ( -j )
|
||||
build:
|
||||
@echo "Build cli binaries"
|
||||
$(MAKE) -j support-bundle preflight analyze collect
|
||||
|
||||
mod-tidy:
|
||||
go mod tidy
|
||||
|
||||
.PHONY: support-bundle
|
||||
support-bundle:
|
||||
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
|
||||
@@ -141,7 +154,7 @@ CONTROLLER_GEN=$(shell which controller-gen)
|
||||
.PHONY: client-gen
|
||||
client-gen:
|
||||
ifeq (, $(shell which client-gen 2>/dev/null))
|
||||
go install k8s.io/code-generator/cmd/client-gen@v0.26.1
|
||||
go install k8s.io/code-generator/cmd/client-gen@v0.28.2
|
||||
CLIENT_GEN=$(shell go env GOPATH)/bin/client-gen
|
||||
else
|
||||
CLIENT_GEN=$(shell which client-gen)
|
||||
@@ -230,6 +243,10 @@ lint: fmt vet
|
||||
lint-and-fix: fmt vet
|
||||
golangci-lint run --new --fix -c .golangci.yaml ${BUILDPATHS}
|
||||
|
||||
.PHONY: watch
|
||||
watch: npm-install
|
||||
bin/watch.js
|
||||
|
||||
## Syncronize the code with a remote server. More info: CONTRIBUTING.md
|
||||
.PHONY: watchrsync
|
||||
watchrsync: npm-install
|
||||
@@ -238,4 +255,4 @@ watchrsync: npm-install
|
||||
.PHONY: npm-install
|
||||
npm-install:
|
||||
npm --version 2>&1 >/dev/null || ( echo "npm not installed; install npm to set up watchrsync" && exit 1 )
|
||||
npm list gaze-run-interrupt || npm install install gaze-run-interrupt@~2.0.0
|
||||
npm list gaze-run-interrupt || npm install install --no-save gaze-run-interrupt@~2.0.0
|
||||
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const gri = require('gaze-run-interrupt');
|
||||
|
||||
const commands = [
|
||||
// {
|
||||
// command: 'rm',
|
||||
// args: binList,
|
||||
// },
|
||||
{
|
||||
command: 'make',
|
||||
args: ['build'],
|
||||
},
|
||||
];
|
||||
|
||||
commands.push({
|
||||
command: "date",
|
||||
args: [],
|
||||
});
|
||||
|
||||
commands.push({
|
||||
command: "echo",
|
||||
args: ["synced"],
|
||||
});
|
||||
|
||||
gri([
|
||||
'cmd/**/*.go',
|
||||
'pkg/**/*.go',
|
||||
], commands);
|
||||
+1
-7
@@ -16,12 +16,6 @@ const binList = [
|
||||
'bin/support-bundle',
|
||||
// 'bin/collect'
|
||||
]
|
||||
const makeList = [
|
||||
// 'analyze',
|
||||
// 'preflight',
|
||||
'support-bundle',
|
||||
// 'collect'
|
||||
]
|
||||
|
||||
const commands = [
|
||||
// {
|
||||
@@ -30,7 +24,7 @@ const commands = [
|
||||
// },
|
||||
{
|
||||
command: 'make',
|
||||
args: makeList,
|
||||
args: ['build'],
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/cmd/util"
|
||||
"github.com/replicatedhq/troubleshoot/cmd/internal/util"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -43,6 +43,8 @@ func RootCmd() *cobra.Command {
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
cmd.AddCommand(util.VersionCmd())
|
||||
|
||||
cmd.Flags().String("analyzers", "", "filename or url of the analyzers to use")
|
||||
cmd.Flags().Bool("debug", false, "enable debug logging")
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ func runAnalyzers(v *viper.Viper, bundlePath string) error {
|
||||
specContent := ""
|
||||
var err error
|
||||
if _, err = os.Stat(specPath); err == nil {
|
||||
b, err := ioutil.ReadFile(specPath)
|
||||
b, err := os.ReadFile(specPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -26,6 +26,7 @@ func runAnalyzers(v *viper.Viper, bundlePath string) error {
|
||||
specContent = string(b)
|
||||
} else {
|
||||
if !util.IsURL(specPath) {
|
||||
// TODO: Better error message when we do not have a file/url etc
|
||||
return fmt.Errorf("%s is not a URL and was not found (err %s)", specPath, err)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/cmd/util"
|
||||
"github.com/replicatedhq/troubleshoot/cmd/internal/util"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/logger"
|
||||
"github.com/spf13/cobra"
|
||||
@@ -43,7 +43,7 @@ func RootCmd() *cobra.Command {
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
cmd.AddCommand(VersionCmd())
|
||||
cmd.AddCommand(util.VersionCmd())
|
||||
|
||||
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
|
||||
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
|
||||
|
||||
@@ -50,7 +50,7 @@ func runCollect(v *viper.Viper, arg string) error {
|
||||
|
||||
collectorContent = spec
|
||||
} else if _, err = os.Stat(arg); err == nil {
|
||||
b, err := ioutil.ReadFile(arg)
|
||||
b, err := os.ReadFile(arg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func VersionCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the current version and exit",
|
||||
Long: `Print the current version and exit`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf("Replicated Collect %s\n", version.Version())
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package cli
|
||||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -2,9 +2,12 @@ package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/logger"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/oci"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func OciFetchCmd() *cobra.Command {
|
||||
@@ -12,6 +15,13 @@ func OciFetchCmd() *cobra.Command {
|
||||
Use: "oci-fetch [URI]",
|
||||
Args: cobra.MinimumNArgs(1),
|
||||
Short: "Fetch a preflight from an OCI registry and print it to standard out",
|
||||
PreRun: func(cmd *cobra.Command, args []string) {
|
||||
v := viper.GetViper()
|
||||
v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
v.BindPFlags(cmd.Flags())
|
||||
|
||||
logger.SetupLogger(v)
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
uri := args[0]
|
||||
data, err := oci.PullPreflightFromOCI(uri)
|
||||
@@ -22,5 +32,9 @@ func OciFetchCmd() *cobra.Command {
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
// Initialize klog flags
|
||||
logger.InitKlogFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/cmd/util"
|
||||
"github.com/replicatedhq/troubleshoot/cmd/internal/util"
|
||||
"github.com/replicatedhq/troubleshoot/internal/traces"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/constants"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
@@ -49,7 +49,7 @@ that a cluster meets the requirements to run an application.`,
|
||||
}
|
||||
|
||||
err = preflight.RunPreflights(v.GetBool("interactive"), v.GetString("output"), v.GetString("format"), args)
|
||||
if v.GetBool("debug") || v.IsSet("v") {
|
||||
if !v.GetBool("dry-run") && (v.GetBool("debug") || v.IsSet("v")) {
|
||||
fmt.Printf("\n%s", traces.GetExporterInstance().GetSummary())
|
||||
}
|
||||
|
||||
@@ -64,10 +64,14 @@ that a cluster meets the requirements to run an application.`,
|
||||
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
cmd.AddCommand(VersionCmd())
|
||||
cmd.AddCommand(util.VersionCmd())
|
||||
cmd.AddCommand(OciFetchCmd())
|
||||
preflight.AddFlags(cmd.PersistentFlags())
|
||||
|
||||
// Dry run flag should be in cmd.PersistentFlags() flags made available to all subcommands
|
||||
// Adding here to avoid that
|
||||
cmd.Flags().Bool("dry-run", false, "print the preflight spec without running preflight checks")
|
||||
|
||||
k8sutil.AddFlags(cmd.Flags())
|
||||
|
||||
// Initialize klog flags
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/version"
|
||||
)
|
||||
|
||||
func VersionCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the current version and exit",
|
||||
Long: `Print the current version and exit`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf("Replicated Preflight %s\n", version.Version())
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/cmd/util"
|
||||
"github.com/replicatedhq/troubleshoot/cmd/internal/util"
|
||||
"github.com/replicatedhq/troubleshoot/internal/traces"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/logger"
|
||||
@@ -45,7 +45,7 @@ from a server that can be used to assist when troubleshooting a Kubernetes clust
|
||||
}
|
||||
|
||||
err = runTroubleshoot(v, args)
|
||||
if v.GetBool("debug") || v.IsSet("v") {
|
||||
if !v.IsSet("dry-run") && (v.GetBool("debug") || v.IsSet("v")) {
|
||||
fmt.Printf("\n%s", traces.GetExporterInstance().GetSummary())
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ from a server that can be used to assist when troubleshooting a Kubernetes clust
|
||||
|
||||
cmd.AddCommand(Analyze())
|
||||
cmd.AddCommand(Redact())
|
||||
cmd.AddCommand(VersionCmd())
|
||||
cmd.AddCommand(util.VersionCmd())
|
||||
|
||||
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
|
||||
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
|
||||
@@ -74,6 +74,7 @@ from a server that can be used to assist when troubleshooting a Kubernetes clust
|
||||
cmd.Flags().String("since", "", "force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.")
|
||||
cmd.Flags().StringP("output", "o", "", "specify the output file path for the support bundle")
|
||||
cmd.Flags().Bool("debug", false, "enable debug logging. This is equivalent to --v=0")
|
||||
cmd.Flags().Bool("dry-run", false, "print support bundle spec without collecting anything")
|
||||
|
||||
// hidden in favor of the `insecure-skip-tls-verify` flag
|
||||
cmd.Flags().Bool("allow-insecure-connections", false, "when set, do not verify TLS certs when retrieving spec and reporting results")
|
||||
@@ -81,7 +82,7 @@ from a server that can be used to assist when troubleshooting a Kubernetes clust
|
||||
|
||||
// `no-uri` references the `followURI` functionality where we can use an upstream spec when creating a support bundle
|
||||
// This flag makes sure we can also disable this and fall back to the default spec.
|
||||
cmd.Flags().Bool("no-uri", false, "When this flag is used, Troubleshoot does not attempt to retrieve the bundle referenced by the uri: field in the spec.`")
|
||||
cmd.Flags().Bool("no-uri", false, "When this flag is used, Troubleshoot does not attempt to retrieve the spec referenced by the uri: field`")
|
||||
|
||||
k8sutil.AddFlags(cmd.Flags())
|
||||
|
||||
|
||||
+130
-222
@@ -9,8 +9,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -18,29 +16,65 @@ import (
|
||||
"github.com/fatih/color"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/replicatedhq/troubleshoot/internal/specs"
|
||||
"github.com/replicatedhq/troubleshoot/internal/util"
|
||||
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/constants"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/convert"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/httputil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/specs"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/loader"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/supportbundle"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/types"
|
||||
"github.com/spf13/viper"
|
||||
spin "github.com/tj/go-spin"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
func runTroubleshoot(v *viper.Viper, arg []string) error {
|
||||
if !v.GetBool("load-cluster-specs") && len(arg) < 1 {
|
||||
func runTroubleshoot(v *viper.Viper, args []string) error {
|
||||
ctx := context.Background()
|
||||
if !v.GetBool("load-cluster-specs") && len(args) < 1 {
|
||||
return errors.New("flag load-cluster-specs must be set if no specs are provided on the command line")
|
||||
}
|
||||
|
||||
restConfig, err := k8sutil.GetRESTConfig()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to convert kube flags to rest config")
|
||||
}
|
||||
|
||||
client, err := kubernetes.NewForConfig(restConfig)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create kubernetes client")
|
||||
}
|
||||
|
||||
mainBundle, additionalRedactors, err := loadSpecs(ctx, args, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// For --dry-run, we want to print the yaml and exit
|
||||
if v.GetBool("dry-run") {
|
||||
k := loader.TroubleshootKinds{
|
||||
SupportBundlesV1Beta2: []troubleshootv1beta2.SupportBundle{*mainBundle},
|
||||
}
|
||||
// If we have redactors, add them to the temp kinds object
|
||||
if len(additionalRedactors.Spec.Redactors) > 0 {
|
||||
k.RedactorsV1Beta2 = []troubleshootv1beta2.Redactor{*additionalRedactors}
|
||||
}
|
||||
|
||||
out, err := k.ToYaml()
|
||||
if err != nil {
|
||||
return types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, errors.Wrap(err, "failed to convert specs to yaml"))
|
||||
}
|
||||
fmt.Printf("%s", out)
|
||||
return nil
|
||||
}
|
||||
|
||||
interactive := v.GetBool("interactive") && isatty.IsTerminal(os.Stdout.Fd())
|
||||
|
||||
if interactive {
|
||||
@@ -58,11 +92,6 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
|
||||
os.Exit(0)
|
||||
}()
|
||||
|
||||
restConfig, err := k8sutil.GetRESTConfig()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to convert kube flags to rest config")
|
||||
}
|
||||
|
||||
var sinceTime *time.Time
|
||||
if v.GetString("since-time") != "" || v.GetString("since") != "" {
|
||||
sinceTime, err = parseTimeFlags(v)
|
||||
@@ -77,61 +106,6 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
|
||||
})
|
||||
}
|
||||
|
||||
var mainBundle *troubleshootv1beta2.SupportBundle
|
||||
|
||||
additionalRedactors := &troubleshootv1beta2.Redactor{}
|
||||
|
||||
// Defining `v` below will render using `v` in reference to Viper unusable.
|
||||
// Therefore refactoring `v` to `val` will make sure we can still use it.
|
||||
for _, val := range arg {
|
||||
|
||||
collectorContent, err := supportbundle.LoadSupportBundleSpec(val)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load support bundle spec")
|
||||
}
|
||||
multidocs := strings.Split(string(collectorContent), "\n---\n")
|
||||
// Referencing `ParseSupportBundle with a secondary arg of `no-uri`
|
||||
// Will make sure we can enable or disable the use of the `Spec.uri` field for an upstream spec.
|
||||
// This change will not have an impact on KOTS' usage of `ParseSupportBundle`
|
||||
// As Kots uses `load.go` directly.
|
||||
supportBundle, err := supportbundle.ParseSupportBundle([]byte(multidocs[0]), !v.GetBool("no-uri"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse support bundle spec")
|
||||
}
|
||||
|
||||
mainBundle = supportbundle.ConcatSpec(mainBundle, supportBundle)
|
||||
|
||||
parsedRedactors, err := supportbundle.ParseRedactorsFromDocs(multidocs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse redactors from doc")
|
||||
}
|
||||
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, parsedRedactors...)
|
||||
}
|
||||
|
||||
if v.GetBool("load-cluster-specs") {
|
||||
sbFromCluster, redactorsFromCluster, err := loadClusterSpecs()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if sbFromCluster == nil {
|
||||
return errors.New("no specs found in cluster")
|
||||
}
|
||||
mainBundle = supportbundle.ConcatSpec(mainBundle, sbFromCluster)
|
||||
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorsFromCluster.Spec.Redactors...)
|
||||
}
|
||||
|
||||
if mainBundle == nil {
|
||||
return errors.New("no support bundle specs provided to run")
|
||||
} else if mainBundle.Spec.Collectors == nil && mainBundle.Spec.HostCollectors == nil {
|
||||
return errors.New("no collectors specified in support bundle")
|
||||
}
|
||||
|
||||
redactors, err := supportbundle.GetRedactorsFromURIs(v.GetStringSlice("redactors"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get redactors")
|
||||
}
|
||||
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactors...)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
collectorCB := func(c chan interface{}, msg string) { c <- msg }
|
||||
progressChan := make(chan interface{})
|
||||
@@ -258,178 +232,112 @@ the %s Admin Console to begin analysis.`
|
||||
return nil
|
||||
}
|
||||
|
||||
// loadClusterSpecs loads the support bundle and redactor specs from the cluster
|
||||
// based on the provided labels. By default this will be troubleshoot.io/kind=support-bundle and troubleshoot.sh/kind=support-bundle label selectors. We search for secrets
|
||||
// and configmaps with the label selector and parse the data as a support bundle. If the
|
||||
// user does not have sufficient permissions to list & read secrets and configmaps from
|
||||
// all namespaces, we will fallback to trying each namespace individually, and eventually
|
||||
// default to the configured kubeconfig namespace.
|
||||
func loadClusterSpecs() (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) {
|
||||
redactors := &troubleshootv1beta2.Redactor{}
|
||||
|
||||
v := viper.GetViper() // It's singleton, so we can use it anywhere
|
||||
|
||||
klog.Info("Discover troubleshoot specs from cluster")
|
||||
|
||||
selectors := v.GetStringSlice("selector")
|
||||
if reflect.DeepEqual(selectors, []string{"troubleshoot.sh/kind=support-bundle"}) {
|
||||
// Its the default selector so we append troubleshoot.io/kind=support-bundle to it due to backwards compatibility
|
||||
selectors = append(selectors, "troubleshoot.io/kind=support-bundle")
|
||||
}
|
||||
|
||||
labelSelector := strings.Join(selectors, ",")
|
||||
|
||||
parsedSelector, err := labels.Parse(labelSelector)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "unable to parse selector")
|
||||
}
|
||||
|
||||
config, err := k8sutil.GetRESTConfig()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to convert kube flags to rest config")
|
||||
}
|
||||
|
||||
client, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to convert create k8s client")
|
||||
}
|
||||
|
||||
// List of namespaces we want to search for secrets and configmaps with support bundle specs
|
||||
namespaces := []string{}
|
||||
ctx := context.Background()
|
||||
|
||||
if v.GetString("namespace") != "" {
|
||||
// Just progress with the namespace provided
|
||||
namespaces = []string{v.GetString("namespace")}
|
||||
} else {
|
||||
// Check if I can read secrets and configmaps in all namespaces
|
||||
ican, err := k8sutil.CanIListAndGetAllSecretsAndConfigMaps(ctx, client)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to check if I can read secrets and configmaps")
|
||||
// loadSupportBundleSpecsFromURIs loads support bundle specs from URIs
|
||||
func loadSupportBundleSpecsFromURIs(ctx context.Context, kinds *loader.TroubleshootKinds) (*loader.TroubleshootKinds, error) {
|
||||
remoteRawSpecs := []string{}
|
||||
for _, s := range kinds.SupportBundlesV1Beta2 {
|
||||
if s.Spec.Uri != "" && util.IsURL(s.Spec.Uri) {
|
||||
// We are using LoadSupportBundleSpec function here since it handles prompting
|
||||
// users to accept insecure connections
|
||||
// There is an opportunity to refactor this code in favour of the Loader APIs
|
||||
// TODO: Pass ctx to LoadSupportBundleSpec
|
||||
rawSpec, err := supportbundle.LoadSupportBundleSpec(s.Spec.Uri)
|
||||
if err != nil {
|
||||
// In the event a spec can't be loaded, we'll just skip it and print a warning
|
||||
klog.Warningf("unable to load support bundle from URI: %q: %v", s.Spec.Uri, err)
|
||||
continue
|
||||
}
|
||||
remoteRawSpecs = append(remoteRawSpecs, string(rawSpec))
|
||||
}
|
||||
klog.V(1).Infof("Can I read any secrets and configmaps: %v", ican)
|
||||
}
|
||||
|
||||
if ican {
|
||||
// I can read secrets and configmaps in all namespaces
|
||||
// No need to iterate over all namespaces
|
||||
namespaces = []string{""}
|
||||
if len(remoteRawSpecs) == 0 {
|
||||
return kinds, nil
|
||||
}
|
||||
|
||||
return loader.LoadSpecs(ctx, loader.LoadOptions{
|
||||
RawSpecs: remoteRawSpecs,
|
||||
})
|
||||
}
|
||||
|
||||
func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface) (*troubleshootv1beta2.SupportBundle, *troubleshootv1beta2.Redactor, error) {
|
||||
// Append redactor uris to the args
|
||||
allArgs := append(args, viper.GetStringSlice("redactors")...)
|
||||
kinds, err := specs.LoadFromCLIArgs(ctx, client, allArgs, viper.GetViper())
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Load additional specs from support bundle URIs
|
||||
if !viper.GetBool("no-uri") {
|
||||
moreKinds, err := loadSupportBundleSpecsFromURIs(ctx, kinds)
|
||||
if err != nil {
|
||||
klog.Warningf("unable to load support bundles from URIs: %v", err)
|
||||
} else {
|
||||
// Get list of all namespaces and try to find specs from each namespace
|
||||
nsList, err := client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
if k8serrors.IsForbidden(err) {
|
||||
kubeconfig := k8sutil.GetKubeconfig()
|
||||
ns, _, err := kubeconfig.Namespace()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "failed to get namespace from kubeconfig")
|
||||
}
|
||||
// If we are not allowed to list namespaces, just use the default namespace
|
||||
// configured in the kubeconfig
|
||||
namespaces = []string{ns}
|
||||
} else {
|
||||
return nil, nil, errors.Wrap(err, "failed to list namespaces")
|
||||
}
|
||||
}
|
||||
|
||||
for _, ns := range nsList.Items {
|
||||
namespaces = append(namespaces, ns.Name)
|
||||
}
|
||||
kinds.Add(moreKinds)
|
||||
}
|
||||
}
|
||||
|
||||
var bundlesFromCluster []string
|
||||
|
||||
parsedSelectorStrings, err := specs.SplitTroubleshootSecretLabelSelector(client, parsedSelector)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to parse troubleshoot labels selector %s", err)
|
||||
// Check if we have any collectors to run in the troubleshoot specs
|
||||
// TODO: Do we use the RemoteCollectors anymore?
|
||||
if len(kinds.CollectorsV1Beta2) == 0 &&
|
||||
len(kinds.HostCollectorsV1Beta2) == 0 &&
|
||||
len(kinds.SupportBundlesV1Beta2) == 0 {
|
||||
return nil, nil, errors.New("no collectors specified to run")
|
||||
}
|
||||
|
||||
// Search cluster for support bundle specs
|
||||
for _, parsedSelectorString := range parsedSelectorStrings {
|
||||
klog.V(1).Infof("Search support bundle specs from [%q] namespace using %q selector", strings.Join(namespaces, ", "), parsedSelectorString)
|
||||
for _, ns := range namespaces {
|
||||
bundlesFromSecrets, err := specs.LoadFromSecretMatchingLabel(client, parsedSelectorString, ns, constants.SupportBundleKey)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from secrets: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading secrets from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
bundlesFromCluster = append(bundlesFromCluster, bundlesFromSecrets...)
|
||||
|
||||
bundlesFromConfigMaps, err := specs.LoadFromConfigMapMatchingLabel(client, parsedSelectorString, ns, constants.SupportBundleKey)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from configmap: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading configmaps from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
bundlesFromCluster = append(bundlesFromCluster, bundlesFromConfigMaps...)
|
||||
}
|
||||
// Merge specs
|
||||
// We need to add the default type information to the support bundle spec
|
||||
// since by default these fields would be empty
|
||||
mainBundle := &troubleshootv1beta2.SupportBundle{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "troubleshoot.sh/v1beta2",
|
||||
Kind: "SupportBundle",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "merged-support-bundle-spec",
|
||||
},
|
||||
}
|
||||
for _, sb := range kinds.SupportBundlesV1Beta2 {
|
||||
sb := sb
|
||||
mainBundle = supportbundle.ConcatSpec(mainBundle, &sb)
|
||||
}
|
||||
|
||||
parsedBundle := &troubleshootv1beta2.SupportBundle{}
|
||||
|
||||
for _, bundle := range bundlesFromCluster {
|
||||
multidocs := strings.Split(string(bundle), "\n---\n")
|
||||
bundleFromDoc, err := supportbundle.ParseSupportBundleFromDoc([]byte(multidocs[0]))
|
||||
if err != nil {
|
||||
klog.Errorf("failed to parse support bundle spec: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
parsedBundle = supportbundle.ConcatSpec(parsedBundle, bundleFromDoc)
|
||||
|
||||
parsedRedactors, err := supportbundle.ParseRedactorsFromDocs(multidocs)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to parse redactors from doc: %s", err)
|
||||
continue
|
||||
}
|
||||
|
||||
redactors.Spec.Redactors = append(redactors.Spec.Redactors, parsedRedactors...)
|
||||
for _, c := range kinds.CollectorsV1Beta2 {
|
||||
mainBundle.Spec.Collectors = append(mainBundle.Spec.Collectors, c.Spec.Collectors...)
|
||||
}
|
||||
|
||||
var redactorsFromCluster []string
|
||||
|
||||
// Search cluster for redactor specs
|
||||
for _, parsedSelectorString := range parsedSelectorStrings {
|
||||
klog.V(1).Infof("Search redactor specs from [%q] namespace using %q selector", strings.Join(namespaces, ", "), parsedSelectorString)
|
||||
for _, ns := range namespaces {
|
||||
redactorsFromSecrets, err := specs.LoadFromSecretMatchingLabel(client, parsedSelectorString, ns, constants.RedactorKey)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from secrets: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading secrets from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
redactorsFromCluster = append(redactorsFromCluster, redactorsFromSecrets...)
|
||||
|
||||
redactorsFromConfigMaps, err := specs.LoadFromConfigMapMatchingLabel(client, parsedSelectorString, ns, constants.RedactorKey)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from configmap: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading configmaps from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
redactorsFromCluster = append(redactorsFromCluster, redactorsFromConfigMaps...)
|
||||
}
|
||||
for _, hc := range kinds.HostCollectorsV1Beta2 {
|
||||
mainBundle.Spec.HostCollectors = append(mainBundle.Spec.HostCollectors, hc.Spec.Collectors...)
|
||||
}
|
||||
|
||||
for _, redactor := range redactorsFromCluster {
|
||||
multidocs := strings.Split(string(redactor), "\n---\n")
|
||||
parsedRedactors, err := supportbundle.ParseRedactorsFromDocs(multidocs)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to parse redactors from doc: %s", err)
|
||||
}
|
||||
// Ensure cluster info and cluster resources collectors are in the merged spec
|
||||
// We need to add them here so when we --dry-run, these collectors are included.
|
||||
// supportbundle.runCollectors duplicates this bit. We'll need to refactor it out later
|
||||
// when its clearer what other code depends on this logic e.g KOTS
|
||||
mainBundle.Spec.Collectors = collect.EnsureCollectorInList(
|
||||
mainBundle.Spec.Collectors,
|
||||
troubleshootv1beta2.Collect{ClusterInfo: &troubleshootv1beta2.ClusterInfo{}},
|
||||
)
|
||||
mainBundle.Spec.Collectors = collect.EnsureCollectorInList(
|
||||
mainBundle.Spec.Collectors,
|
||||
troubleshootv1beta2.Collect{ClusterResources: &troubleshootv1beta2.ClusterResources{}},
|
||||
)
|
||||
|
||||
redactors.Spec.Redactors = append(redactors.Spec.Redactors, parsedRedactors...)
|
||||
additionalRedactors := &troubleshootv1beta2.Redactor{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "troubleshoot.sh/v1beta2",
|
||||
Kind: "Redactor",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "merged-redactors-spec",
|
||||
},
|
||||
}
|
||||
for _, r := range kinds.RedactorsV1Beta2 {
|
||||
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, r.Spec.Redactors...)
|
||||
}
|
||||
|
||||
return parsedBundle, redactors, nil
|
||||
return mainBundle, additionalRedactors, nil
|
||||
}
|
||||
|
||||
func parseTimeFlags(v *viper.Viper) (*time.Time, error) {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/replicatedhq/troubleshoot/pkg/httputil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/loader"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var orig = `
|
||||
apiVersion: troubleshoot.sh/v1beta2
|
||||
kind: SupportBundle
|
||||
metadata:
|
||||
name: sb-1
|
||||
spec:
|
||||
uri: $MY_URI
|
||||
collectors:
|
||||
- configMap:
|
||||
name: kube-root-ca.crt
|
||||
namespace: default
|
||||
`
|
||||
|
||||
func Test_loadSupportBundleSpecsFromURIs(t *testing.T) {
|
||||
// Run a webserver to serve the spec
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write([]byte(`
|
||||
apiVersion: troubleshoot.sh/v1beta2
|
||||
kind: SupportBundle
|
||||
metadata:
|
||||
name: sb-2
|
||||
spec:
|
||||
collectors:
|
||||
- clusterInfo: {}`))
|
||||
}))
|
||||
defer srv.Close()
|
||||
|
||||
orig := strings.ReplaceAll(orig, "$MY_URI", srv.URL)
|
||||
|
||||
ctx := context.Background()
|
||||
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{RawSpec: orig})
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, kinds)
|
||||
|
||||
moreKinds, err := loadSupportBundleSpecsFromURIs(ctx, kinds)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Len(t, moreKinds.SupportBundlesV1Beta2, 1)
|
||||
assert.NotNil(t, moreKinds.SupportBundlesV1Beta2[0].Spec.Collectors[0].ClusterInfo)
|
||||
}
|
||||
|
||||
func Test_loadSupportBundleSpecsFromURIs_TimeoutError(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(2 * time.Second) // this will cause a timeout
|
||||
}))
|
||||
defer srv.Close()
|
||||
ctx := context.Background()
|
||||
|
||||
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
|
||||
RawSpec: strings.ReplaceAll(orig, "$MY_URI", srv.URL),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set the timeout on the http client to 10ms
|
||||
// supportbundle.LoadSupportBundleSpec does not yet use the context
|
||||
before := httputil.GetHttpClient().Timeout
|
||||
httputil.GetHttpClient().Timeout = 10 * time.Millisecond
|
||||
defer func() {
|
||||
// Reinstate the original timeout. Its a global var so we need to reset it
|
||||
httputil.GetHttpClient().Timeout = before
|
||||
}()
|
||||
|
||||
kindsAfter, err := loadSupportBundleSpecsFromURIs(ctx, kinds)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, kinds, kindsAfter)
|
||||
}
|
||||
@@ -163,6 +163,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -180,6 +187,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -195,6 +209,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -835,6 +835,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -852,6 +859,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -867,6 +881,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -866,6 +866,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -883,6 +890,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -898,6 +912,13 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: A Duration represents the elapsed time
|
||||
between two instants as an int64 nanosecond count.
|
||||
The representation limits the largest representable
|
||||
duration to approximately 290 years.
|
||||
format: int64
|
||||
type: integer
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -732,6 +732,8 @@ spec:
|
||||
type: BoolString
|
||||
fileName:
|
||||
type: string
|
||||
jsonPath:
|
||||
type: string
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
@@ -1487,6 +1489,19 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
velero:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
strict:
|
||||
type: BoolString
|
||||
type: object
|
||||
weaveReport:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -1669,6 +1684,55 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
cpu:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -2404,6 +2468,67 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
textAnalyze:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
excludeFiles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
fileName:
|
||||
type: string
|
||||
ignoreIfNoFiles:
|
||||
type: boolean
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
regex:
|
||||
type: string
|
||||
regexGroups:
|
||||
type: string
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
time:
|
||||
properties:
|
||||
annotations:
|
||||
|
||||
@@ -318,6 +318,17 @@ spec:
|
||||
- namespace
|
||||
- selector
|
||||
type: object
|
||||
helm:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
namespace:
|
||||
type: string
|
||||
releaseName:
|
||||
type: string
|
||||
type: object
|
||||
http:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -332,6 +343,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -349,6 +365,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -364,6 +385,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -2600,6 +2626,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -2739,8 +2790,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -2780,18 +2831,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -4110,6 +4156,13 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: Restart policy for the container
|
||||
to manage the restart behavior of each container
|
||||
within a pod. This may only be set for init
|
||||
containers. You cannot set this field on ephemeral
|
||||
containers.
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'Optional: SecurityContext defines
|
||||
the security options the ephemeral container
|
||||
@@ -4248,8 +4301,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -4289,18 +4342,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -5656,6 +5704,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -5795,8 +5868,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -5836,18 +5909,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -6309,17 +6377,10 @@ spec:
|
||||
template will be used to create a new ResourceClaim,
|
||||
which will be bound to this pod. When this
|
||||
pod is deleted, the ResourceClaim will also
|
||||
be deleted. The name of the ResourceClaim
|
||||
will be <pod name>-<resource name>, where
|
||||
<resource name> is the PodResourceClaim.Name.
|
||||
Pod validation will reject the pod if the
|
||||
concatenated name is not valid for a ResourceClaim
|
||||
(e.g. too long). \n An existing ResourceClaim
|
||||
with that name that is not owned by the
|
||||
pod will not be used for the pod to avoid
|
||||
using an unrelated resource by mistake.
|
||||
Scheduling and pod startup are then blocked
|
||||
until the unrelated ResourceClaim is removed.
|
||||
be deleted. The pod name and resource name,
|
||||
along with a generated component, will be
|
||||
used to form a unique name for the ResourceClaim,
|
||||
which will be recorded in pod.status.resourceClaimStatuses.
|
||||
\n This field is immutable and no changes
|
||||
will be made to the corresponding ResourceClaim
|
||||
by the control plane after creating the
|
||||
@@ -6480,7 +6541,8 @@ spec:
|
||||
The profile must be preconfigured on the node
|
||||
to work. Must be a descending path, relative
|
||||
to the kubelet's configured seccomp profile
|
||||
location. Must only be set if type is "Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind of seccomp
|
||||
@@ -6553,14 +6615,10 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if a container
|
||||
should be run as a 'Host Process' container.
|
||||
This field is alpha-level and will only be
|
||||
honored by components that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without the
|
||||
feature flag will result in errors when validating
|
||||
the Pod. All of a Pod's containers must have
|
||||
the same effective HostProcess value (it is
|
||||
not allowed to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In addition,
|
||||
All of a Pod's containers must have the same
|
||||
effective HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers and
|
||||
non-HostProcess containers). In addition,
|
||||
if HostProcess is true then HostNetwork must
|
||||
also be set to true.
|
||||
type: boolean
|
||||
|
||||
@@ -143,6 +143,55 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
cpu:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -878,6 +927,67 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
textAnalyze:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
excludeFiles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
fileName:
|
||||
type: string
|
||||
ignoreIfNoFiles:
|
||||
type: boolean
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
regex:
|
||||
type: string
|
||||
regexGroups:
|
||||
type: string
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
time:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -1002,6 +1112,19 @@ spec:
|
||||
- certificatePath
|
||||
- keyPath
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
paths:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- paths
|
||||
type: object
|
||||
copy:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -1137,6 +1260,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1152,6 +1280,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1167,6 +1300,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1230,8 +1368,24 @@ spec:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
exclude:
|
||||
type: BoolString
|
||||
ignoreParentEnvs:
|
||||
type: boolean
|
||||
inheritEnvs:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
input:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
outputDir:
|
||||
type: string
|
||||
required:
|
||||
- args
|
||||
- command
|
||||
|
||||
@@ -143,6 +143,55 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
cpu:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -878,6 +927,67 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
textAnalyze:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
excludeFiles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
fileName:
|
||||
type: string
|
||||
ignoreIfNoFiles:
|
||||
type: boolean
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
regex:
|
||||
type: string
|
||||
regexGroups:
|
||||
type: string
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
time:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -1002,6 +1112,19 @@ spec:
|
||||
- certificatePath
|
||||
- keyPath
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
paths:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- paths
|
||||
type: object
|
||||
copy:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -1137,6 +1260,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1152,6 +1280,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1167,6 +1300,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1230,8 +1368,24 @@ spec:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
exclude:
|
||||
type: BoolString
|
||||
ignoreParentEnvs:
|
||||
type: boolean
|
||||
inheritEnvs:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
input:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
outputDir:
|
||||
type: string
|
||||
required:
|
||||
- args
|
||||
- command
|
||||
@@ -1546,6 +1700,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1561,6 +1720,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1576,6 +1740,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -732,6 +732,8 @@ spec:
|
||||
type: BoolString
|
||||
fileName:
|
||||
type: string
|
||||
jsonPath:
|
||||
type: string
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
@@ -1487,6 +1489,19 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
velero:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
strict:
|
||||
type: BoolString
|
||||
type: object
|
||||
weaveReport:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -1813,6 +1828,17 @@ spec:
|
||||
- namespace
|
||||
- selector
|
||||
type: object
|
||||
helm:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
namespace:
|
||||
type: string
|
||||
releaseName:
|
||||
type: string
|
||||
type: object
|
||||
http:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -1827,6 +1853,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1844,6 +1875,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1859,6 +1895,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -4095,6 +4136,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -4234,8 +4300,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -4275,18 +4341,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -5605,6 +5666,13 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: Restart policy for the container
|
||||
to manage the restart behavior of each container
|
||||
within a pod. This may only be set for init
|
||||
containers. You cannot set this field on ephemeral
|
||||
containers.
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'Optional: SecurityContext defines
|
||||
the security options the ephemeral container
|
||||
@@ -5743,8 +5811,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -5784,18 +5852,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -7151,6 +7214,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -7290,8 +7378,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -7331,18 +7419,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -7804,17 +7887,10 @@ spec:
|
||||
template will be used to create a new ResourceClaim,
|
||||
which will be bound to this pod. When this
|
||||
pod is deleted, the ResourceClaim will also
|
||||
be deleted. The name of the ResourceClaim
|
||||
will be <pod name>-<resource name>, where
|
||||
<resource name> is the PodResourceClaim.Name.
|
||||
Pod validation will reject the pod if the
|
||||
concatenated name is not valid for a ResourceClaim
|
||||
(e.g. too long). \n An existing ResourceClaim
|
||||
with that name that is not owned by the
|
||||
pod will not be used for the pod to avoid
|
||||
using an unrelated resource by mistake.
|
||||
Scheduling and pod startup are then blocked
|
||||
until the unrelated ResourceClaim is removed.
|
||||
be deleted. The pod name and resource name,
|
||||
along with a generated component, will be
|
||||
used to form a unique name for the ResourceClaim,
|
||||
which will be recorded in pod.status.resourceClaimStatuses.
|
||||
\n This field is immutable and no changes
|
||||
will be made to the corresponding ResourceClaim
|
||||
by the control plane after creating the
|
||||
@@ -7975,7 +8051,8 @@ spec:
|
||||
The profile must be preconfigured on the node
|
||||
to work. Must be a descending path, relative
|
||||
to the kubelet's configured seccomp profile
|
||||
location. Must only be set if type is "Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind of seccomp
|
||||
@@ -8048,14 +8125,10 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if a container
|
||||
should be run as a 'Host Process' container.
|
||||
This field is alpha-level and will only be
|
||||
honored by components that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without the
|
||||
feature flag will result in errors when validating
|
||||
the Pod. All of a Pod's containers must have
|
||||
the same effective HostProcess value (it is
|
||||
not allowed to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In addition,
|
||||
All of a Pod's containers must have the same
|
||||
effective HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers and
|
||||
non-HostProcess containers). In addition,
|
||||
if HostProcess is true then HostNetwork must
|
||||
also be set to true.
|
||||
type: boolean
|
||||
@@ -10403,6 +10476,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -10418,6 +10496,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -10433,6 +10516,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -207,6 +207,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -222,6 +227,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -237,6 +247,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
|
||||
@@ -763,6 +763,8 @@ spec:
|
||||
type: BoolString
|
||||
fileName:
|
||||
type: string
|
||||
jsonPath:
|
||||
type: string
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
@@ -1518,6 +1520,19 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
velero:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
strict:
|
||||
type: BoolString
|
||||
type: object
|
||||
weaveReport:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -1844,6 +1859,17 @@ spec:
|
||||
- namespace
|
||||
- selector
|
||||
type: object
|
||||
helm:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
namespace:
|
||||
type: string
|
||||
releaseName:
|
||||
type: string
|
||||
type: object
|
||||
http:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -1858,6 +1884,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1875,6 +1906,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -1890,6 +1926,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -4126,6 +4167,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -4265,8 +4331,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -4306,18 +4372,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -5636,6 +5697,13 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: Restart policy for the container
|
||||
to manage the restart behavior of each container
|
||||
within a pod. This may only be set for init
|
||||
containers. You cannot set this field on ephemeral
|
||||
containers.
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'Optional: SecurityContext defines
|
||||
the security options the ephemeral container
|
||||
@@ -5774,8 +5842,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -5815,18 +5883,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -7182,6 +7245,31 @@ spec:
|
||||
info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/'
|
||||
type: object
|
||||
type: object
|
||||
restartPolicy:
|
||||
description: 'RestartPolicy defines the restart
|
||||
behavior of individual containers in a pod.
|
||||
This field may only be set for init containers,
|
||||
and the only allowed value is "Always". For
|
||||
non-init containers or when this field is not
|
||||
specified, the restart behavior is defined by
|
||||
the Pod''s restart policy and the container
|
||||
type. Setting the RestartPolicy as "Always"
|
||||
for the init container will have the following
|
||||
effect: this init container will be continually
|
||||
restarted on exit until all regular containers
|
||||
have terminated. Once all regular containers
|
||||
have completed, all init containers with restartPolicy
|
||||
"Always" will be shut down. This lifecycle differs
|
||||
from normal init containers and is often referred
|
||||
to as a "sidecar" container. Although this init
|
||||
container still starts in the init container
|
||||
sequence, it does not wait for the container
|
||||
to complete before proceeding to the next init
|
||||
container. Instead, the next init container
|
||||
starts immediately after this init container
|
||||
is started, or after any startupProbe has successfully
|
||||
completed.'
|
||||
type: string
|
||||
securityContext:
|
||||
description: 'SecurityContext defines the security
|
||||
options the container should be run with. If
|
||||
@@ -7321,8 +7409,8 @@ spec:
|
||||
preconfigured on the node to work. Must
|
||||
be a descending path, relative to the
|
||||
kubelet's configured seccomp profile
|
||||
location. Must only be set if type is
|
||||
"Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind
|
||||
@@ -7362,18 +7450,13 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if
|
||||
a container should be run as a 'Host
|
||||
Process' container. This field is alpha-level
|
||||
and will only be honored by components
|
||||
that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without
|
||||
the feature flag will result in errors
|
||||
when validating the Pod. All of a Pod's
|
||||
containers must have the same effective
|
||||
HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In
|
||||
addition, if HostProcess is true then
|
||||
HostNetwork must also be set to true.
|
||||
Process' container. All of a Pod's containers
|
||||
must have the same effective HostProcess
|
||||
value (it is not allowed to have a mix
|
||||
of HostProcess containers and non-HostProcess
|
||||
containers). In addition, if HostProcess
|
||||
is true then HostNetwork must also be
|
||||
set to true.
|
||||
type: boolean
|
||||
runAsUserName:
|
||||
description: The UserName in Windows to
|
||||
@@ -7835,17 +7918,10 @@ spec:
|
||||
template will be used to create a new ResourceClaim,
|
||||
which will be bound to this pod. When this
|
||||
pod is deleted, the ResourceClaim will also
|
||||
be deleted. The name of the ResourceClaim
|
||||
will be <pod name>-<resource name>, where
|
||||
<resource name> is the PodResourceClaim.Name.
|
||||
Pod validation will reject the pod if the
|
||||
concatenated name is not valid for a ResourceClaim
|
||||
(e.g. too long). \n An existing ResourceClaim
|
||||
with that name that is not owned by the
|
||||
pod will not be used for the pod to avoid
|
||||
using an unrelated resource by mistake.
|
||||
Scheduling and pod startup are then blocked
|
||||
until the unrelated ResourceClaim is removed.
|
||||
be deleted. The pod name and resource name,
|
||||
along with a generated component, will be
|
||||
used to form a unique name for the ResourceClaim,
|
||||
which will be recorded in pod.status.resourceClaimStatuses.
|
||||
\n This field is immutable and no changes
|
||||
will be made to the corresponding ResourceClaim
|
||||
by the control plane after creating the
|
||||
@@ -8006,7 +8082,8 @@ spec:
|
||||
The profile must be preconfigured on the node
|
||||
to work. Must be a descending path, relative
|
||||
to the kubelet's configured seccomp profile
|
||||
location. Must only be set if type is "Localhost".
|
||||
location. Must be set if type is "Localhost".
|
||||
Must NOT be set for any other type.
|
||||
type: string
|
||||
type:
|
||||
description: "type indicates which kind of seccomp
|
||||
@@ -8079,14 +8156,10 @@ spec:
|
||||
hostProcess:
|
||||
description: HostProcess determines if a container
|
||||
should be run as a 'Host Process' container.
|
||||
This field is alpha-level and will only be
|
||||
honored by components that enable the WindowsHostProcessContainers
|
||||
feature flag. Setting this field without the
|
||||
feature flag will result in errors when validating
|
||||
the Pod. All of a Pod's containers must have
|
||||
the same effective HostProcess value (it is
|
||||
not allowed to have a mix of HostProcess containers
|
||||
and non-HostProcess containers). In addition,
|
||||
All of a Pod's containers must have the same
|
||||
effective HostProcess value (it is not allowed
|
||||
to have a mix of HostProcess containers and
|
||||
non-HostProcess containers). In addition,
|
||||
if HostProcess is true then HostNetwork must
|
||||
also be set to true.
|
||||
type: boolean
|
||||
@@ -10401,6 +10474,55 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
cpu:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -11136,6 +11258,67 @@ spec:
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
textAnalyze:
|
||||
properties:
|
||||
annotations:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
checkName:
|
||||
type: string
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
excludeFiles:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
fileName:
|
||||
type: string
|
||||
ignoreIfNoFiles:
|
||||
type: boolean
|
||||
outcomes:
|
||||
items:
|
||||
properties:
|
||||
fail:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
pass:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
warn:
|
||||
properties:
|
||||
message:
|
||||
type: string
|
||||
uri:
|
||||
type: string
|
||||
when:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
type: array
|
||||
regex:
|
||||
type: string
|
||||
regexGroups:
|
||||
type: string
|
||||
strict:
|
||||
type: BoolString
|
||||
required:
|
||||
- outcomes
|
||||
type: object
|
||||
time:
|
||||
properties:
|
||||
annotations:
|
||||
@@ -11260,6 +11443,19 @@ spec:
|
||||
- certificatePath
|
||||
- keyPath
|
||||
type: object
|
||||
certificatesCollection:
|
||||
properties:
|
||||
collectorName:
|
||||
type: string
|
||||
exclude:
|
||||
type: BoolString
|
||||
paths:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
required:
|
||||
- paths
|
||||
type: object
|
||||
copy:
|
||||
properties:
|
||||
collectorName:
|
||||
@@ -11395,6 +11591,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -11410,6 +11611,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -11425,6 +11631,11 @@ spec:
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
type: boolean
|
||||
timeout:
|
||||
description: Timeout is the time to wait for a server's
|
||||
response. Its a duration e.g 15s, 2h30m. Missing value
|
||||
or empty string or means no timeout.
|
||||
type: string
|
||||
url:
|
||||
type: string
|
||||
required:
|
||||
@@ -11488,8 +11699,24 @@ spec:
|
||||
type: string
|
||||
command:
|
||||
type: string
|
||||
env:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
exclude:
|
||||
type: BoolString
|
||||
ignoreParentEnvs:
|
||||
type: boolean
|
||||
inheritEnvs:
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
input:
|
||||
additionalProperties:
|
||||
type: string
|
||||
type: object
|
||||
outputDir:
|
||||
type: string
|
||||
required:
|
||||
- args
|
||||
- command
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
project_name: troubleshoot
|
||||
release:
|
||||
github:
|
||||
owner: replicatedhq
|
||||
name: troubleshoot
|
||||
builds:
|
||||
- id: preflight
|
||||
# NOTE: if you add any additional goos/goarch values, ensure you update ../.github/workflows/build-test-deploy.yaml
|
||||
@@ -15,6 +11,7 @@ builds:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
- riscv64
|
||||
ignore:
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
@@ -38,6 +35,7 @@ builds:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
- riscv64
|
||||
ignore:
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
@@ -61,6 +59,7 @@ builds:
|
||||
- amd64
|
||||
- arm
|
||||
- arm64
|
||||
- riscv64
|
||||
ignore:
|
||||
- goos: windows
|
||||
goarch: arm
|
||||
|
||||
+2
-1
@@ -29,6 +29,7 @@ preflight [url] [flags]
|
||||
--cpuprofile string File path to write cpu profiling data
|
||||
--debug enable debug logging
|
||||
--disable-compression If true, opt-out of response compression for all requests to the server
|
||||
--dry-run print the preflight spec without running preflight checks
|
||||
--format string output format, one of human, json, yaml. only used when interactive is set to false (default "human")
|
||||
-h, --help help for preflight
|
||||
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
|
||||
@@ -53,4 +54,4 @@ preflight [url] [flags]
|
||||
* [preflight oci-fetch](preflight_oci-fetch.md) - Fetch a preflight from an OCI registry and print it to standard out
|
||||
* [preflight version](preflight_version.md) - Print the current version and exit
|
||||
|
||||
###### Auto generated by spf13/cobra on 8-Jun-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -33,4 +33,4 @@ preflight oci-fetch [URI] [flags]
|
||||
|
||||
* [preflight](preflight.md) - Run and retrieve preflight checks in a cluster
|
||||
|
||||
###### Auto generated by spf13/cobra on 8-Jun-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -37,4 +37,4 @@ preflight version [flags]
|
||||
|
||||
* [preflight](preflight.md) - Run and retrieve preflight checks in a cluster
|
||||
|
||||
###### Auto generated by spf13/cobra on 3-Jan-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -55,4 +55,4 @@ support-bundle [urls...] [flags]
|
||||
* [support-bundle redact](support-bundle_redact.md) - Redact information from a generated support bundle archive
|
||||
* [support-bundle version](support-bundle_version.md) - Print the current version and exit
|
||||
|
||||
###### Auto generated by spf13/cobra on 8-Jun-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -30,4 +30,4 @@ support-bundle analyze [url] [flags]
|
||||
|
||||
* [support-bundle](support-bundle.md) - Generate a support bundle
|
||||
|
||||
###### Auto generated by spf13/cobra on 3-Jan-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -39,4 +39,4 @@ support-bundle redact [urls...] [flags]
|
||||
|
||||
* [support-bundle](support-bundle.md) - Generate a support bundle
|
||||
|
||||
###### Auto generated by spf13/cobra on 3-Jan-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -27,4 +27,4 @@ support-bundle version [flags]
|
||||
|
||||
* [support-bundle](support-bundle.md) - Generate a support bundle
|
||||
|
||||
###### Auto generated by spf13/cobra on 3-Jan-2023
|
||||
###### Auto generated by spf13/cobra on 31-Aug-2023
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
apiVersion: troubleshoot.sh/v1beta2
|
||||
kind: HostCollector
|
||||
metadata:
|
||||
name: run-host-cmd-and-save-output
|
||||
spec:
|
||||
collectors:
|
||||
- run:
|
||||
collectorName: "my-custom-run"
|
||||
command: "sh"
|
||||
# this is for demonstration purpose only -- you probably don't want to drop your input to the bundle!
|
||||
args:
|
||||
- "-c"
|
||||
- "cat $TS_INPUT_DIR/dummy.yaml > $TS_OUTPUT_DIR/dummy_content.yaml"
|
||||
outputDir: "myCommandOutputs"
|
||||
env:
|
||||
- AWS_REGION=us-west-1
|
||||
# if ignoreParentEnvs is true, it will not inherit envs from parent process.
|
||||
# values specified in inheritEnv will not be used either
|
||||
# ignoreParentEnvs: true
|
||||
inheritEnvs:
|
||||
- USER
|
||||
input:
|
||||
dummy.conf: |-
|
||||
[hello]
|
||||
hello = 1
|
||||
|
||||
[bye]
|
||||
bye = 2
|
||||
dummy.yaml: |-
|
||||
username: postgres
|
||||
password: <my-pass>
|
||||
dbHost: <hostname>
|
||||
map:
|
||||
key: value
|
||||
list:
|
||||
- val1
|
||||
- val2
|
||||
@@ -19,4 +19,3 @@ spec:
|
||||
message: At least 16 CPU cores preferred
|
||||
- pass:
|
||||
message: This server has sufficient CPU cores
|
||||
|
||||
|
||||
@@ -72,6 +72,9 @@ spec:
|
||||
- pass:
|
||||
when: "== k3s"
|
||||
message: K3S is a supported distribution
|
||||
- pass:
|
||||
when: "== oke"
|
||||
message: OKE is a supported distribution
|
||||
- warn:
|
||||
message: Unable to determine the distribution of Kubernetes
|
||||
- nodeResources:
|
||||
|
||||
@@ -9,7 +9,7 @@ replace github.com/replicatedhq/troubleshoot v0.0.0 => ../../../
|
||||
|
||||
require (
|
||||
github.com/replicatedhq/troubleshoot v0.0.0
|
||||
helm.sh/helm/v3 v3.12.1
|
||||
helm.sh/helm/v3 v3.12.3
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
@@ -18,8 +18,8 @@ require (
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||
@@ -28,10 +28,10 @@ require (
|
||||
github.com/gobwas/glob v0.2.3 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.15 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
@@ -48,26 +48,26 @@ require (
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/oauth2 v0.7.0 // indirect
|
||||
golang.org/x/sys v0.8.0 // indirect
|
||||
golang.org/x/term v0.8.0 // indirect
|
||||
golang.org/x/text v0.10.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
google.golang.org/protobuf v1.31.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/api v0.27.3 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.27.2 // indirect
|
||||
k8s.io/apimachinery v0.27.3 // indirect
|
||||
k8s.io/client-go v0.27.3 // indirect
|
||||
k8s.io/api v0.28.2 // indirect
|
||||
k8s.io/apiextensions-apiserver v0.28.1 // indirect
|
||||
k8s.io/apimachinery v0.28.2 // indirect
|
||||
k8s.io/client-go v0.28.2 // indirect
|
||||
k8s.io/klog/v2 v2.100.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.15.0 // indirect
|
||||
sigs.k8s.io/controller-runtime v0.16.2 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
)
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
|
||||
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
@@ -10,33 +7,16 @@ github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0
|
||||
github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA=
|
||||
github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
|
||||
github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@@ -51,31 +31,12 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
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.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
|
||||
github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
|
||||
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/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.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
@@ -84,10 +45,8 @@ 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-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU=
|
||||
github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
@@ -100,7 +59,6 @@ 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/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -122,24 +80,21 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/onsi/ginkgo/v2 v2.9.5 h1:+6Hr4uxzP4XIUyAkg61dWBw8lb/gc4/X5luuxN/EC+Q=
|
||||
github.com/onsi/gomega v1.27.7 h1:fVih9JD6ogIiHUN6ePK7HJidyEDpWGVB5mzM7cWNXoU=
|
||||
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
|
||||
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
@@ -160,161 +115,103 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
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.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
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/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/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-20190108225652-1e06a53dbb7e/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-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
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-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
|
||||
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
|
||||
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-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
|
||||
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
|
||||
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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
|
||||
golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
|
||||
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/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/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
|
||||
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
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-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
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.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.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
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.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/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=
|
||||
helm.sh/helm/v3 v3.12.1 h1:lzU7etZX24A6BTMXYQF3bFq0ECfD8s+fKlNBBL8AbEc=
|
||||
helm.sh/helm/v3 v3.12.1/go.mod h1:qhmSY9kcX7yH1xebe+FDMZa7E5NAeZ+LvK5j1gSln48=
|
||||
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.27.3 h1:yR6oQXXnUEBWEWcvPWS0jQL575KoAboQPfJAuKNrw5Y=
|
||||
k8s.io/api v0.27.3/go.mod h1:C4BNvZnQOF7JA/0Xed2S+aUyJSfTGkGFxLXz9MnpIpg=
|
||||
k8s.io/apiextensions-apiserver v0.27.2 h1:iwhyoeS4xj9Y7v8YExhUwbVuBhMr3Q4bd/laClBV6Bo=
|
||||
k8s.io/apiextensions-apiserver v0.27.2/go.mod h1:Oz9UdvGguL3ULgRdY9QMUzL2RZImotgxvGjdWRq6ZXQ=
|
||||
k8s.io/apimachinery v0.27.3 h1:Ubye8oBufD04l9QnNtW05idcOe9Z3GQN8+7PqmuVcUM=
|
||||
k8s.io/apimachinery v0.27.3/go.mod h1:XNfZ6xklnMCOGGFNqXG7bUrQCoR04dh/E7FprV6pb+E=
|
||||
k8s.io/client-go v0.27.3 h1:7dnEGHZEJld3lYwxvLl7WoehK6lAq7GvgjxpA3nv1E8=
|
||||
k8s.io/client-go v0.27.3/go.mod h1:2MBEKuTo6V1lbKy3z1euEGnhPfGZLKTS9tiJ2xodM48=
|
||||
helm.sh/helm/v3 v3.12.3 h1:5y1+Sbty12t48T/t/CGNYUIME5BJ0WKfmW/sobYqkFg=
|
||||
helm.sh/helm/v3 v3.12.3/go.mod h1:KPKQiX9IP5HX7o5YnnhViMnNuKiL/lJBVQ47GHe1R0k=
|
||||
k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
|
||||
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
|
||||
k8s.io/apiextensions-apiserver v0.28.1 h1:l2ThkBRjrWpw4f24uq0Da2HaEgqJZ7pcgiEUTKSmQZw=
|
||||
k8s.io/apiextensions-apiserver v0.28.1/go.mod h1:sVvrI+P4vxh2YBBcm8n2ThjNyzU4BQGilCQ/JAY5kGs=
|
||||
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
|
||||
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
|
||||
k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
|
||||
k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
|
||||
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
|
||||
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f h1:2kWPakN3i/k81b0gvD5C5FJ2kxm1WrQFanWchyKuqGg=
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f/go.mod h1:byini6yhqGC14c3ebc/QwanvYwhuMWF6yz2F8uwW8eg=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ=
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM=
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk=
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||
sigs.k8s.io/controller-runtime v0.15.0 h1:ML+5Adt3qZnMSYxZ7gAverBLNPSMQEibtzAgp0UPojU=
|
||||
sigs.k8s.io/controller-runtime v0.15.0/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk=
|
||||
sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU=
|
||||
sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU=
|
||||
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/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/replicatedhq/troubleshoot
|
||||
|
||||
go 1.19
|
||||
go 1.20
|
||||
|
||||
require (
|
||||
github.com/ahmetalpbalkan/go-cursor v0.0.0-20131010032410-8136607ea412
|
||||
@@ -15,83 +15,115 @@ require (
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/godbus/dbus/v5 v5.1.0
|
||||
github.com/google/gofuzz v1.2.0
|
||||
github.com/google/uuid v1.3.0
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/gorilla/handlers v1.5.1
|
||||
github.com/hashicorp/go-getter v1.7.1
|
||||
github.com/hashicorp/go-getter v1.7.2
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/jackc/pgx/v5 v5.4.1
|
||||
github.com/jackc/pgx/v5 v5.4.3
|
||||
github.com/longhorn/go-iscsi-helper v0.0.0-20210330030558-49a327fb024e
|
||||
github.com/manifoldco/promptui v0.9.0
|
||||
github.com/mattn/go-isatty v0.0.19
|
||||
github.com/mholt/archiver/v3 v3.5.1
|
||||
github.com/microsoft/go-mssqldb v1.3.0
|
||||
github.com/microsoft/go-mssqldb v1.6.0
|
||||
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/replicatedhq/termui/v3 v3.1.1-0.20200811145416-f40076d26851
|
||||
github.com/segmentio/ksuid v1.0.4
|
||||
github.com/shirou/gopsutil/v3 v3.23.6
|
||||
github.com/shirou/gopsutil/v3 v3.23.9
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.16.0
|
||||
github.com/spf13/viper v1.17.0
|
||||
github.com/stretchr/testify v1.8.4
|
||||
github.com/tj/go-spin v1.1.0
|
||||
go.opentelemetry.io/otel v1.16.0
|
||||
go.opentelemetry.io/otel/sdk v1.16.0
|
||||
golang.org/x/sync v0.3.0
|
||||
github.com/vmware-tanzu/velero v1.12.0
|
||||
go.opentelemetry.io/otel v1.19.0
|
||||
go.opentelemetry.io/otel/sdk v1.19.0
|
||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
|
||||
golang.org/x/mod v0.12.0
|
||||
golang.org/x/sync v0.4.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.27.3
|
||||
k8s.io/apiextensions-apiserver v0.27.2
|
||||
k8s.io/apimachinery v0.27.3
|
||||
k8s.io/apiserver v0.27.3
|
||||
k8s.io/cli-runtime v0.27.3
|
||||
k8s.io/client-go v0.27.3
|
||||
k8s.io/api v0.28.2
|
||||
k8s.io/apiextensions-apiserver v0.28.1
|
||||
k8s.io/apimachinery v0.28.2
|
||||
k8s.io/apiserver v0.28.1
|
||||
k8s.io/cli-runtime v0.28.2
|
||||
k8s.io/client-go v0.28.2
|
||||
k8s.io/klog/v2 v2.100.1
|
||||
oras.land/oras-go v1.2.3
|
||||
sigs.k8s.io/controller-runtime v0.15.0
|
||||
sigs.k8s.io/controller-runtime v0.16.2
|
||||
sigs.k8s.io/e2e-framework v0.3.0
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230106234847-43070de90fa1 // indirect
|
||||
github.com/MakeNowJust/heredoc v1.0.0 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Masterminds/squirrel v1.5.4 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/chai2010/gettext-go v1.0.2 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/docker/distribution v2.8.2+incompatible // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
|
||||
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
|
||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.0.5 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/google/s2a-go v0.1.3 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/s2a-go v0.1.7 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
|
||||
github.com/gosuri/uitable v0.0.4 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jmoiron/sqlx v1.3.5 // indirect
|
||||
github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
|
||||
github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/mistifyio/go-zfs/v3 v3.0.0 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/rubenv/sql-migrate v1.3.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/sylabs/sif/v2 v2.11.1 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.16.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.16.0 // indirect
|
||||
go.uber.org/atomic v1.10.0 // indirect
|
||||
github.com/vladimirvivien/gexe v0.2.0 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
|
||||
golang.org/x/mod v0.10.0 // indirect
|
||||
golang.org/x/tools v0.9.1 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
|
||||
k8s.io/component-base v0.28.1 // indirect
|
||||
k8s.io/kubectl v0.28.1 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.0 // indirect
|
||||
cloud.google.com/go/compute v1.19.0 // indirect
|
||||
cloud.google.com/go/iam v0.13.0 // indirect
|
||||
cloud.google.com/go/storage v1.28.1 // indirect
|
||||
cloud.google.com/go v0.110.7 // indirect
|
||||
cloud.google.com/go/compute v1.23.0 // indirect
|
||||
cloud.google.com/go/iam v1.1.1 // indirect
|
||||
cloud.google.com/go/storage v1.30.1 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/BurntSushi/toml v1.2.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/Microsoft/hcsshim v0.10.0-rc.7 // indirect
|
||||
github.com/andybalholm/brotli v1.0.1 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.122 // indirect
|
||||
github.com/aws/aws-sdk-go v1.44.253 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
|
||||
github.com/c9s/goprocinfo v0.0.0-20170724085704-0010a05ce49f // indirect
|
||||
@@ -103,8 +135,8 @@ require (
|
||||
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
|
||||
github.com/containers/ocicrypt v1.1.7 // indirect
|
||||
github.com/containers/storage v1.46.0 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/cli v23.0.1+incompatible // indirect
|
||||
github.com/docker/docker v23.0.3+incompatible // indirect
|
||||
github.com/docker/docker-credential-helpers v0.7.0 // indirect
|
||||
@@ -125,11 +157,10 @@ require (
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/gnostic v0.6.9 // indirect
|
||||
github.com/google/go-cmp v0.5.9 // indirect
|
||||
github.com/google/go-intervals v0.0.2 // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.8.0 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/gorilla/mux v1.8.0 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
@@ -142,7 +173,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.16.3 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6-0.20220930104621-17e8dac29df8 // indirect
|
||||
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
@@ -171,54 +202,54 @@ require (
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.2 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_golang v1.15.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
github.com/prometheus/client_model v0.4.0 // indirect
|
||||
github.com/prometheus/common v0.42.0 // indirect
|
||||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/prometheus/common v0.44.0 // indirect
|
||||
github.com/prometheus/procfs v0.10.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/spf13/afero v1.9.5 // indirect
|
||||
github.com/spf13/afero v1.10.0 // indirect
|
||||
github.com/spf13/cast v1.5.1 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/subosito/gotenv v1.4.2 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.12 // indirect
|
||||
github.com/tklauser/numcpus v0.6.1 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||
github.com/xlab/treeprint v1.1.0 // indirect
|
||||
github.com/xlab/treeprint v1.2.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
|
||||
golang.org/x/crypto v0.9.0 // indirect
|
||||
golang.org/x/net v0.10.0 // indirect
|
||||
golang.org/x/oauth2 v0.7.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/term v0.8.0 // indirect
|
||||
golang.org/x/text v0.11.0
|
||||
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/oauth2 v0.12.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/term v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.122.0 // indirect
|
||||
google.golang.org/api v0.143.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect
|
||||
google.golang.org/grpc v1.55.0 // indirect
|
||||
google.golang.org/protobuf v1.30.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
|
||||
google.golang.org/grpc v1.58.3 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
|
||||
k8s.io/metrics v0.27.3
|
||||
helm.sh/helm/v3 v3.12.3
|
||||
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
|
||||
k8s.io/metrics v0.28.2
|
||||
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
|
||||
periph.io/x/host/v3 v3.8.2
|
||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.2 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.1 // indirect
|
||||
sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0 // indirect
|
||||
sigs.k8s.io/yaml v1.3.0
|
||||
)
|
||||
|
||||
replace (
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package specs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
func LoadFromConfigMap(ctx context.Context, client kubernetes.Interface, ns string, name string) (map[string]string, error) {
|
||||
foundConfigMap, err := client.CoreV1().ConfigMaps(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get configmap")
|
||||
}
|
||||
|
||||
klog.V(1).InfoS("Loaded data from config map", "name",
|
||||
foundConfigMap.Name, "namespace", foundConfigMap.Namespace,
|
||||
)
|
||||
|
||||
return foundConfigMap.Data, nil
|
||||
}
|
||||
|
||||
func LoadFromConfigMapMatchingLabel(ctx context.Context, client kubernetes.Interface, label string, ns string, key string) ([]string, error) {
|
||||
var configMapMatchingKey []string
|
||||
|
||||
configMaps, err := client.CoreV1().ConfigMaps(ns).List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to search for configmaps in the cluster")
|
||||
}
|
||||
|
||||
for _, configMap := range configMaps.Items {
|
||||
spec, ok := configMap.Data[key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
klog.V(1).InfoS("Loaded spec from config map", "name", configMap.Name,
|
||||
"namespace", configMap.Namespace, "data key", key, "label selector", label,
|
||||
)
|
||||
configMapMatchingKey = append(configMapMatchingKey, string(spec))
|
||||
}
|
||||
|
||||
return configMapMatchingKey, nil
|
||||
}
|
||||
@@ -359,7 +359,7 @@ spec:
|
||||
_, err := client.CoreV1().ConfigMaps(configmap.Namespace).Create(ctx, &configmap, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromConfigMapMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "", "support-bundle-spec")
|
||||
got, err := LoadFromConfigMapMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "", "support-bundle-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -451,7 +451,7 @@ spec:
|
||||
_, err := client.CoreV1().ConfigMaps(configmap.Namespace).Create(ctx, &configmap, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromConfigMapMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "some-namespace", "support-bundle-spec")
|
||||
got, err := LoadFromConfigMapMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "some-namespace", "support-bundle-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -549,7 +549,7 @@ spec:
|
||||
_, err := client.CoreV1().ConfigMaps(configmap.Namespace).Create(ctx, &configmap, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromConfigMapMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "", "redactor-spec")
|
||||
got, err := LoadFromConfigMapMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "", "redactor-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -0,0 +1,42 @@
|
||||
package specs
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
func LoadFromSecret(ctx context.Context, client kubernetes.Interface, ns string, name string) (map[string][]byte, error) {
|
||||
foundSecret, err := client.CoreV1().Secrets(ns).Get(ctx, name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get secret")
|
||||
}
|
||||
|
||||
return foundSecret.Data, nil
|
||||
}
|
||||
|
||||
func LoadFromSecretMatchingLabel(ctx context.Context, client kubernetes.Interface, label string, ns string, key string) ([]string, error) {
|
||||
var secretsMatchingKey []string
|
||||
|
||||
secrets, err := client.CoreV1().Secrets(ns).List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to search for secrets in the cluster")
|
||||
}
|
||||
|
||||
for _, secret := range secrets.Items {
|
||||
spec, ok := secret.Data[key]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
klog.V(1).InfoS("Loaded spec from secret", "name", secret.Name,
|
||||
"namespace", secret.Namespace, "data key", key, "label selector", label,
|
||||
)
|
||||
secretsMatchingKey = append(secretsMatchingKey, string(spec))
|
||||
}
|
||||
|
||||
return secretsMatchingKey, nil
|
||||
}
|
||||
@@ -359,7 +359,7 @@ spec:
|
||||
_, err := client.CoreV1().Secrets(secret.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromSecretMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "", "support-bundle-spec")
|
||||
got, err := LoadFromSecretMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "", "support-bundle-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -451,7 +451,7 @@ spec:
|
||||
_, err := client.CoreV1().Secrets(secret.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromSecretMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "some-namespace", "support-bundle-spec")
|
||||
got, err := LoadFromSecretMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "some-namespace", "support-bundle-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -549,7 +549,7 @@ spec:
|
||||
_, err := client.CoreV1().Secrets(secret.Namespace).Create(ctx, &secret, metav1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
got, err := LoadFromSecretMatchingLabel(client, "troubleshoot.io/kind=support-bundle", "", "redactor-spec")
|
||||
got, err := LoadFromSecretMatchingLabel(ctx, client, "troubleshoot.io/kind=support-bundle", "", "redactor-spec")
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
@@ -0,0 +1,342 @@
|
||||
package specs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/replicatedhq/troubleshoot/internal/util"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/constants"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/loader"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/oci"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/types"
|
||||
"github.com/spf13/viper"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
// SplitTroubleshootSecretLabelSelector splits a label selector into two selectors, if applicable:
|
||||
// 1. troubleshoot.io/kind=support-bundle and non-troubleshoot (if contains) labels selector.
|
||||
// 2. troubleshoot.sh/kind=support-bundle and non-troubleshoot (if contains) labels selector.
|
||||
func SplitTroubleshootSecretLabelSelector(ctx context.Context, labelSelector labels.Selector) ([]string, error) {
|
||||
|
||||
klog.V(1).Infof("Split %q selector into troubleshoot and non-troubleshoot labels selector separately, if applicable", labelSelector.String())
|
||||
|
||||
selectorRequirements, selectorSelectable := labelSelector.Requirements()
|
||||
if !selectorSelectable {
|
||||
return nil, errors.Errorf("Selector %q is not selectable", labelSelector.String())
|
||||
}
|
||||
|
||||
var troubleshootReqs, otherReqs []labels.Requirement
|
||||
|
||||
for _, req := range selectorRequirements {
|
||||
if req.Key() == constants.TroubleshootIOLabelKey || req.Key() == constants.TroubleshootSHLabelKey {
|
||||
troubleshootReqs = append(troubleshootReqs, req)
|
||||
} else {
|
||||
otherReqs = append(otherReqs, req)
|
||||
}
|
||||
}
|
||||
|
||||
parsedSelectorStrings := make([]string, 0)
|
||||
// Combine each troubleshoot requirement with other requirements to form new selectors
|
||||
s := labelSelector.String()
|
||||
if len(troubleshootReqs) == 0 && s != "" {
|
||||
return []string{s}, nil
|
||||
}
|
||||
|
||||
for _, tReq := range troubleshootReqs {
|
||||
reqs := append(otherReqs, tReq)
|
||||
newSelector := labels.NewSelector().Add(reqs...)
|
||||
parsedSelectorStrings = append(parsedSelectorStrings, newSelector.String())
|
||||
}
|
||||
|
||||
return parsedSelectorStrings, nil
|
||||
}
|
||||
|
||||
var httpClient = &http.Client{
|
||||
Timeout: 30 * time.Second,
|
||||
}
|
||||
|
||||
// LoadFromCLIArgs loads troubleshoot specs from args passed to a CLI command.
|
||||
// This loader function is meant for troubleshoot CLI commands only, hence not making it public.
|
||||
// It will contain opinionated logic for CLI commands such as interpreting viper flags,
|
||||
// supporting secret/ uri format, downloading from OCI registry and other URLs, etc.
|
||||
func LoadFromCLIArgs(ctx context.Context, client kubernetes.Interface, args []string, vp *viper.Viper) (*loader.TroubleshootKinds, error) {
|
||||
// Let's always ensure we have a context
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
rawSpecs := []string{}
|
||||
|
||||
for _, v := range args {
|
||||
if strings.HasPrefix(v, "secret/") {
|
||||
// format secret/namespace-name/secret-name[/data-key]
|
||||
pathParts := strings.Split(v, "/")
|
||||
if len(pathParts) > 4 {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("secret path %s must have at most 4 components", v))
|
||||
}
|
||||
if len(pathParts) < 3 {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("secret path %s must have at least 3 components", v))
|
||||
}
|
||||
|
||||
data, err := LoadFromSecret(ctx, client, pathParts[1], pathParts[2])
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to get spec from secret"))
|
||||
}
|
||||
|
||||
// If we have a key defined, then load specs from that key only.
|
||||
if len(pathParts) == 4 {
|
||||
spec, ok := data[pathParts[3]]
|
||||
if ok {
|
||||
rawSpecs = append(rawSpecs, string(spec))
|
||||
}
|
||||
} else {
|
||||
// Append all data in the secret. Some may not be specs, but that's ok. They will be ignored.
|
||||
for _, spec := range data {
|
||||
rawSpecs = append(rawSpecs, string(spec))
|
||||
}
|
||||
}
|
||||
} else if strings.HasPrefix(v, "configmap/") {
|
||||
// format configmap/namespace-name/configmap-name[/data-key]
|
||||
pathParts := strings.Split(v, "/")
|
||||
if len(pathParts) > 4 {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("configmap path %s must have at most 4 components", v))
|
||||
}
|
||||
if len(pathParts) < 3 {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("configmap path %s must have at least 3 components", v))
|
||||
}
|
||||
|
||||
data, err := LoadFromConfigMap(ctx, client, pathParts[1], pathParts[2])
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to get spec from configmap"))
|
||||
}
|
||||
|
||||
// If we have a key defined, then load specs from that key only.
|
||||
if len(pathParts) == 4 {
|
||||
spec, ok := data[pathParts[3]]
|
||||
if ok {
|
||||
rawSpecs = append(rawSpecs, spec)
|
||||
}
|
||||
} else {
|
||||
// Append all data in the configmap. Some may not be specs, but that's ok. They will be ignored.
|
||||
for _, spec := range data {
|
||||
rawSpecs = append(rawSpecs, spec)
|
||||
}
|
||||
}
|
||||
} else if _, err := os.Stat(v); err == nil {
|
||||
b, err := os.ReadFile(v)
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
|
||||
}
|
||||
|
||||
rawSpecs = append(rawSpecs, string(b))
|
||||
} else if v == "-" {
|
||||
b, err := io.ReadAll(os.Stdin)
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, err)
|
||||
}
|
||||
rawSpecs = append(rawSpecs, string(b))
|
||||
} else {
|
||||
u, err := url.Parse(v)
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
|
||||
}
|
||||
|
||||
if u.Scheme == "oci" {
|
||||
content, err := oci.PullSpecsFromOCI(ctx, v)
|
||||
if err != nil {
|
||||
if err == oci.ErrNoRelease {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("no release found for %s.\nCheck the oci:// uri for errors or contact the application vendor for support.", v))
|
||||
}
|
||||
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
|
||||
}
|
||||
|
||||
rawSpecs = append(rawSpecs, content...)
|
||||
} else {
|
||||
if !util.IsURL(v) {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, fmt.Errorf("%s is not a URL and was not found (err %s)", v, err))
|
||||
}
|
||||
|
||||
// Download preflight specs
|
||||
rawSpec, err := downloadFromHttpURL(ctx, v, map[string]string{"User-Agent": "Replicated_Preflight/v1beta2"})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawSpecs = append(rawSpecs, rawSpec)
|
||||
|
||||
// Download support bundle specs
|
||||
rawSpec, err = downloadFromHttpURL(ctx, v, map[string]string{
|
||||
"User-Agent": "Replicated_Troubleshoot/v1beta1",
|
||||
"Bundle-Upload-Host": fmt.Sprintf("%s://%s", u.Scheme, u.Host),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawSpecs = append(rawSpecs, rawSpec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
|
||||
RawSpecs: rawSpecs,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if vp.GetBool("load-cluster-specs") {
|
||||
clusterKinds, err := LoadFromCluster(ctx, client, vp.GetStringSlice("selector"), vp.GetString("namespace"))
|
||||
if err != nil {
|
||||
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
|
||||
}
|
||||
|
||||
kinds.Add(clusterKinds)
|
||||
}
|
||||
|
||||
return kinds, nil
|
||||
}
|
||||
|
||||
func downloadFromHttpURL(ctx context.Context, url string, headers map[string]string) (string, error) {
|
||||
hs := []string{}
|
||||
for k, v := range headers {
|
||||
hs = append(hs, fmt.Sprintf("%s: %s", k, v))
|
||||
}
|
||||
|
||||
klog.V(1).Infof("Downloading troubleshoot specs: url=%s, headers=[%v]", url, strings.Join(hs, ", "))
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
// exit code: should this be catch all or spec issues...?
|
||||
return "", types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, err)
|
||||
}
|
||||
for k, v := range headers {
|
||||
req.Header.Set(k, v)
|
||||
}
|
||||
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
// exit code: should this be catch all or spec issues...?
|
||||
return "", types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
klog.V(1).Infof("Response status: %s", resp.Status)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
|
||||
}
|
||||
return string(body), nil
|
||||
}
|
||||
|
||||
// LoadFromCluster loads troubleshoot specs from the cluster based on the provided labels.
|
||||
// By default this will be troubleshoot.io/kind=support-bundle and troubleshoot.sh/kind=support-bundle
|
||||
// labels. We search for secrets and configmaps with the label selector and extract the raw data.
|
||||
// We then load the specs from the raw data. If the user does not have sufficient permissions
|
||||
// to list & read secrets and configmaps from all namespaces, we will fallback to trying each
|
||||
// namespace individually, and eventually default to the configured kubeconfig namespace.
|
||||
func LoadFromCluster(ctx context.Context, client kubernetes.Interface, selectors []string, ns string) (*loader.TroubleshootKinds, error) {
|
||||
if reflect.DeepEqual(selectors, []string{"troubleshoot.sh/kind=support-bundle"}) {
|
||||
// Its the default selector so we append troubleshoot.io/kind=support-bundle to it due to backwards compatibility
|
||||
selectors = append(selectors, "troubleshoot.io/kind=support-bundle")
|
||||
}
|
||||
|
||||
labelSelector := strings.Join(selectors, ",")
|
||||
|
||||
parsedSelector, err := labels.Parse(labelSelector)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse selector")
|
||||
}
|
||||
|
||||
// List of namespaces we want to search for secrets and configmaps with support bundle specs
|
||||
namespaces := []string{}
|
||||
if ns != "" {
|
||||
// Just progress with the namespace provided
|
||||
namespaces = []string{ns}
|
||||
} else {
|
||||
// Check if I can read secrets and configmaps in all namespaces
|
||||
ican, err := k8sutil.CanIListAndGetAllSecretsAndConfigMaps(ctx, client)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to check if I can read secrets and configmaps")
|
||||
}
|
||||
klog.V(1).Infof("Can I read any secrets and configmaps: %v", ican)
|
||||
|
||||
if ican {
|
||||
// I can read secrets and configmaps in all namespaces
|
||||
// No need to iterate over all namespaces
|
||||
namespaces = []string{""}
|
||||
} else {
|
||||
// Get list of all namespaces and try to find specs from each namespace
|
||||
nsList, err := client.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
if k8serrors.IsForbidden(err) {
|
||||
kubeconfig := k8sutil.GetKubeconfig()
|
||||
ns, _, err := kubeconfig.Namespace()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get namespace from kubeconfig")
|
||||
}
|
||||
// If we are not allowed to list namespaces, just use the default namespace
|
||||
// configured in the kubeconfig
|
||||
namespaces = []string{ns}
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "failed to list namespaces")
|
||||
}
|
||||
}
|
||||
|
||||
for _, ns := range nsList.Items {
|
||||
namespaces = append(namespaces, ns.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var rawSpecs []string
|
||||
|
||||
parsedSelectorStrings, err := SplitTroubleshootSecretLabelSelector(ctx, parsedSelector)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to parse troubleshoot labels selector %s", err)
|
||||
}
|
||||
|
||||
// Iteratively search for troubleshoot specs in all namespaces using the given selectors
|
||||
for _, parsedSelectorString := range parsedSelectorStrings {
|
||||
klog.V(1).Infof("Search specs from [%q] namespace using %q selector", strings.Join(namespaces, ", "), parsedSelectorString)
|
||||
for _, ns := range namespaces {
|
||||
for _, key := range []string{constants.SupportBundleKey, constants.PreflightKey, constants.RedactorKey} {
|
||||
specs, err := LoadFromSecretMatchingLabel(ctx, client, parsedSelectorString, ns, key)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from secrets: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading secrets from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
rawSpecs = append(rawSpecs, specs...)
|
||||
|
||||
specs, err = LoadFromConfigMapMatchingLabel(ctx, client, parsedSelectorString, ns, key)
|
||||
if err != nil {
|
||||
if !k8serrors.IsForbidden(err) {
|
||||
klog.Errorf("failed to load support bundle spec from configmap: %s", err)
|
||||
} else {
|
||||
klog.Warningf("Reading configmaps from %q namespace forbidden", ns)
|
||||
}
|
||||
}
|
||||
rawSpecs = append(rawSpecs, specs...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load troubleshoot specs from the raw specs
|
||||
return loader.LoadSpecs(ctx, loader.LoadOptions{
|
||||
RawSpecs: rawSpecs,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package specs
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/replicatedhq/troubleshoot/internal/testutils"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/loader"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
testclient "k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func Test_SplitTroubleshootSecretLabelSelector(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
selectorString string
|
||||
expectedSelectors []string
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Split both troubleshoot and non-troubleshoot labels",
|
||||
selectorString: "troubleshoot.io/kind=support-bundle,troubleshoot.sh/kind=support-bundle,a=b",
|
||||
expectedSelectors: []string{
|
||||
"a=b,troubleshoot.io/kind=support-bundle",
|
||||
"a=b,troubleshoot.sh/kind=support-bundle",
|
||||
},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Split only troubleshoot.io label",
|
||||
selectorString: "troubleshoot.io/kind=support-bundle",
|
||||
expectedSelectors: []string{"troubleshoot.io/kind=support-bundle"},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Split only troubleshoot.sh label",
|
||||
selectorString: "troubleshoot.sh/kind=support-bundle",
|
||||
expectedSelectors: []string{"troubleshoot.sh/kind=support-bundle"},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Split only non-troubleshoot label",
|
||||
selectorString: "a=b",
|
||||
expectedSelectors: []string{"a=b"},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "No selector labels to split",
|
||||
selectorString: "",
|
||||
expectedSelectors: []string{},
|
||||
expectedError: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
selector, err := labels.Parse(tt.selectorString)
|
||||
if err != nil {
|
||||
t.Errorf("Error parsing selector string: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
gotSelectors, err := SplitTroubleshootSecretLabelSelector(context.TODO(), selector)
|
||||
if (err != nil) != tt.expectedError {
|
||||
t.Errorf("Expected error: %v, got: %v", tt.expectedError, err)
|
||||
return
|
||||
}
|
||||
|
||||
assert.ElementsMatch(t, tt.expectedSelectors, gotSelectors)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoadFromCluster(t *testing.T) {
|
||||
theRedactor := troubleshootv1beta2.Redactor{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "troubleshoot.sh/v1beta2",
|
||||
Kind: "Redactor",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "redact-some-content",
|
||||
},
|
||||
Spec: troubleshootv1beta2.RedactorSpec{
|
||||
Redactors: []*troubleshootv1beta2.Redact{
|
||||
{
|
||||
Name: "redact-text-1",
|
||||
Removals: troubleshootv1beta2.Removals{
|
||||
Values: []string{"TEXT"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
selectors []string
|
||||
namespace string
|
||||
objects []runtime.Object
|
||||
want *loader.TroubleshootKinds
|
||||
}{
|
||||
{
|
||||
name: "no selectors",
|
||||
want: loader.NewTroubleshootKinds(),
|
||||
},
|
||||
{
|
||||
name: "spec in secret and default label selector",
|
||||
namespace: "bigbank",
|
||||
selectors: []string{
|
||||
"troubleshoot.sh/kind=support-bundle",
|
||||
},
|
||||
objects: []runtime.Object{
|
||||
secretObject("bigbank", map[string]string{
|
||||
"troubleshoot.io/kind": "support-bundle",
|
||||
}),
|
||||
},
|
||||
want: &loader.TroubleshootKinds{
|
||||
RedactorsV1Beta2: []troubleshootv1beta2.Redactor{theRedactor},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "spec in secret and no selector argument passed",
|
||||
namespace: "bigbank",
|
||||
objects: []runtime.Object{
|
||||
secretObject("bigbank", map[string]string{
|
||||
"troubleshoot.io/kind": "support-bundle",
|
||||
}),
|
||||
},
|
||||
want: loader.NewTroubleshootKinds(),
|
||||
},
|
||||
{
|
||||
name: "multiple specs default selector",
|
||||
namespace: "bigbank",
|
||||
selectors: []string{
|
||||
"troubleshoot.sh/kind=support-bundle",
|
||||
},
|
||||
objects: []runtime.Object{
|
||||
secretObject("bigbank", map[string]string{
|
||||
"troubleshoot.io/kind": "support-bundle",
|
||||
}),
|
||||
secretObject("bigbank", map[string]string{
|
||||
"troubleshoot.io/kind": "support-bundle",
|
||||
}),
|
||||
},
|
||||
want: &loader.TroubleshootKinds{
|
||||
RedactorsV1Beta2: []troubleshootv1beta2.Redactor{theRedactor, theRedactor},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "spec in secret but different namespace",
|
||||
namespace: "bigbank",
|
||||
objects: []runtime.Object{
|
||||
secretObject("anotherbank", map[string]string{
|
||||
"troubleshoot.io/kind": "support-bundle",
|
||||
}),
|
||||
},
|
||||
want: loader.NewTroubleshootKinds(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
client := testclient.NewSimpleClientset(tt.objects...)
|
||||
got, err := LoadFromCluster(ctx, client, tt.selectors, tt.namespace)
|
||||
require.NoError(t, err)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("got = %v, want %v", testutils.AsJSON(t, got), testutils.AsJSON(t, tt.want))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func secretObject(ns string, selectors map[string]string) runtime.Object {
|
||||
return &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("secret-name-%s", uuid.New().String()),
|
||||
Namespace: ns,
|
||||
Labels: selectors,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"redactor-spec": []byte(`apiVersion: troubleshoot.sh/v1beta2
|
||||
kind: Redactor
|
||||
metadata:
|
||||
name: redact-some-content
|
||||
spec:
|
||||
redactors:
|
||||
- name: redact-text-1
|
||||
removals:
|
||||
values:
|
||||
- TEXT`),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,10 @@ import (
|
||||
|
||||
func GetTestFixture(t *testing.T, path string) string {
|
||||
t.Helper()
|
||||
p := filepath.Join("../../testdata", path)
|
||||
p := path
|
||||
if !filepath.IsAbs(path) {
|
||||
p = filepath.Join("../../testdata", path)
|
||||
}
|
||||
b, err := os.ReadFile(p)
|
||||
require.NoError(t, err)
|
||||
return string(b)
|
||||
@@ -53,10 +56,16 @@ func CreateTestFileWithData(t *testing.T, path, data string) {
|
||||
func LogJSON(t *testing.T, v interface{}) {
|
||||
t.Helper()
|
||||
|
||||
t.Log(AsJSON(t, v))
|
||||
}
|
||||
|
||||
func AsJSON(t *testing.T, v interface{}) string {
|
||||
t.Helper()
|
||||
|
||||
b, err := json.MarshalIndent(v, "", " ")
|
||||
if err != nil {
|
||||
t.Log(v)
|
||||
return fmt.Sprintf("%#v", v)
|
||||
} else {
|
||||
t.Log(string(b))
|
||||
return string(b)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ var (
|
||||
printer = message.NewPrinter(language.English)
|
||||
)
|
||||
|
||||
const legend = "Suceeded (S), eXcluded (X), Failed (F)\n"
|
||||
const legend = "Succeeded (S), eXcluded (X), Failed (F)\n"
|
||||
|
||||
// FUTURE WORK: This exporter should only be used by troubleshoot CLIs
|
||||
// until the following issue is addressed:
|
||||
|
||||
@@ -76,7 +76,7 @@ func TestExporter_GetSummary(t *testing.T) {
|
||||
},
|
||||
want: `
|
||||
============ Collectors summary =============
|
||||
Suceeded (S), eXcluded (X), Failed (F)
|
||||
Succeeded (S), eXcluded (X), Failed (F)
|
||||
=============================================
|
||||
all-logs (S) : 60,000ms
|
||||
host-os (S) : 1,000ms
|
||||
@@ -118,7 +118,7 @@ failed-collector (F) : 1ms`,
|
||||
},
|
||||
want: `
|
||||
============= Analyzers summary =============
|
||||
Suceeded (S), eXcluded (X), Failed (F)
|
||||
Succeeded (S), eXcluded (X), Failed (F)
|
||||
=============================================
|
||||
host-cpu (S) : 60,000ms
|
||||
cluster-version (S) : 1,000ms
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_HomeDir(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
env string
|
||||
dir string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "test linux/unix home directory",
|
||||
env: "HOME",
|
||||
dir: "/home/test",
|
||||
want: "/home/test",
|
||||
},
|
||||
{
|
||||
name: "test windows home directory",
|
||||
env: "USERPROFILE",
|
||||
dir: `C:\Users\test`,
|
||||
want: `C:\Users\test`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
os.Setenv(tt.env, tt.dir)
|
||||
if HomeDir() != tt.want {
|
||||
assert.Equal(t, tt.want, HomeDir())
|
||||
}
|
||||
os.Unsetenv(tt.env) // cleanup
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_IsURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
url string
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "valid url with http",
|
||||
url: "http://example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "valid url with https",
|
||||
url: "https://example.com",
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "invalid url without scheme",
|
||||
url: "example.com",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "invalid url with spaces",
|
||||
url: "http://example .com",
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "empty string",
|
||||
url: "",
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := IsURL(tt.url); got != tt.want {
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_AppName(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
in string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "simple name",
|
||||
in: "myapp",
|
||||
want: "Myapp",
|
||||
},
|
||||
{
|
||||
name: "hyphenated name",
|
||||
in: "my-app",
|
||||
want: "My App",
|
||||
},
|
||||
{
|
||||
name: "name with ai",
|
||||
in: "my-ai-app",
|
||||
want: "My AI App",
|
||||
},
|
||||
{
|
||||
name: "name with io",
|
||||
in: "my-app-io",
|
||||
want: "My App.io",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := AppName(tt.in); got != tt.want {
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_SplitYAML(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
doc string
|
||||
want []string
|
||||
}{
|
||||
{
|
||||
name: "single document",
|
||||
doc: `apiVersion: v1`,
|
||||
want: []string{`apiVersion: v1`},
|
||||
},
|
||||
{
|
||||
name: "multiple documents",
|
||||
doc: `apiVersion: v1
|
||||
---
|
||||
apiVersion: v1`,
|
||||
want: []string{`apiVersion: v1`, `apiVersion: v1`},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := SplitYAML(tt.doc); !reflect.DeepEqual(got, tt.want) {
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_EstimateNumberOfLines(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
text string
|
||||
want int
|
||||
}{
|
||||
{
|
||||
name: "no line",
|
||||
text: "",
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "single line without newline",
|
||||
text: "Hello, World!",
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
name: "single line with newline",
|
||||
text: "Hello, World!\n",
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
name: "multiple lines",
|
||||
text: "Hello,\nWorld!",
|
||||
want: 2,
|
||||
},
|
||||
{
|
||||
name: "multiple lines ending with newline",
|
||||
text: "Hello,\nWorld!\n",
|
||||
want: 2,
|
||||
},
|
||||
{
|
||||
name: "multiple lines with extra newlines",
|
||||
text: "\nHello,\nWorld!\n\n",
|
||||
want: 4,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := EstimateNumberOfLines(tt.text); got != tt.want {
|
||||
assert.Equal(t, tt.want, got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
+26
-1
@@ -1,16 +1,20 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/constants"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/multitype"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/redact"
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
"go.opentelemetry.io/otel/codes"
|
||||
@@ -18,6 +22,8 @@ import (
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
const FILE_NOT_COLLECTED = "fileNotCollected"
|
||||
|
||||
type AnalyzeResult struct {
|
||||
IsPass bool
|
||||
IsFail bool
|
||||
@@ -79,7 +85,7 @@ func HostAnalyze(
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := analyzer.Analyze(getFile)
|
||||
result, err := analyzer.Analyze(getFile, findFiles)
|
||||
if err != nil {
|
||||
return NewAnalyzeResultError(analyzer, errors.Wrap(err, "analyze"))
|
||||
}
|
||||
@@ -218,10 +224,14 @@ func getAnalyzer(analyzer *troubleshootv1beta2.Analyze) Analyzer {
|
||||
return &AnalyzePostgres{analyzer: analyzer.Postgres}
|
||||
case analyzer.Mysql != nil:
|
||||
return &AnalyzeMysql{analyzer: analyzer.Mysql}
|
||||
case analyzer.Mssql != nil:
|
||||
return &AnalyzeMssql{analyzer: analyzer.Mssql}
|
||||
case analyzer.Redis != nil:
|
||||
return &AnalyzeRedis{analyzer: analyzer.Redis}
|
||||
case analyzer.CephStatus != nil:
|
||||
return &AnalyzeCephStatus{analyzer: analyzer.CephStatus}
|
||||
case analyzer.Velero != nil:
|
||||
return &AnalyzeVelero{analyzer: analyzer.Velero}
|
||||
case analyzer.Longhorn != nil:
|
||||
return &AnalyzeLonghorn{analyzer: analyzer.Longhorn}
|
||||
case analyzer.RegistryImages != nil:
|
||||
@@ -261,3 +271,18 @@ func DedupAnalyzers(allAnalyzers []*troubleshootv1beta2.Analyze) []*troubleshoot
|
||||
}
|
||||
return finalAnalyzers
|
||||
}
|
||||
|
||||
func stripRedactedLines(yaml []byte) []byte {
|
||||
buf := bytes.NewBuffer(yaml)
|
||||
scanner := bufio.NewScanner(buf)
|
||||
|
||||
out := []byte{}
|
||||
|
||||
for scanner.Scan() {
|
||||
line := strings.ReplaceAll(scanner.Text(), redact.MASK_TEXT, "HIDDEN")
|
||||
out = append(out, []byte(line)...)
|
||||
out = append(out, '\n')
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package analyzer
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
@@ -32,7 +33,8 @@ func (a *AnalyzeClusterPodStatuses) IsExcluded() (bool, error) {
|
||||
}
|
||||
|
||||
func (a *AnalyzeClusterPodStatuses) Analyze(getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
|
||||
results, err := clusterPodStatuses(a.analyzer, findFiles)
|
||||
// findFiles is used to get the pod status and events files
|
||||
results, err := clusterPodStatuses(a.analyzer, findFiles, findFiles)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -42,7 +44,7 @@ func (a *AnalyzeClusterPodStatuses) Analyze(getFile getCollectedFileContents, fi
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChildCollectedFileContents getChildCollectedFileContents) ([]*AnalyzeResult, error) {
|
||||
func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChildCollectedFileContents getChildCollectedFileContents, getChildCollectedFileContentsEvents getChildCollectedFileContents) ([]*AnalyzeResult, error) {
|
||||
excludeFiles := []string{}
|
||||
collected, err := getChildCollectedFileContents(filepath.Join(constants.CLUSTER_RESOURCES_DIR, constants.CLUSTER_RESOURCES_PODS, "*.json"), excludeFiles)
|
||||
if err != nil {
|
||||
@@ -77,7 +79,38 @@ func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChi
|
||||
|
||||
for _, pod := range pods {
|
||||
if pod.Status.Reason == "" {
|
||||
pod.Status.Reason = k8sutil.GetPodStatusReason(&pod)
|
||||
// get pod status reason and message from the pod
|
||||
pod.Status.Reason, pod.Status.Message = k8sutil.GetPodStatusReason(&pod)
|
||||
}
|
||||
|
||||
// if the pod has no last termination message like pending or container creating, then check the pod events and get the warning messages. Errors will be logged and return empty message.
|
||||
if pod.Status.Message == "" {
|
||||
messages := []string{}
|
||||
collectedEvents, err := getChildCollectedFileContentsEvents(filepath.Join(constants.CLUSTER_RESOURCES_DIR, "events", fmt.Sprintf("%s.json", pod.Namespace)), excludeFiles)
|
||||
if err != nil {
|
||||
klog.V(2).Infof("failed to read collected events for namespace %s: %v", pod.Namespace, err)
|
||||
}
|
||||
|
||||
for _, fileContent := range collectedEvents {
|
||||
var nsEvents []corev1.Event
|
||||
if err := json.Unmarshal(fileContent, &nsEvents); err != nil {
|
||||
// try new format
|
||||
var nsEventsList corev1.EventList
|
||||
if err := json.Unmarshal(fileContent, &nsEventsList); err != nil {
|
||||
klog.V(2).Infof("failed to unmarshal events for namespace %s: %v", pod.Namespace, err)
|
||||
}
|
||||
nsEvents = nsEventsList.Items
|
||||
}
|
||||
|
||||
for _, event := range nsEvents {
|
||||
if event.InvolvedObject.Kind == "Pod" && event.InvolvedObject.Name == pod.Name && event.InvolvedObject.Namespace == pod.Namespace {
|
||||
if event.Type == "Warning" && event.Message != "" {
|
||||
messages = append(messages, event.Message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pod.Status.Message = strings.Join(messages, ". ")
|
||||
}
|
||||
|
||||
for _, outcome := range analyzer.Outcomes {
|
||||
@@ -149,7 +182,12 @@ func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChi
|
||||
}
|
||||
|
||||
if r.Message == "" {
|
||||
r.Message = "Pod {{ .Namespace }}/{{ .Name }} status is {{ .Status.Reason }}"
|
||||
r.Message = "Pod {{ .Namespace }}/{{ .Name }} status is {{ .Status.Reason }}. Message is: {{ .Status.Message }}"
|
||||
}
|
||||
|
||||
// if the pod has no status message, set it to None
|
||||
if pod.Status.Message == "" {
|
||||
pod.Status.Message = "None"
|
||||
}
|
||||
|
||||
tmpl := template.New("pod")
|
||||
@@ -176,7 +214,7 @@ func clusterPodStatuses(analyzer *troubleshootv1beta2.ClusterPodStatuses, getChi
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to execute template")
|
||||
}
|
||||
r.Message = m.String()
|
||||
r.Message = strings.TrimSpace(m.String())
|
||||
|
||||
// add to results, break and check the next pod
|
||||
allResults = append(allResults, &r)
|
||||
|
||||
@@ -15,6 +15,7 @@ func Test_ClusterPodStatuses(t *testing.T) {
|
||||
analyzer troubleshootv1beta2.ClusterPodStatuses
|
||||
expectResult []*AnalyzeResult
|
||||
files map[string][]byte
|
||||
eventFiles map[string][]byte
|
||||
}{
|
||||
{
|
||||
name: "pass_when_all_pods_are_healthy_in_specific_namespace",
|
||||
@@ -374,6 +375,295 @@ func Test_ClusterPodStatuses(t *testing.T) {
|
||||
"cluster-resources/pods/other-unhealthy.json": []byte(otherPodsUnhealthy),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_pending_pods_with_wrong_node_affinity",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_pending_pods_with_wrong_node_affinity",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-pending-node-affinity"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_pending_pods_with_wrong_node_affinity",
|
||||
Message: "A Pod, kotsadm-b6cb54c8f-zgzrn, is unhealthy with a status of: Pending. Message is: 0/1 nodes are available: 1 node(s) didn't match Pod's node affinity/selector. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling.",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-pending-node-affinity",
|
||||
Name: "kotsadm-b6cb54c8f-zgzrn",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-pending-node-affinity.json": []byte(messagePendingNodeAffinity),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_container_creating_pod_with_failed_mount",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_container_creating_pod_with_failed_mount",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-container-creating-failed-mount"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_container_creating_pod_with_failed_mount",
|
||||
Message: "A Pod, troubleshoot-copyfromhost-4m79m-psdjm, is unhealthy with a status of: ContainerCreating. Message is: MountVolume.SetUp failed for volume \"host\" : hostPath type check failed: /var/lib/collectd is not a directory. Unable to attach or mount volumes: unmounted volumes=[host], unattached volumes=[host kube-api-access-xddvj]: timed out waiting for the condition",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-container-creating-failed-mount",
|
||||
Name: "troubleshoot-copyfromhost-4m79m-psdjm",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-container-creating-failed-mount.json": []byte(messageContainerCreatingFailedMount),
|
||||
},
|
||||
eventFiles: map[string][]byte{
|
||||
"cluster-resources/events/message-container-creating-failed-mount.json": []byte(messageContainerCreatingFailedMountEvents),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_pod_crashloop_backoff",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_pod_crashloop_backoff",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-pod-crashloop-backoff"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_pod_crashloop_backoff",
|
||||
Message: "A Pod, init-demo, is unhealthy with a status of: CrashLoopBackOff. Message is: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-pod-crashloop-backoff",
|
||||
Name: "init-demo",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-pod-crashloop-backoff.json": []byte(messagePodCrashLoopBackOff),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_init_pod_crashloop_backoff",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_init_pod_crashloop_backoff",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-pod-init-crashloop-backoff"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_init_pod_crashloop_backoff",
|
||||
Message: "A Pod, init-demo2, is unhealthy with a status of: Init:RunContainerError. Message is: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-pod-init-crashloop-backoff",
|
||||
Name: "init-demo2",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-pod-init-crashloop-backoff.json": []byte(messagePodInitCrashLoopBackOff),
|
||||
},
|
||||
eventFiles: map[string][]byte{
|
||||
"cluster-resources/events/message-pod-init-crashloop-backoff.json": []byte(messagePodInitCrashLoopBackOffEvents),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_pending_pod_resource",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_pending_pod_resource",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-pending-pod-resources"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_pending_pod_resource",
|
||||
Message: "A Pod, pending-pod-resources-5fddcf7688-djjfc, is unhealthy with a status of: Pending. Message is: 0/1 nodes are available: 1 Insufficient nvidia.com/gpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-pending-pod-resources",
|
||||
Name: "pending-pod-resources-5fddcf7688-djjfc",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-pending-pod-resources.json": []byte(messagePendingPodResources),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_oom_killed_pod",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_oom_killed_pod",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-oomkill-pod"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_oom_killed_pod",
|
||||
Message: "A Pod, oom-kill-job3-gbb89, is unhealthy with a status of: OOMKilled. Message is: ExitCode:137",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-oomkill-pod",
|
||||
Name: "oom-kill-job3-gbb89",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-oomkill-pod.json": []byte(messageOOMKillPod),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_message_of_image_pull_fail",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_message_of_image_pull_fail",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-image-pull-fail"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_message_of_image_pull_fail",
|
||||
Message: "A Pod, no-image-deployment-849c4c4958-rxqmt, is unhealthy with a status of: ErrImagePull. Message is: Failed to pull image \"noimage.com/no-such-image\": rpc error: code = Unknown desc = Error response from daemon: Get \"https://noimage.com/v2/\": x509: certificate is not valid for any names, but wanted to match noimage.com. Error: ErrImagePull. Error: ImagePullBackOff",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-image-pull-fail",
|
||||
Name: "no-image-deployment-849c4c4958-rxqmt",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-image-pull-fail.json": []byte(messageImagePullFail),
|
||||
},
|
||||
eventFiles: map[string][]byte{
|
||||
"cluster-resources/events/message-image-pull-fail.json": []byte(messageImagePullFailEvents),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "show_none_message_of_no_events_pod",
|
||||
analyzer: troubleshootv1beta2.ClusterPodStatuses{
|
||||
AnalyzeMeta: troubleshootv1beta2.AnalyzeMeta{
|
||||
CheckName: "show_none_message_of_no_events_pod",
|
||||
},
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "!= Healthy",
|
||||
Message: "A Pod, {{ .Name }}, is unhealthy with a status of: {{ .Status.Reason }}. Message is: {{ .Status.Message }}",
|
||||
},
|
||||
},
|
||||
},
|
||||
Namespaces: []string{"message-image-pull-fail"},
|
||||
},
|
||||
expectResult: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "show_none_message_of_no_events_pod",
|
||||
Message: "A Pod, no-image-deployment-849c4c4958-rxqmt, is unhealthy with a status of: ErrImagePull. Message is: None",
|
||||
InvolvedObject: &corev1.ObjectReference{
|
||||
APIVersion: "v1",
|
||||
Kind: "Pod",
|
||||
Namespace: "message-image-pull-fail",
|
||||
Name: "no-image-deployment-849c4c4958-rxqmt",
|
||||
},
|
||||
},
|
||||
},
|
||||
files: map[string][]byte{
|
||||
"cluster-resources/pods/message-image-pull-fail.json": []byte(messageImagePullFail),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
@@ -387,7 +677,14 @@ func Test_ClusterPodStatuses(t *testing.T) {
|
||||
return test.files, nil
|
||||
}
|
||||
|
||||
actual, err := clusterPodStatuses(&test.analyzer, getFiles)
|
||||
getEventFiles := func(n string, _ []string) (map[string][]byte, error) {
|
||||
if file, ok := test.eventFiles[n]; ok {
|
||||
return map[string][]byte{n: file}, nil
|
||||
}
|
||||
return test.files, nil
|
||||
}
|
||||
|
||||
actual, err := clusterPodStatuses(&test.analyzer, getFiles, getEventFiles)
|
||||
req.NoError(err)
|
||||
req.Equal(len(test.expectResult), len(actual))
|
||||
for _, a := range actual {
|
||||
|
||||
@@ -2,10 +2,11 @@ package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
)
|
||||
|
||||
func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey string, iconURI string, readyReplicas int, exists bool, resourceType string) (*AnalyzeResult, error) {
|
||||
@@ -64,7 +65,7 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
|
||||
if exists == false && outcome.Warn.When != "absent" {
|
||||
result.IsFail = true
|
||||
result.Message = fmt.Sprintf("The %s %q was not found", resourceType, name)
|
||||
result.URI = outcome.Fail.URI
|
||||
result.URI = outcome.Warn.URI
|
||||
return result, nil
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
|
||||
if exists == false && outcome.Pass.When != "absent" {
|
||||
result.IsFail = true
|
||||
result.Message = fmt.Sprintf("The %s %q was not found", resourceType, name)
|
||||
result.URI = outcome.Fail.URI
|
||||
result.URI = outcome.Pass.URI
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -45,3 +45,33 @@ var defaultPodsUnhealthy string
|
||||
|
||||
//go:embed files/pods/other-unhealthy.json
|
||||
var otherPodsUnhealthy string
|
||||
|
||||
//go:embed files/pods/message-pending-node-affinity.json
|
||||
var messagePendingNodeAffinity string
|
||||
|
||||
//go:embed files/pods/message-container-creating-failed-mount.json
|
||||
var messageContainerCreatingFailedMount string
|
||||
|
||||
//go:embed files/events/message-container-creating-failed-mount.json
|
||||
var messageContainerCreatingFailedMountEvents string
|
||||
|
||||
//go:embed files/pods/message-pod-crashloop-backoff.json
|
||||
var messagePodCrashLoopBackOff string
|
||||
|
||||
//go:embed files/pods/message-pod-init-crashloop-backoff.json
|
||||
var messagePodInitCrashLoopBackOff string
|
||||
|
||||
//go:embed files/events/message-pod-init-crashloop-backoff.json
|
||||
var messagePodInitCrashLoopBackOffEvents string
|
||||
|
||||
//go:embed files/pods/message-pending-pod-resources.json
|
||||
var messagePendingPodResources string
|
||||
|
||||
//go:embed files/pods/message-oomkill-pod.json
|
||||
var messageOOMKillPod string
|
||||
|
||||
//go:embed files/pods/message-image-pull-fail.json
|
||||
var messageImagePullFail string
|
||||
|
||||
//go:embed files/events/message-image-pull-fail.json
|
||||
var messageImagePullFailEvents string
|
||||
|
||||
@@ -26,6 +26,7 @@ type providers struct {
|
||||
minikube bool
|
||||
rke2 bool
|
||||
k3s bool
|
||||
oke bool
|
||||
}
|
||||
|
||||
type Provider int
|
||||
@@ -45,6 +46,7 @@ const (
|
||||
minikube Provider = iota
|
||||
rke2 Provider = iota
|
||||
k3s Provider = iota
|
||||
oke Provider = iota
|
||||
)
|
||||
|
||||
type AnalyzeDistribution struct {
|
||||
@@ -125,6 +127,11 @@ func ParseNodesForProviders(nodes []corev1.Node) (providers, string) {
|
||||
foundProviders.k3s = true
|
||||
stringProvider = "k3s"
|
||||
}
|
||||
if k == "oci.oraclecloud.com/fault-domain" {
|
||||
// Based on: https://docs.oracle.com/en-us/iaas/Content/ContEng/Reference/contengsupportedlabelsusecases.htm
|
||||
foundProviders.oke = true
|
||||
stringProvider = "oke"
|
||||
}
|
||||
}
|
||||
|
||||
for k := range node.ObjectMeta.Annotations {
|
||||
@@ -326,6 +333,8 @@ func compareDistributionConditionalToActual(conditional string, actual providers
|
||||
isMatch = actual.rke2
|
||||
case k3s:
|
||||
isMatch = actual.k3s
|
||||
case oke:
|
||||
isMatch = actual.oke
|
||||
}
|
||||
|
||||
switch parts[0] {
|
||||
@@ -366,6 +375,8 @@ func mustNormalizeDistributionName(raw string) Provider {
|
||||
return rke2
|
||||
case "k3s":
|
||||
return k3s
|
||||
case "oke":
|
||||
return oke
|
||||
}
|
||||
|
||||
return unknown
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,913 @@
|
||||
{
|
||||
"kind": "EventList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "986840"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b96096f009dd",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "3b134296-43f6-4228-9c98-aeb622fb0a9a",
|
||||
"resourceVersion": "986732",
|
||||
"creationTimestamp": "2023-07-11T05:34:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T05:34:44Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986727"
|
||||
},
|
||||
"reason": "Scheduled",
|
||||
"message": "Successfully assigned default/no-image-deployment-849c4c4958-rxqmt to minikube",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Normal",
|
||||
"eventTime": "2023-07-11T05:34:44.764227Z",
|
||||
"action": "Binding",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b960b6f1e0ea",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "e5ea1f55-0d14-4443-8f79-d5b6ef692f61",
|
||||
"resourceVersion": "986820",
|
||||
"creationTimestamp": "2023-07-11T05:34:45Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:11Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986730",
|
||||
"fieldPath": "spec.containers{demo-deployment-container}"
|
||||
},
|
||||
"reason": "Pulling",
|
||||
"message": "Pulling image \"noimage.com/no-such-image\"",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:45Z",
|
||||
"lastTimestamp": "2023-07-11T05:36:11Z",
|
||||
"count": 4,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b960f12b4918",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "4ed0acd0-b3a2-477c-bb33-0e14512f5dd8",
|
||||
"resourceVersion": "986821",
|
||||
"creationTimestamp": "2023-07-11T05:34:46Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:12Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986730",
|
||||
"fieldPath": "spec.containers{demo-deployment-container}"
|
||||
},
|
||||
"reason": "Failed",
|
||||
"message": "Failed to pull image \"noimage.com/no-such-image\": rpc error: code = Unknown desc = Error response from daemon: Get \"https://noimage.com/v2/\": x509: certificate is not valid for any names, but wanted to match noimage.com",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:46Z",
|
||||
"lastTimestamp": "2023-07-11T05:36:12Z",
|
||||
"count": 4,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b960f12bd46b",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "4a66c16a-b2ee-4345-8de6-028936861f03",
|
||||
"resourceVersion": "986822",
|
||||
"creationTimestamp": "2023-07-11T05:34:46Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:12Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986730",
|
||||
"fieldPath": "spec.containers{demo-deployment-container}"
|
||||
},
|
||||
"reason": "Failed",
|
||||
"message": "Error: ErrImagePull",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:46Z",
|
||||
"lastTimestamp": "2023-07-11T05:36:12Z",
|
||||
"count": 4,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b960fa64918a",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "0b4b988c-faf5-447a-bb2e-367b627152dc",
|
||||
"resourceVersion": "986833",
|
||||
"creationTimestamp": "2023-07-11T05:34:46Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986730",
|
||||
"fieldPath": "spec.containers{demo-deployment-container}"
|
||||
},
|
||||
"reason": "BackOff",
|
||||
"message": "Back-off pulling image \"noimage.com/no-such-image\"",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:46Z",
|
||||
"lastTimestamp": "2023-07-11T05:36:25Z",
|
||||
"count": 5,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt.1770b960fa64bb88",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "eae7cb57-316e-4dc7-8e3a-45c01ca369a5",
|
||||
"resourceVersion": "986835",
|
||||
"creationTimestamp": "2023-07-11T05:34:46Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "986730",
|
||||
"fieldPath": "spec.containers{demo-deployment-container}"
|
||||
},
|
||||
"reason": "Failed",
|
||||
"message": "Error: ImagePullBackOff",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:46Z",
|
||||
"lastTimestamp": "2023-07-11T05:36:25Z",
|
||||
"count": 5,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958.1770b96096c622fa",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "55bc2a37-2ff2-4a17-a29d-c3eab878e353",
|
||||
"resourceVersion": "986728",
|
||||
"creationTimestamp": "2023-07-11T05:34:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:34:44Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "ReplicaSet",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment-849c4c4958",
|
||||
"uid": "d992c1a5-d2c4-4065-ac5b-3bb893f9000a",
|
||||
"apiVersion": "apps/v1",
|
||||
"resourceVersion": "986723"
|
||||
},
|
||||
"reason": "SuccessfulCreate",
|
||||
"message": "Created pod: no-image-deployment-849c4c4958-rxqmt",
|
||||
"source": {
|
||||
"component": "replicaset-controller"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:44Z",
|
||||
"lastTimestamp": "2023-07-11T05:34:44Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment.1770b96096492cbe",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "3feddf40-caa5-45f9-9d8b-bc24796d508f",
|
||||
"resourceVersion": "986725",
|
||||
"creationTimestamp": "2023-07-11T05:34:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:34:44Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Deployment",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "no-image-deployment",
|
||||
"uid": "abe37ef6-38c5-4f29-a956-f79def48c342",
|
||||
"apiVersion": "apps/v1",
|
||||
"resourceVersion": "986722"
|
||||
},
|
||||
"reason": "ScalingReplicaSet",
|
||||
"message": "Scaled up replica set no-image-deployment-849c4c4958 to 1",
|
||||
"source": {
|
||||
"component": "deployment-controller"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T05:34:44Z",
|
||||
"lastTimestamp": "2023-07-11T05:34:44Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89.1770b6922c75433d",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "3cfa33ed-cedc-4fa3-a9b7-aa657048784a",
|
||||
"resourceVersion": "984536",
|
||||
"creationTimestamp": "2023-07-11T04:43:19Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T04:43:19Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984532"
|
||||
},
|
||||
"reason": "Scheduled",
|
||||
"message": "Successfully assigned default/oom-kill-job3-gbb89 to minikube",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Normal",
|
||||
"eventTime": "2023-07-11T04:43:19.191283Z",
|
||||
"action": "Binding",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89.1770b6924d361854",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "695da2fb-7e2f-4c20-b60a-9a4cd3b1b60e",
|
||||
"resourceVersion": "984539",
|
||||
"creationTimestamp": "2023-07-11T04:43:19Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:19Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984533",
|
||||
"fieldPath": "spec.containers{memory-eater}"
|
||||
},
|
||||
"reason": "Pulling",
|
||||
"message": "Pulling image \"us-central1-docker.pkg.dev/genuine-flight-317411/devel/memory-eater:1.0\"",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:19Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:19Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89.1770b6939d446433",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "b7ddf622-f531-4822-bdb2-46f6e27218ae",
|
||||
"resourceVersion": "984544",
|
||||
"creationTimestamp": "2023-07-11T04:43:25Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984533",
|
||||
"fieldPath": "spec.containers{memory-eater}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"us-central1-docker.pkg.dev/genuine-flight-317411/devel/memory-eater:1.0\" in 5.638046961s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:25Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:25Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89.1770b6939f884130",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "84e0a635-a3b8-4cdc-b439-a71454e7d7d5",
|
||||
"resourceVersion": "984545",
|
||||
"creationTimestamp": "2023-07-11T04:43:25Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984533",
|
||||
"fieldPath": "spec.containers{memory-eater}"
|
||||
},
|
||||
"reason": "Created",
|
||||
"message": "Created container memory-eater",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:25Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:25Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89.1770b693a39538e4",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "a15333ad-0390-4325-8880-34ef36508831",
|
||||
"resourceVersion": "984546",
|
||||
"creationTimestamp": "2023-07-11T04:43:25Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984533",
|
||||
"fieldPath": "spec.containers{memory-eater}"
|
||||
},
|
||||
"reason": "Started",
|
||||
"message": "Started container memory-eater",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:25Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:25Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3.1770b6922c53f55c",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "db095cdc-df52-490d-a308-9b283f99eaa6",
|
||||
"resourceVersion": "984534",
|
||||
"creationTimestamp": "2023-07-11T04:43:19Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:19Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Job",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3",
|
||||
"uid": "a85295e8-54e4-40a4-aeb0-b47c19f1a69f",
|
||||
"apiVersion": "batch/v1",
|
||||
"resourceVersion": "984531"
|
||||
},
|
||||
"reason": "SuccessfulCreate",
|
||||
"message": "Created pod: oom-kill-job3-gbb89",
|
||||
"source": {
|
||||
"component": "job-controller"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:19Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:19Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3.1770b6944e3d254b",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "fb3ea640-2484-44d5-b65d-698d8e5bd3db",
|
||||
"resourceVersion": "984553",
|
||||
"creationTimestamp": "2023-07-11T04:43:28Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:28Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Job",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "oom-kill-job3",
|
||||
"uid": "a85295e8-54e4-40a4-aeb0-b47c19f1a69f",
|
||||
"apiVersion": "batch/v1",
|
||||
"resourceVersion": "984551"
|
||||
},
|
||||
"reason": "BackoffLimitExceeded",
|
||||
"message": "Job has reached the specified backoff limit",
|
||||
"source": {
|
||||
"component": "job-controller"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:43:28Z",
|
||||
"lastTimestamp": "2023-07-11T04:43:28Z",
|
||||
"count": 1,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "pending-pod-resources-5fddcf7688-djjfc.1770b59c8b866b56",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "64330c31-0f5e-46f3-8fb6-ffdac523bb77",
|
||||
"resourceVersion": "984662",
|
||||
"creationTimestamp": "2023-07-11T04:25:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T04:46:01Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:series": {
|
||||
".": {},
|
||||
"f:count": {},
|
||||
"f:lastObservedTime": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "pending-pod-resources-5fddcf7688-djjfc",
|
||||
"uid": "e4d4c4cc-2c41-4ab7-b41c-9c8b28ded451",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "983556"
|
||||
},
|
||||
"reason": "FailedScheduling",
|
||||
"message": "0/1 nodes are available: 1 Insufficient nvidia.com/gpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod.",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Warning",
|
||||
"eventTime": "2023-07-11T04:25:44.224298Z",
|
||||
"series": {
|
||||
"count": 3,
|
||||
"lastObservedTime": "2023-07-11T04:40:44.264058Z"
|
||||
},
|
||||
"action": "Scheduling",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "pending-pod-resources-5fddcf7688-djjfc.1770b68fb368b5a6",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "369454df-c891-4e76-96b9-ebdaabe2a6a6",
|
||||
"resourceVersion": "984523",
|
||||
"creationTimestamp": "2023-07-11T04:43:08Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T04:43:08Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"name": "pending-pod-resources-5fddcf7688-djjfc",
|
||||
"uid": "e4d4c4cc-2c41-4ab7-b41c-9c8b28ded451",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "984521"
|
||||
},
|
||||
"reason": "FailedScheduling",
|
||||
"message": "skip schedule deleting pod: default/pending-pod-resources-5fddcf7688-djjfc",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Warning",
|
||||
"eventTime": "2023-07-11T04:43:08.570490Z",
|
||||
"action": "Scheduling",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,928 @@
|
||||
{
|
||||
"kind": "EventList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "982712"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2a98cf7b53c",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "cfdfe0af-6dc5-4c6c-a3be-f1532d424ab4",
|
||||
"resourceVersion": "981383",
|
||||
"creationTimestamp": "2023-07-11T03:31:41Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T03:31:41Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981381"
|
||||
},
|
||||
"reason": "Scheduled",
|
||||
"message": "Successfully assigned default/init-demo to minikube",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Normal",
|
||||
"eventTime": "2023-07-11T03:31:41.548190Z",
|
||||
"action": "Binding",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2a9adf25515",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "091c0f14-75df-47e6-af31-309d8a0b0b86",
|
||||
"resourceVersion": "981479",
|
||||
"creationTimestamp": "2023-07-11T03:31:42Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:33:12Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulling",
|
||||
"message": "Pulling image \"nginx\"",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:31:42Z",
|
||||
"lastTimestamp": "2023-07-11T03:33:12Z",
|
||||
"count": 5,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2aa4adc35a4",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "740be04d-5aa8-4bce-ace3-ec61e4d229e0",
|
||||
"resourceVersion": "981389",
|
||||
"creationTimestamp": "2023-07-11T03:31:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:31:44Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"nginx\" in 2.633289584s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:31:44Z",
|
||||
"lastTimestamp": "2023-07-11T03:31:44Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2aa4cbb718f",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "a158f7ff-6b95-45db-ac28-2d02ba1d8ca0",
|
||||
"resourceVersion": "981483",
|
||||
"creationTimestamp": "2023-07-11T03:31:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:33:15Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Created",
|
||||
"message": "Created container nginx",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:31:44Z",
|
||||
"lastTimestamp": "2023-07-11T03:33:15Z",
|
||||
"count": 5,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2aa50edfd38",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "0fc24955-49dd-4c16-8c7b-c4a3316b1f9d",
|
||||
"resourceVersion": "981484",
|
||||
"creationTimestamp": "2023-07-11T03:31:44Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:33:15Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Failed",
|
||||
"message": "Error: failed to start container \"nginx\": Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:31:44Z",
|
||||
"lastTimestamp": "2023-07-11T03:33:15Z",
|
||||
"count": 5,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2aae7fb3f76",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "3c489943-7de7-4a1b-a108-1e9d55a2d6a7",
|
||||
"resourceVersion": "981396",
|
||||
"creationTimestamp": "2023-07-11T03:31:47Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:31:47Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"nginx\" in 1.952280959s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:31:47Z",
|
||||
"lastTimestamp": "2023-07-11T03:31:47Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2ae5cec9549",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "793ce261-4cb0-4b2a-9c97-fe1924e534e3",
|
||||
"resourceVersion": "981413",
|
||||
"creationTimestamp": "2023-07-11T03:32:02Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:32:02Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"nginx\" in 2.228363585s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:32:02Z",
|
||||
"lastTimestamp": "2023-07-11T03:32:02Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2b1917b81fa",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "2dbed976-4a5d-42f8-8cd7-8778f2382b7a",
|
||||
"resourceVersion": "982495",
|
||||
"creationTimestamp": "2023-07-11T03:32:15Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:56:47Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "BackOff",
|
||||
"message": "Back-off restarting failed container",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:32:15Z",
|
||||
"lastTimestamp": "2023-07-11T03:56:47Z",
|
||||
"count": 111,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2b3b6fab35b",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "f3d43cf2-f8b7-428a-b834-4826603b414c",
|
||||
"resourceVersion": "981439",
|
||||
"creationTimestamp": "2023-07-11T03:32:25Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:32:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"nginx\" in 2.117272501s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:32:25Z",
|
||||
"lastTimestamp": "2023-07-11T03:32:25Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo.1770b2bf5bb3f082",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "f9f3da46-c519-43b0-9721-07113e30e2e3",
|
||||
"resourceVersion": "981482",
|
||||
"creationTimestamp": "2023-07-11T03:33:15Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:33:15Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "981382",
|
||||
"fieldPath": "spec.containers{nginx}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Successfully pulled image \"nginx\" in 2.219218792s",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T03:33:15Z",
|
||||
"lastTimestamp": "2023-07-11T03:33:15Z",
|
||||
"count": 1,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2.1770b446b3f016ce",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "12009dc6-123f-488f-9b1f-412930c8d28d",
|
||||
"resourceVersion": "982692",
|
||||
"creationTimestamp": "2023-07-11T04:01:16Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "events.k8s.io/v1",
|
||||
"time": "2023-07-11T04:01:16Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:action": {},
|
||||
"f:eventTime": {},
|
||||
"f:note": {},
|
||||
"f:reason": {},
|
||||
"f:regarding": {},
|
||||
"f:reportingController": {},
|
||||
"f:reportingInstance": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo2",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "982690"
|
||||
},
|
||||
"reason": "Scheduled",
|
||||
"message": "Successfully assigned default/init-demo2 to minikube",
|
||||
"source": {},
|
||||
"firstTimestamp": null,
|
||||
"lastTimestamp": null,
|
||||
"type": "Normal",
|
||||
"eventTime": "2023-07-11T04:01:16.023486Z",
|
||||
"action": "Binding",
|
||||
"reportingComponent": "default-scheduler",
|
||||
"reportingInstance": "default-scheduler-minikube"
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2.1770b446d40953ed",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "a5ffd925-1612-4178-b5ce-02e981500ee5",
|
||||
"resourceVersion": "982698",
|
||||
"creationTimestamp": "2023-07-11T04:01:16Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:16Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo2",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "982691",
|
||||
"fieldPath": "spec.initContainers{install}"
|
||||
},
|
||||
"reason": "Pulled",
|
||||
"message": "Container image \"busybox:1.28\" already present on machine",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:01:16Z",
|
||||
"lastTimestamp": "2023-07-11T04:01:16Z",
|
||||
"count": 2,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2.1770b446d5539074",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "f431bae6-64fb-47ba-81ee-ab4f32122024",
|
||||
"resourceVersion": "982700",
|
||||
"creationTimestamp": "2023-07-11T04:01:16Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:16Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo2",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "982691",
|
||||
"fieldPath": "spec.initContainers{install}"
|
||||
},
|
||||
"reason": "Created",
|
||||
"message": "Created container install",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:01:16Z",
|
||||
"lastTimestamp": "2023-07-11T04:01:16Z",
|
||||
"count": 2,
|
||||
"type": "Normal",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2.1770b446d9b392f2",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "9e237187-eb36-4f2d-a139-3c5c450a75e9",
|
||||
"resourceVersion": "982701",
|
||||
"creationTimestamp": "2023-07-11T04:01:16Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:17Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo2",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "982691",
|
||||
"fieldPath": "spec.initContainers{install}"
|
||||
},
|
||||
"reason": "Failed",
|
||||
"message": "Error: failed to start container \"install\": Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:01:16Z",
|
||||
"lastTimestamp": "2023-07-11T04:01:17Z",
|
||||
"count": 2,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2.1770b448549c898a",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "44c503f2-0bd9-46ad-81be-9c2626d3bdf3",
|
||||
"resourceVersion": "982706",
|
||||
"creationTimestamp": "2023-07-11T04:01:23Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:23Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "init-demo2",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "982691",
|
||||
"fieldPath": "spec.initContainers{install}"
|
||||
},
|
||||
"reason": "BackOff",
|
||||
"message": "Back-off restarting failed container",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-11T04:01:23Z",
|
||||
"lastTimestamp": "2023-07-11T04:01:23Z",
|
||||
"count": 1,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "troubleshoot-copyfromhost-4m79m-psdjm.177058280d4c0493",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "380bec72-7cfd-4a00-85ff-8725c9fc28f9",
|
||||
"resourceVersion": "981372",
|
||||
"creationTimestamp": "2023-07-09T23:53:09Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:31:29Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "troubleshoot-copyfromhost-4m79m-psdjm",
|
||||
"uid": "55ca5d14-2541-42a9-9eb1-5eb53133e178",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "938779"
|
||||
},
|
||||
"reason": "FailedMount",
|
||||
"message": "MountVolume.SetUp failed for volume \"host\" : hostPath type check failed: /var/lib/collectd is not a directory",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-09T23:53:09Z",
|
||||
"lastTimestamp": "2023-07-11T03:31:29Z",
|
||||
"count": 490,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
},
|
||||
{
|
||||
"kind": "Event",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "troubleshoot-copyfromhost-4m79m-psdjm.17705863d9fdab48",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "bab0a7d9-61a5-43a1-813c-ed2d050aee34",
|
||||
"resourceVersion": "981185",
|
||||
"creationTimestamp": "2023-07-09T23:57:26Z",
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:27:03Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:count": {},
|
||||
"f:firstTimestamp": {},
|
||||
"f:involvedObject": {},
|
||||
"f:lastTimestamp": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:source": {
|
||||
"f:component": {},
|
||||
"f:host": {}
|
||||
},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"involvedObject": {
|
||||
"kind": "Pod",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"name": "troubleshoot-copyfromhost-4m79m-psdjm",
|
||||
"uid": "55ca5d14-2541-42a9-9eb1-5eb53133e178",
|
||||
"apiVersion": "v1",
|
||||
"resourceVersion": "938779"
|
||||
},
|
||||
"reason": "FailedMount",
|
||||
"message": "Unable to attach or mount volumes: unmounted volumes=[host], unattached volumes=[host kube-api-access-xddvj]: timed out waiting for the condition",
|
||||
"source": {
|
||||
"component": "kubelet",
|
||||
"host": "minikube"
|
||||
},
|
||||
"firstTimestamp": "2023-07-09T23:57:26Z",
|
||||
"lastTimestamp": "2023-07-11T03:27:03Z",
|
||||
"count": 324,
|
||||
"type": "Warning",
|
||||
"eventTime": null,
|
||||
"reportingComponent": "",
|
||||
"reportingInstance": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "954528"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "troubleshoot-copyfromhost-4m79m-psdjm",
|
||||
"generateName": "troubleshoot-copyfromhost-4m79m-",
|
||||
"namespace": "message-container-creating-failed-mount",
|
||||
"uid": "55ca5d14-2541-42a9-9eb1-5eb53133e178",
|
||||
"resourceVersion": "938782",
|
||||
"creationTimestamp": "2023-07-09T23:53:09Z",
|
||||
"labels": {
|
||||
"app.kubernetes.io/managed-by": "troubleshoot.sh",
|
||||
"controller-revision-hash": "54b4f4f449",
|
||||
"pod-template-generation": "1",
|
||||
"troubleshoot.sh/collector": "copyfromhost",
|
||||
"troubleshoot.sh/copyfromhost-id": "2SAoFNhXU68STgniojM3fJcNQig"
|
||||
},
|
||||
"ownerReferences": [
|
||||
{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "DaemonSet",
|
||||
"name": "troubleshoot-copyfromhost-4m79m",
|
||||
"uid": "ed30f463-4614-41b3-b2b6-52f65e50b1d3",
|
||||
"controller": true,
|
||||
"blockOwnerDeletion": true
|
||||
}
|
||||
],
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-09T23:53:09Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:generateName": {},
|
||||
"f:labels": {
|
||||
".": {},
|
||||
"f:app.kubernetes.io/managed-by": {},
|
||||
"f:controller-revision-hash": {},
|
||||
"f:pod-template-generation": {},
|
||||
"f:troubleshoot.sh/collector": {},
|
||||
"f:troubleshoot.sh/copyfromhost-id": {}
|
||||
},
|
||||
"f:ownerReferences": {
|
||||
".": {},
|
||||
"k:{\"uid\":\"ed30f463-4614-41b3-b2b6-52f65e50b1d3\"}": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:affinity": {
|
||||
".": {},
|
||||
"f:nodeAffinity": {
|
||||
".": {},
|
||||
"f:requiredDuringSchedulingIgnoredDuringExecution": {}
|
||||
}
|
||||
},
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"collector\"}": {
|
||||
".": {},
|
||||
"f:args": {},
|
||||
"f:command": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:resources": {},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {},
|
||||
"f:volumeMounts": {
|
||||
".": {},
|
||||
"k:{\"mountPath\":\"/host\"}": {
|
||||
".": {},
|
||||
"f:mountPath": {},
|
||||
"f:name": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {},
|
||||
"f:tolerations": {},
|
||||
"f:volumes": {
|
||||
".": {},
|
||||
"k:{\"name\":\"host\"}": {
|
||||
".": {},
|
||||
"f:hostPath": {
|
||||
".": {},
|
||||
"f:path": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"f:name": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-09T23:53:09Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
"k:{\"type\":\"ContainersReady\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Initialized\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Ready\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
},
|
||||
"f:containerStatuses": {},
|
||||
"f:hostIP": {},
|
||||
"f:startTime": {}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "host",
|
||||
"hostPath": {
|
||||
"path": "/var/lib/collectd",
|
||||
"type": "Directory"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "kube-api-access-xddvj",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "collector",
|
||||
"image": "alpine",
|
||||
"command": [
|
||||
"sleep"
|
||||
],
|
||||
"args": [
|
||||
"1000000"
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "host",
|
||||
"mountPath": "/host"
|
||||
},
|
||||
{
|
||||
"name": "kube-api-access-xddvj",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "IfNotPresent"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"nodeName": "minikube",
|
||||
"securityContext": {},
|
||||
"affinity": {
|
||||
"nodeAffinity": {
|
||||
"requiredDuringSchedulingIgnoredDuringExecution": {
|
||||
"nodeSelectorTerms": [
|
||||
{
|
||||
"matchFields": [
|
||||
{
|
||||
"key": "metadata.name",
|
||||
"operator": "In",
|
||||
"values": [
|
||||
"minikube"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node-role.kubernetes.io/master",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
},
|
||||
{
|
||||
"key": "node-role.kubernetes.io/control-plane",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/disk-pressure",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/memory-pressure",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/pid-pressure",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unschedulable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoSchedule"
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Pending",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Initialized",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-09T23:53:09Z"
|
||||
},
|
||||
{
|
||||
"type": "Ready",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-09T23:53:09Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [collector]"
|
||||
},
|
||||
{
|
||||
"type": "ContainersReady",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-09T23:53:09Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [collector]"
|
||||
},
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-09T23:53:09Z"
|
||||
}
|
||||
],
|
||||
"hostIP": "192.168.49.2",
|
||||
"startTime": "2023-07-09T23:53:09Z",
|
||||
"containerStatuses": [
|
||||
{
|
||||
"name": "collector",
|
||||
"state": {
|
||||
"waiting": {
|
||||
"reason": "ContainerCreating"
|
||||
}
|
||||
},
|
||||
"lastState": {},
|
||||
"ready": false,
|
||||
"restartCount": 0,
|
||||
"image": "alpine",
|
||||
"imageID": "",
|
||||
"started": false
|
||||
}
|
||||
],
|
||||
"qosClass": "BestEffort"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "986839"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "no-image-deployment-849c4c4958-rxqmt",
|
||||
"generateName": "no-image-deployment-849c4c4958-",
|
||||
"namespace": "message-image-pull-fail",
|
||||
"uid": "209076ce-26d6-4836-981b-8c05cb0081eb",
|
||||
"resourceVersion": "986834",
|
||||
"creationTimestamp": "2023-07-11T05:34:44Z",
|
||||
"labels": {
|
||||
"app": "no-image-deployment",
|
||||
"pod-template-hash": "849c4c4958",
|
||||
"visualize": "true"
|
||||
},
|
||||
"ownerReferences": [
|
||||
{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "ReplicaSet",
|
||||
"name": "no-image-deployment-849c4c4958",
|
||||
"uid": "d992c1a5-d2c4-4065-ac5b-3bb893f9000a",
|
||||
"controller": true,
|
||||
"blockOwnerDeletion": true
|
||||
}
|
||||
],
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:34:44Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:generateName": {},
|
||||
"f:labels": {
|
||||
".": {},
|
||||
"f:app": {},
|
||||
"f:pod-template-hash": {},
|
||||
"f:visualize": {}
|
||||
},
|
||||
"f:ownerReferences": {
|
||||
".": {},
|
||||
"k:{\"uid\":\"d992c1a5-d2c4-4065-ac5b-3bb893f9000a\"}": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"demo-deployment-container\"}": {
|
||||
".": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:resources": {},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T05:36:25Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
"k:{\"type\":\"ContainersReady\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Initialized\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Ready\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
},
|
||||
"f:containerStatuses": {},
|
||||
"f:hostIP": {},
|
||||
"f:podIP": {},
|
||||
"f:podIPs": {
|
||||
".": {},
|
||||
"k:{\"ip\":\"172.17.0.3\"}": {
|
||||
".": {},
|
||||
"f:ip": {}
|
||||
}
|
||||
},
|
||||
"f:startTime": {}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "kube-api-access-5p7hr",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "demo-deployment-container",
|
||||
"image": "noimage.com/no-such-image",
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "kube-api-access-5p7hr",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "IfNotPresent"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"nodeName": "minikube",
|
||||
"securityContext": {},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Pending",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Initialized",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T05:34:44Z"
|
||||
},
|
||||
{
|
||||
"type": "Ready",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T05:34:44Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [demo-deployment-container]"
|
||||
},
|
||||
{
|
||||
"type": "ContainersReady",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T05:34:44Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [demo-deployment-container]"
|
||||
},
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T05:34:44Z"
|
||||
}
|
||||
],
|
||||
"hostIP": "192.168.49.2",
|
||||
"podIP": "172.17.0.3",
|
||||
"podIPs": [
|
||||
{
|
||||
"ip": "172.17.0.3"
|
||||
}
|
||||
],
|
||||
"startTime": "2023-07-11T05:34:44Z",
|
||||
"containerStatuses": [
|
||||
{
|
||||
"name": "demo-deployment-container",
|
||||
"state": {
|
||||
"waiting": {
|
||||
"reason": "ErrImagePull",
|
||||
"message": "rpc error: code = Unknown desc = Error response from daemon: Get \"https://noimage.com/v2/\": x509: certificate is not valid for any names, but wanted to match noimage.com"
|
||||
}
|
||||
},
|
||||
"lastState": {},
|
||||
"ready": false,
|
||||
"restartCount": 0,
|
||||
"image": "noimage.com/no-such-image",
|
||||
"imageID": "",
|
||||
"started": false
|
||||
}
|
||||
],
|
||||
"qosClass": "BestEffort"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,296 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "985854"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "oom-kill-job3-gbb89",
|
||||
"generateName": "oom-kill-job3-",
|
||||
"namespace": "message-oomkill-pod",
|
||||
"uid": "c8d3f094-b80c-4ff8-aff7-f0e624f1bf3a",
|
||||
"resourceVersion": "984552",
|
||||
"creationTimestamp": "2023-07-11T04:43:19Z",
|
||||
"labels": {
|
||||
"controller-uid": "a85295e8-54e4-40a4-aeb0-b47c19f1a69f",
|
||||
"job-name": "oom-kill-job3"
|
||||
},
|
||||
"ownerReferences": [
|
||||
{
|
||||
"apiVersion": "batch/v1",
|
||||
"kind": "Job",
|
||||
"name": "oom-kill-job3",
|
||||
"uid": "a85295e8-54e4-40a4-aeb0-b47c19f1a69f",
|
||||
"controller": true,
|
||||
"blockOwnerDeletion": true
|
||||
}
|
||||
],
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:19Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:generateName": {},
|
||||
"f:labels": {
|
||||
".": {},
|
||||
"f:controller-uid": {},
|
||||
"f:job-name": {}
|
||||
},
|
||||
"f:ownerReferences": {
|
||||
".": {},
|
||||
"k:{\"uid\":\"a85295e8-54e4-40a4-aeb0-b47c19f1a69f\"}": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"memory-eater\"}": {
|
||||
".": {},
|
||||
"f:args": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:resources": {
|
||||
".": {},
|
||||
"f:limits": {
|
||||
".": {},
|
||||
"f:memory": {}
|
||||
},
|
||||
"f:requests": {
|
||||
".": {},
|
||||
"f:memory": {}
|
||||
}
|
||||
},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:43:28Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
"k:{\"type\":\"ContainersReady\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Initialized\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Ready\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
},
|
||||
"f:containerStatuses": {},
|
||||
"f:hostIP": {},
|
||||
"f:phase": {},
|
||||
"f:podIP": {},
|
||||
"f:podIPs": {
|
||||
".": {},
|
||||
"k:{\"ip\":\"172.17.0.3\"}": {
|
||||
".": {},
|
||||
"f:ip": {}
|
||||
}
|
||||
},
|
||||
"f:startTime": {}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "kube-api-access-rbt47",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "memory-eater",
|
||||
"image": "us-central1-docker.pkg.dev/genuine-flight-317411/devel/memory-eater:1.0",
|
||||
"args": [
|
||||
"75Mi",
|
||||
"0",
|
||||
"30Mi",
|
||||
"80",
|
||||
"1"
|
||||
],
|
||||
"resources": {
|
||||
"limits": {
|
||||
"memory": "100Mi"
|
||||
},
|
||||
"requests": {
|
||||
"memory": "100Mi"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "kube-api-access-rbt47",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "Always"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Never",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"nodeName": "minikube",
|
||||
"securityContext": {},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Failed",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Initialized",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:43:19Z"
|
||||
},
|
||||
{
|
||||
"type": "Ready",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:43:19Z",
|
||||
"reason": "PodFailed"
|
||||
},
|
||||
{
|
||||
"type": "ContainersReady",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:43:19Z",
|
||||
"reason": "PodFailed"
|
||||
},
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:43:19Z"
|
||||
}
|
||||
],
|
||||
"hostIP": "192.168.49.2",
|
||||
"podIP": "172.17.0.3",
|
||||
"podIPs": [
|
||||
{
|
||||
"ip": "172.17.0.3"
|
||||
}
|
||||
],
|
||||
"startTime": "2023-07-11T04:43:19Z",
|
||||
"containerStatuses": [
|
||||
{
|
||||
"name": "memory-eater",
|
||||
"state": {
|
||||
"terminated": {
|
||||
"exitCode": 137,
|
||||
"reason": "OOMKilled",
|
||||
"startedAt": "2023-07-11T04:43:25Z",
|
||||
"finishedAt": "2023-07-11T04:43:25Z",
|
||||
"containerID": "docker://84d3d308bb9a5765e637884194e718d297046f156a377cf6145a9397d5e469b7"
|
||||
}
|
||||
},
|
||||
"lastState": {},
|
||||
"ready": false,
|
||||
"restartCount": 0,
|
||||
"image": "us-central1-docker.pkg.dev/genuine-flight-317411/devel/memory-eater:1.0",
|
||||
"imageID": "docker-pullable://us-central1-docker.pkg.dev/genuine-flight-317411/devel/memory-eater@sha256:b99901aacc6c87f86a767b3a0b02cdc926aae62bb4a5e7361d895f26f4773562",
|
||||
"containerID": "docker://84d3d308bb9a5765e637884194e718d297046f156a377cf6145a9397d5e469b7",
|
||||
"started": false
|
||||
}
|
||||
],
|
||||
"qosClass": "Burstable"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,223 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "984246"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "pending-pod-resources-5fddcf7688-djjfc",
|
||||
"generateName": "pending-pod-resources-5fddcf7688-",
|
||||
"namespace": "message-pending-pod-resources",
|
||||
"uid": "e4d4c4cc-2c41-4ab7-b41c-9c8b28ded451",
|
||||
"resourceVersion": "983556",
|
||||
"creationTimestamp": "2023-07-11T04:20:29Z",
|
||||
"labels": {
|
||||
"app": "pending-pod-resources",
|
||||
"pod-template-hash": "5fddcf7688"
|
||||
},
|
||||
"ownerReferences": [
|
||||
{
|
||||
"apiVersion": "apps/v1",
|
||||
"kind": "ReplicaSet",
|
||||
"name": "pending-pod-resources-5fddcf7688",
|
||||
"uid": "f57de73f-8492-4118-b4da-b0f9d7408c9b",
|
||||
"controller": true,
|
||||
"blockOwnerDeletion": true
|
||||
}
|
||||
],
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kube-controller-manager",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:20:29Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:generateName": {},
|
||||
"f:labels": {
|
||||
".": {},
|
||||
"f:app": {},
|
||||
"f:pod-template-hash": {}
|
||||
},
|
||||
"f:ownerReferences": {
|
||||
".": {},
|
||||
"k:{\"uid\":\"f57de73f-8492-4118-b4da-b0f9d7408c9b\"}": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"nginx\"}": {
|
||||
".": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:resources": {
|
||||
".": {},
|
||||
"f:limits": {
|
||||
".": {},
|
||||
"f:cpu": {},
|
||||
"f:memory": {},
|
||||
"f:nvidia.com/gpu": {}
|
||||
},
|
||||
"f:requests": {
|
||||
".": {},
|
||||
"f:cpu": {},
|
||||
"f:memory": {},
|
||||
"f:nvidia.com/gpu": {}
|
||||
}
|
||||
},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kube-scheduler",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:20:29Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
".": {},
|
||||
"k:{\"type\":\"PodScheduled\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "kube-api-access-sjnlv",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx",
|
||||
"resources": {
|
||||
"limits": {
|
||||
"cpu": "3",
|
||||
"memory": "5Gi",
|
||||
"nvidia.com/gpu": "5"
|
||||
},
|
||||
"requests": {
|
||||
"cpu": "3",
|
||||
"memory": "5Gi",
|
||||
"nvidia.com/gpu": "5"
|
||||
}
|
||||
},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "kube-api-access-sjnlv",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "IfNotPresent"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"securityContext": {},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Pending",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:20:29Z",
|
||||
"reason": "Unschedulable",
|
||||
"message": "0/1 nodes are available: 1 Insufficient nvidia.com/gpu. preemption: 0/1 nodes are available: 1 No preemption victims found for incoming pod."
|
||||
}
|
||||
],
|
||||
"qosClass": "Guaranteed"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "981519"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo",
|
||||
"namespace": "message-pod-crashloop-backoff",
|
||||
"uid": "8d27f35a-4b45-4752-a5db-7985ea8b38bf",
|
||||
"resourceVersion": "981491",
|
||||
"creationTimestamp": "2023-07-11T03:31:41Z",
|
||||
"annotations": {
|
||||
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"init-demo\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"command\":[\"wge\",\"-O\",\"/work-dir/index.html\",\"https://home.robusta.dev\"],\"image\":\"nginx\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}]}]}}\n"
|
||||
},
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubectl-client-side-apply",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:31:41Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:annotations": {
|
||||
".": {},
|
||||
"f:kubectl.kubernetes.io/last-applied-configuration": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"nginx\"}": {
|
||||
".": {},
|
||||
"f:command": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:ports": {
|
||||
".": {},
|
||||
"k:{\"containerPort\":80,\"protocol\":\"TCP\"}": {
|
||||
".": {},
|
||||
"f:containerPort": {},
|
||||
"f:protocol": {}
|
||||
}
|
||||
},
|
||||
"f:resources": {},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T03:33:23Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
"k:{\"type\":\"ContainersReady\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Initialized\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Ready\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
},
|
||||
"f:containerStatuses": {},
|
||||
"f:hostIP": {},
|
||||
"f:phase": {},
|
||||
"f:podIP": {},
|
||||
"f:podIPs": {
|
||||
".": {},
|
||||
"k:{\"ip\":\"172.17.0.3\"}": {
|
||||
".": {},
|
||||
"f:ip": {}
|
||||
}
|
||||
},
|
||||
"f:startTime": {}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "kube-api-access-htb9q",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx",
|
||||
"command": [
|
||||
"wge",
|
||||
"-O",
|
||||
"/work-dir/index.html",
|
||||
"https://home.robusta.dev"
|
||||
],
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "kube-api-access-htb9q",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "Always"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "ClusterFirst",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"nodeName": "minikube",
|
||||
"securityContext": {},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Running",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Initialized",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T03:31:41Z"
|
||||
},
|
||||
{
|
||||
"type": "Ready",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T03:31:41Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [nginx]"
|
||||
},
|
||||
{
|
||||
"type": "ContainersReady",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T03:31:41Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [nginx]"
|
||||
},
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T03:31:41Z"
|
||||
}
|
||||
],
|
||||
"hostIP": "192.168.49.2",
|
||||
"podIP": "172.17.0.3",
|
||||
"podIPs": [
|
||||
{
|
||||
"ip": "172.17.0.3"
|
||||
}
|
||||
],
|
||||
"startTime": "2023-07-11T03:31:41Z",
|
||||
"containerStatuses": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"state": {
|
||||
"waiting": {
|
||||
"reason": "CrashLoopBackOff",
|
||||
"message": "back-off 1m20s restarting failed container=nginx pod=init-demo_default(8d27f35a-4b45-4752-a5db-7985ea8b38bf)"
|
||||
}
|
||||
},
|
||||
"lastState": {
|
||||
"terminated": {
|
||||
"exitCode": 127,
|
||||
"reason": "ContainerCannotRun",
|
||||
"message": "failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
"startedAt": "2023-07-11T03:33:15Z",
|
||||
"finishedAt": "2023-07-11T03:33:15Z",
|
||||
"containerID": "docker://c04bcccbdc5eee8f0fc1b88c85c9b31e79f963dbee75fda97c022938222c8d90"
|
||||
}
|
||||
},
|
||||
"ready": false,
|
||||
"restartCount": 4,
|
||||
"image": "nginx:latest",
|
||||
"imageID": "docker-pullable://nginx@sha256:08bc36ad52474e528cc1ea3426b5e3f4bad8a130318e3140d6cfe29c8892c7ef",
|
||||
"containerID": "docker://c04bcccbdc5eee8f0fc1b88c85c9b31e79f963dbee75fda97c022938222c8d90",
|
||||
"started": false
|
||||
}
|
||||
],
|
||||
"qosClass": "BestEffort"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,368 @@
|
||||
{
|
||||
"kind": "PodList",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"resourceVersion": "982711"
|
||||
},
|
||||
"items": [
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "init-demo2",
|
||||
"namespace": "message-pod-init-crashloop-backoff",
|
||||
"uid": "5a560e83-c634-4c91-b308-510ee692ed6a",
|
||||
"resourceVersion": "982707",
|
||||
"creationTimestamp": "2023-07-11T04:01:16Z",
|
||||
"annotations": {
|
||||
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"name\":\"init-demo2\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\",\"ports\":[{\"containerPort\":80}],\"volumeMounts\":[{\"mountPath\":\"/usr/share/nginx/html\",\"name\":\"workdir\"}]}],\"dnsPolicy\":\"Default\",\"initContainers\":[{\"command\":[\"wge\",\"-O\",\"/work-dir/index.html\",\"https://home.robusta.dev\"],\"image\":\"busybox:1.28\",\"name\":\"install\",\"volumeMounts\":[{\"mountPath\":\"/work-dir\",\"name\":\"workdir\"}]}],\"volumes\":[{\"emptyDir\":{},\"name\":\"workdir\"}]}}\n"
|
||||
},
|
||||
"managedFields": [
|
||||
{
|
||||
"manager": "kubectl-client-side-apply",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:16Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:metadata": {
|
||||
"f:annotations": {
|
||||
".": {},
|
||||
"f:kubectl.kubernetes.io/last-applied-configuration": {}
|
||||
}
|
||||
},
|
||||
"f:spec": {
|
||||
"f:containers": {
|
||||
"k:{\"name\":\"nginx\"}": {
|
||||
".": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:ports": {
|
||||
".": {},
|
||||
"k:{\"containerPort\":80,\"protocol\":\"TCP\"}": {
|
||||
".": {},
|
||||
"f:containerPort": {},
|
||||
"f:protocol": {}
|
||||
}
|
||||
},
|
||||
"f:resources": {},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {},
|
||||
"f:volumeMounts": {
|
||||
".": {},
|
||||
"k:{\"mountPath\":\"/usr/share/nginx/html\"}": {
|
||||
".": {},
|
||||
"f:mountPath": {},
|
||||
"f:name": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"f:dnsPolicy": {},
|
||||
"f:enableServiceLinks": {},
|
||||
"f:initContainers": {
|
||||
".": {},
|
||||
"k:{\"name\":\"install\"}": {
|
||||
".": {},
|
||||
"f:command": {},
|
||||
"f:image": {},
|
||||
"f:imagePullPolicy": {},
|
||||
"f:name": {},
|
||||
"f:resources": {},
|
||||
"f:terminationMessagePath": {},
|
||||
"f:terminationMessagePolicy": {},
|
||||
"f:volumeMounts": {
|
||||
".": {},
|
||||
"k:{\"mountPath\":\"/work-dir\"}": {
|
||||
".": {},
|
||||
"f:mountPath": {},
|
||||
"f:name": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"f:restartPolicy": {},
|
||||
"f:schedulerName": {},
|
||||
"f:securityContext": {},
|
||||
"f:terminationGracePeriodSeconds": {},
|
||||
"f:volumes": {
|
||||
".": {},
|
||||
"k:{\"name\":\"workdir\"}": {
|
||||
".": {},
|
||||
"f:emptyDir": {},
|
||||
"f:name": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"manager": "kubelet",
|
||||
"operation": "Update",
|
||||
"apiVersion": "v1",
|
||||
"time": "2023-07-11T04:01:23Z",
|
||||
"fieldsType": "FieldsV1",
|
||||
"fieldsV1": {
|
||||
"f:status": {
|
||||
"f:conditions": {
|
||||
"k:{\"type\":\"ContainersReady\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Initialized\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
},
|
||||
"k:{\"type\":\"Ready\"}": {
|
||||
".": {},
|
||||
"f:lastProbeTime": {},
|
||||
"f:lastTransitionTime": {},
|
||||
"f:message": {},
|
||||
"f:reason": {},
|
||||
"f:status": {},
|
||||
"f:type": {}
|
||||
}
|
||||
},
|
||||
"f:containerStatuses": {},
|
||||
"f:hostIP": {},
|
||||
"f:initContainerStatuses": {},
|
||||
"f:podIP": {},
|
||||
"f:podIPs": {
|
||||
".": {},
|
||||
"k:{\"ip\":\"172.17.0.3\"}": {
|
||||
".": {},
|
||||
"f:ip": {}
|
||||
}
|
||||
},
|
||||
"f:startTime": {}
|
||||
}
|
||||
},
|
||||
"subresource": "status"
|
||||
}
|
||||
]
|
||||
},
|
||||
"spec": {
|
||||
"volumes": [
|
||||
{
|
||||
"name": "workdir",
|
||||
"emptyDir": {}
|
||||
},
|
||||
{
|
||||
"name": "kube-api-access-w4mrq",
|
||||
"projected": {
|
||||
"sources": [
|
||||
{
|
||||
"serviceAccountToken": {
|
||||
"expirationSeconds": 3607,
|
||||
"path": "token"
|
||||
}
|
||||
},
|
||||
{
|
||||
"configMap": {
|
||||
"name": "kube-root-ca.crt",
|
||||
"items": [
|
||||
{
|
||||
"key": "ca.crt",
|
||||
"path": "ca.crt"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"downwardAPI": {
|
||||
"items": [
|
||||
{
|
||||
"path": "namespace",
|
||||
"fieldRef": {
|
||||
"apiVersion": "v1",
|
||||
"fieldPath": "metadata.namespace"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"defaultMode": 420
|
||||
}
|
||||
}
|
||||
],
|
||||
"initContainers": [
|
||||
{
|
||||
"name": "install",
|
||||
"image": "busybox:1.28",
|
||||
"command": [
|
||||
"wge",
|
||||
"-O",
|
||||
"/work-dir/index.html",
|
||||
"https://home.robusta.dev"
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "workdir",
|
||||
"mountPath": "/work-dir"
|
||||
},
|
||||
{
|
||||
"name": "kube-api-access-w4mrq",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "IfNotPresent"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"image": "nginx",
|
||||
"ports": [
|
||||
{
|
||||
"containerPort": 80,
|
||||
"protocol": "TCP"
|
||||
}
|
||||
],
|
||||
"resources": {},
|
||||
"volumeMounts": [
|
||||
{
|
||||
"name": "workdir",
|
||||
"mountPath": "/usr/share/nginx/html"
|
||||
},
|
||||
{
|
||||
"name": "kube-api-access-w4mrq",
|
||||
"readOnly": true,
|
||||
"mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
|
||||
}
|
||||
],
|
||||
"terminationMessagePath": "/dev/termination-log",
|
||||
"terminationMessagePolicy": "File",
|
||||
"imagePullPolicy": "Always"
|
||||
}
|
||||
],
|
||||
"restartPolicy": "Always",
|
||||
"terminationGracePeriodSeconds": 30,
|
||||
"dnsPolicy": "Default",
|
||||
"serviceAccountName": "default",
|
||||
"serviceAccount": "default",
|
||||
"nodeName": "minikube",
|
||||
"securityContext": {},
|
||||
"schedulerName": "default-scheduler",
|
||||
"tolerations": [
|
||||
{
|
||||
"key": "node.kubernetes.io/not-ready",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
},
|
||||
{
|
||||
"key": "node.kubernetes.io/unreachable",
|
||||
"operator": "Exists",
|
||||
"effect": "NoExecute",
|
||||
"tolerationSeconds": 300
|
||||
}
|
||||
],
|
||||
"priority": 0,
|
||||
"enableServiceLinks": true,
|
||||
"preemptionPolicy": "PreemptLowerPriority"
|
||||
},
|
||||
"status": {
|
||||
"phase": "Pending",
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Initialized",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:01:16Z",
|
||||
"reason": "ContainersNotInitialized",
|
||||
"message": "containers with incomplete status: [install]"
|
||||
},
|
||||
{
|
||||
"type": "Ready",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:01:16Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [nginx]"
|
||||
},
|
||||
{
|
||||
"type": "ContainersReady",
|
||||
"status": "False",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:01:16Z",
|
||||
"reason": "ContainersNotReady",
|
||||
"message": "containers with unready status: [nginx]"
|
||||
},
|
||||
{
|
||||
"type": "PodScheduled",
|
||||
"status": "True",
|
||||
"lastProbeTime": null,
|
||||
"lastTransitionTime": "2023-07-11T04:01:16Z"
|
||||
}
|
||||
],
|
||||
"hostIP": "192.168.49.2",
|
||||
"podIP": "172.17.0.3",
|
||||
"podIPs": [
|
||||
{
|
||||
"ip": "172.17.0.3"
|
||||
}
|
||||
],
|
||||
"startTime": "2023-07-11T04:01:16Z",
|
||||
"initContainerStatuses": [
|
||||
{
|
||||
"name": "install",
|
||||
"state": {
|
||||
"waiting": {
|
||||
"reason": "RunContainerError",
|
||||
"message": "failed to start container \"b201927f10154b9ab9913f65aa13b46e5eeed74b8efff500d11e3f08af09621b\": Error response from daemon: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown"
|
||||
}
|
||||
},
|
||||
"lastState": {
|
||||
"terminated": {
|
||||
"exitCode": 127,
|
||||
"reason": "ContainerCannotRun",
|
||||
"message": "failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: \"wge\": executable file not found in $PATH: unknown",
|
||||
"startedAt": "2023-07-11T04:01:16Z",
|
||||
"finishedAt": "2023-07-11T04:01:16Z",
|
||||
"containerID": "docker://b201927f10154b9ab9913f65aa13b46e5eeed74b8efff500d11e3f08af09621b"
|
||||
}
|
||||
},
|
||||
"ready": false,
|
||||
"restartCount": 1,
|
||||
"image": "busybox:1.28",
|
||||
"imageID": "docker-pullable://busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47",
|
||||
"containerID": "docker://b201927f10154b9ab9913f65aa13b46e5eeed74b8efff500d11e3f08af09621b"
|
||||
}
|
||||
],
|
||||
"containerStatuses": [
|
||||
{
|
||||
"name": "nginx",
|
||||
"state": {
|
||||
"waiting": {
|
||||
"reason": "PodInitializing"
|
||||
}
|
||||
},
|
||||
"lastState": {},
|
||||
"ready": false,
|
||||
"restartCount": 0,
|
||||
"image": "nginx",
|
||||
"imageID": "",
|
||||
"started": false
|
||||
}
|
||||
],
|
||||
"qosClass": "BestEffort"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubl
|
||||
type HostAnalyzer interface {
|
||||
Title() string
|
||||
IsExcluded() (bool, error)
|
||||
Analyze(getFile func(string) ([]byte, error)) ([]*AnalyzeResult, error)
|
||||
Analyze(getFile func(string) ([]byte, error), findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error)
|
||||
}
|
||||
|
||||
func GetHostAnalyzer(analyzer *troubleshootv1beta2.HostAnalyze) (HostAnalyzer, bool) {
|
||||
@@ -44,10 +44,14 @@ func GetHostAnalyzer(analyzer *troubleshootv1beta2.HostAnalyze) (HostAnalyzer, b
|
||||
return &AnalyzeHostFilesystemPerformance{analyzer.FilesystemPerformance}, true
|
||||
case analyzer.Certificate != nil:
|
||||
return &AnalyzeHostCertificate{analyzer.Certificate}, true
|
||||
case analyzer.CertificatesCollection != nil:
|
||||
return &AnalyzeHostCertificatesCollection{analyzer.CertificatesCollection}, true
|
||||
case analyzer.HostServices != nil:
|
||||
return &AnalyzeHostServices{analyzer.HostServices}, true
|
||||
case analyzer.HostOS != nil:
|
||||
return &AnalyzeHostOS{analyzer.HostOS}, true
|
||||
case analyzer.TextAnalyze != nil:
|
||||
return &AnalyzeHostTextAnalyze{analyzer.TextAnalyze}, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
|
||||
@@ -24,7 +24,9 @@ func (a *AnalyzeHostBlockDevices) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostBlockDevices) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostBlockDevices) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
contents, err := getCollectedFileContents(collect.HostBlockDevicesPath)
|
||||
|
||||
@@ -265,7 +265,7 @@ func TestAnalyzeBlockDevices(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostBlockDevices{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostBlockDevices{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -20,7 +20,9 @@ func (a *AnalyzeHostCertificate) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCertificate) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostCertificate) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
collectorName := hostAnalyzer.CollectorName
|
||||
|
||||
@@ -332,7 +332,7 @@ func TestAnalyzeCertificate(t *testing.T) {
|
||||
return []byte(test.status), nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostCertificate{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostCertificate{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
)
|
||||
|
||||
type AnalyzeHostCertificatesCollection struct {
|
||||
hostAnalyzer *troubleshootv1beta2.HostCertificatesCollectionAnalyze
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCertificatesCollection) Title() string {
|
||||
return hostAnalyzerTitleOrDefault(a.hostAnalyzer.AnalyzeMeta, "Host Certificates Collection")
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCertificatesCollection) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCertificatesCollection) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
collectorName := hostAnalyzer.CollectorName
|
||||
if collectorName == "" {
|
||||
collectorName = "certificatesCollection"
|
||||
}
|
||||
name := filepath.Join("host-collectors/certificatesCollection", collectorName+".json")
|
||||
|
||||
certificatesInfo, err := getCollectedFileContents(name)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get contents of certificatesCollection.json")
|
||||
}
|
||||
|
||||
collectorCertificates := []collect.HostCertificatesCollection{}
|
||||
if err := json.Unmarshal(certificatesInfo, &collectorCertificates); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to parse certificatesCollection.json")
|
||||
}
|
||||
|
||||
var coll resultCollector
|
||||
|
||||
for _, cert := range collectorCertificates {
|
||||
|
||||
source := ""
|
||||
|
||||
if cert.CertificatePath != "" {
|
||||
source = fmt.Sprintf("obtained from %s", cert.CertificatePath)
|
||||
}
|
||||
|
||||
if cert.Message == collect.CertMissing {
|
||||
// return the result immediately if the certificate is missing
|
||||
coll.push(&AnalyzeResult{
|
||||
Title: a.Title(),
|
||||
IsFail: true,
|
||||
Message: fmt.Sprintf("Certificate is missing, cannot be %s", source),
|
||||
})
|
||||
} else {
|
||||
results, err := a.analyzeHostAnalyzeCertificatesResult(cert.CertificateChain, hostAnalyzer.Outcomes, source)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, result := range results {
|
||||
coll.push(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return coll.get(a.Title()), nil
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCertificatesCollection) analyzeHostAnalyzeCertificatesResult(certificateChains []collect.ParsedCertificate, outcomes []*troubleshootv1beta2.Outcome, source string) ([]*AnalyzeResult, error) {
|
||||
var coll resultCollector
|
||||
var passResults []*AnalyzeResult
|
||||
when := ""
|
||||
message := ""
|
||||
|
||||
for _, certChain := range certificateChains {
|
||||
for _, outcome := range outcomes {
|
||||
result := &AnalyzeResult{
|
||||
Title: a.Title(),
|
||||
}
|
||||
|
||||
if outcome.Fail != nil {
|
||||
result.IsFail = true
|
||||
when = outcome.Fail.When
|
||||
message = outcome.Fail.Message
|
||||
} else if outcome.Warn != nil {
|
||||
result.IsWarn = true
|
||||
when = outcome.Warn.When
|
||||
message = outcome.Warn.Message
|
||||
} else if outcome.Pass != nil {
|
||||
result.IsPass = true
|
||||
when = outcome.Pass.When
|
||||
message = outcome.Pass.Message
|
||||
} else {
|
||||
return nil, errors.New("empty outcome")
|
||||
}
|
||||
|
||||
if result.IsPass && certChain.IsValid {
|
||||
result.Message = fmt.Sprintf("%s, %s", message, source)
|
||||
// if the certificate is valid, we need to wait for the warning check whether the certificate is going to expire
|
||||
passResults = append(passResults, result)
|
||||
}
|
||||
|
||||
if result.IsFail && !certChain.IsValid {
|
||||
result.Message = fmt.Sprintf("%s, %s", message, source)
|
||||
// return the result immediately if the certificate is invalid
|
||||
coll.push(result)
|
||||
}
|
||||
|
||||
if result.IsWarn && certChain.IsValid {
|
||||
warnDate, _ := regexp.Compile(`notAfter \< Today \+ (\d+) days`)
|
||||
warnMatch := warnDate.FindStringSubmatch(when)
|
||||
if warnMatch != nil {
|
||||
warnMatchDays, err := strconv.Atoi(warnMatch[1])
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to convert string to integer")
|
||||
}
|
||||
|
||||
targetTime := time.Now().AddDate(0, 0, warnMatchDays)
|
||||
|
||||
if targetTime.After(certChain.NotAfter) {
|
||||
result.Message = fmt.Sprintf("%s in %d days, %s", message, warnMatchDays, source)
|
||||
// discard passResults if the certificate is going to expire in certain days
|
||||
passResults = []*AnalyzeResult{}
|
||||
coll.push(result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// append passResults if the certificate is valid and not going to expire in certain days
|
||||
for _, passResult := range passResults {
|
||||
coll.push(passResult)
|
||||
}
|
||||
}
|
||||
return coll.results, nil
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAnalyzeHostCertificatesCollection(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
file string
|
||||
hostAnalyzer *troubleshootv1beta2.HostCertificatesCollectionAnalyze
|
||||
result []*AnalyzeResult
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "certificate-valid",
|
||||
file: fmt.Sprintf(`[{
|
||||
"certificatePath": "apiserver-kubelet-client.crt",
|
||||
"certificateChain": [
|
||||
{
|
||||
"certificate": "ca.crt",
|
||||
"subject": "CN=kubernetes",
|
||||
"subjectAlternativeNames": [
|
||||
"kubernetes"
|
||||
],
|
||||
"issuer": "CN=kubernetes",
|
||||
"notAfter": "%s",
|
||||
"notBefore": "2023-04-19T00:30:20Z",
|
||||
"isValid": true,
|
||||
"isCA": true
|
||||
}
|
||||
],
|
||||
"message": "cert-valid"
|
||||
}]`, time.Now().AddDate(1, 0, 0).Format("2006-01-02T15:04:05Z")),
|
||||
hostAnalyzer: &troubleshootv1beta2.HostCertificatesCollectionAnalyze{
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "Certificate is valid",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: true,
|
||||
IsWarn: false,
|
||||
IsFail: false,
|
||||
Title: "Host Certificates Collection",
|
||||
Message: "Certificate is valid, obtained from apiserver-kubelet-client.crt",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "certificate-invalid",
|
||||
file: `[{
|
||||
"certificatePath": "apiserver-kubelet-client.crt",
|
||||
"certificateChain": [
|
||||
{
|
||||
"certificate": "ca.crt",
|
||||
"subject": "CN=kubernetes",
|
||||
"subjectAlternativeNames": [
|
||||
"kubernetes"
|
||||
],
|
||||
"issuer": "CN=kubernetes",
|
||||
"notAfter": "2022-04-16T00:30:20Z",
|
||||
"notBefore": "2021-04-19T00:30:20Z",
|
||||
"isValid": false,
|
||||
"isCA": true
|
||||
}
|
||||
],
|
||||
"message": "cert-invalid"
|
||||
}]`,
|
||||
hostAnalyzer: &troubleshootv1beta2.HostCertificatesCollectionAnalyze{
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "notAfter < Today",
|
||||
Message: "Certificate has expired",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: false,
|
||||
IsFail: true,
|
||||
Title: "Host Certificates Collection",
|
||||
Message: "Certificate has expired, obtained from apiserver-kubelet-client.crt",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "certificate-about-to-expire",
|
||||
file: fmt.Sprintf(`[{
|
||||
"certificatePath": "apiserver-kubelet-client.crt",
|
||||
"certificateChain": [
|
||||
{
|
||||
"certificate": "ca.crt",
|
||||
"subject": "CN=kubernetes",
|
||||
"subjectAlternativeNames": [
|
||||
"kubernetes"
|
||||
],
|
||||
"issuer": "CN=kubernetes",
|
||||
"notAfter": "%s",
|
||||
"notBefore": "2021-04-19T00:30:20Z",
|
||||
"isValid": true,
|
||||
"isCA": true
|
||||
}
|
||||
],
|
||||
"message": "cert-valid"
|
||||
}]`, time.Now().AddDate(0, 0, 5).Format("2006-01-02T15:04:05Z")),
|
||||
hostAnalyzer: &troubleshootv1beta2.HostCertificatesCollectionAnalyze{
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "notAfter < Today + 15 days",
|
||||
Message: "Certificate is about to expire",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "Host Certificates Collection",
|
||||
Message: "Certificate is about to expire in 15 days, obtained from apiserver-kubelet-client.crt",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "certificate-missing",
|
||||
file: `[{
|
||||
"certificatePath": "apiserver-kubelet-client.crt",
|
||||
"message": "cert-missing"
|
||||
}]`,
|
||||
hostAnalyzer: &troubleshootv1beta2.HostCertificatesCollectionAnalyze{
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: false,
|
||||
IsFail: true,
|
||||
Title: "Host Certificates Collection",
|
||||
Message: "Certificate is missing, cannot be obtained from apiserver-kubelet-client.crt",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "certificate-valid-and-about-to-expire",
|
||||
file: fmt.Sprintf(`[{
|
||||
"certificatePath": "apiserver-kubelet-client.crt",
|
||||
"certificateChain": [
|
||||
{
|
||||
"certificate": "ca.crt",
|
||||
"subject": "CN=kubernetes",
|
||||
"subjectAlternativeNames": [
|
||||
"kubernetes"
|
||||
],
|
||||
"issuer": "CN=kubernetes",
|
||||
"notAfter": "%s",
|
||||
"notBefore": "2021-04-19T00:30:20Z",
|
||||
"isValid": true,
|
||||
"isCA": true
|
||||
}
|
||||
],
|
||||
"message": "cert-valid"
|
||||
}]`, time.Now().AddDate(0, 0, 5).Format("2006-01-02T15:04:05Z")),
|
||||
hostAnalyzer: &troubleshootv1beta2.HostCertificatesCollectionAnalyze{
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "Certificate is valid",
|
||||
},
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "notAfter < Today + 15 days",
|
||||
Message: "Certificate is about to expire",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
IsPass: false,
|
||||
IsWarn: true,
|
||||
IsFail: false,
|
||||
Title: "Host Certificates Collection",
|
||||
Message: "Certificate is about to expire in 15 days, obtained from apiserver-kubelet-client.crt",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
|
||||
getCollectedFileContents := func(filename string) ([]byte, error) {
|
||||
return []byte(test.file), nil
|
||||
}
|
||||
|
||||
a := AnalyzeHostCertificatesCollection{
|
||||
test.hostAnalyzer,
|
||||
}
|
||||
|
||||
result, err := a.Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,9 @@ func (a *AnalyzeHostCPU) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostCPU) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostCPU) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
contents, err := getCollectedFileContents(collect.HostCPUPath)
|
||||
|
||||
@@ -204,7 +204,7 @@ func TestHostCpuAnalyze(t *testing.T) {
|
||||
Outcomes: tc.outcomes,
|
||||
},
|
||||
}
|
||||
results, err := analyzer.Analyze(fn)
|
||||
results, err := analyzer.Analyze(fn, nil)
|
||||
if tc.wantErr {
|
||||
require.NotNil(t, err)
|
||||
return
|
||||
|
||||
@@ -25,7 +25,9 @@ func (a *AnalyzeHostDiskUsage) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostDiskUsage) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostDiskUsage) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
name := filepath.Join("host-collectors/diskUsage", "diskUsage.json")
|
||||
|
||||
@@ -412,7 +412,7 @@ func TestAnalyzeHostDiskUsage(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostDiskUsage{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostDiskUsage{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -27,9 +27,15 @@ func (a *AnalyzeHostFilesystemPerformance) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostFilesystemPerformance) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostFilesystemPerformance) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
result := &AnalyzeResult{
|
||||
Title: a.Title(),
|
||||
}
|
||||
|
||||
collectorName := hostAnalyzer.CollectorName
|
||||
if collectorName == "" {
|
||||
collectorName = "filesystemPerformance"
|
||||
@@ -37,16 +43,46 @@ func (a *AnalyzeHostFilesystemPerformance) Analyze(getCollectedFileContents func
|
||||
name := filepath.Join("host-collectors/filesystemPerformance", collectorName+".json")
|
||||
contents, err := getCollectedFileContents(name)
|
||||
if err != nil {
|
||||
if len(hostAnalyzer.Outcomes) >= 1 {
|
||||
// if the very first outcome is FILE_NOT_COLLECTED', then use that outcome
|
||||
// otherwise, return the error
|
||||
if hostAnalyzer.Outcomes[0].Fail != nil && hostAnalyzer.Outcomes[0].Fail.When == FILE_NOT_COLLECTED {
|
||||
result.IsFail = true
|
||||
result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Fail.Message, collect.FSPerfResults{})
|
||||
result.URI = hostAnalyzer.Outcomes[0].Fail.URI
|
||||
return []*AnalyzeResult{result}, nil
|
||||
}
|
||||
if hostAnalyzer.Outcomes[0].Warn != nil && hostAnalyzer.Outcomes[0].Warn.When == FILE_NOT_COLLECTED {
|
||||
result.IsWarn = true
|
||||
result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Warn.Message, collect.FSPerfResults{})
|
||||
result.URI = hostAnalyzer.Outcomes[0].Warn.URI
|
||||
return []*AnalyzeResult{result}, nil
|
||||
}
|
||||
if hostAnalyzer.Outcomes[0].Pass != nil && hostAnalyzer.Outcomes[0].Pass.When == FILE_NOT_COLLECTED {
|
||||
result.IsPass = true
|
||||
result.Message = renderFSPerfOutcome(hostAnalyzer.Outcomes[0].Pass.Message, collect.FSPerfResults{})
|
||||
result.URI = hostAnalyzer.Outcomes[0].Pass.URI
|
||||
return []*AnalyzeResult{result}, nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Wrapf(err, "failed to get collected file %s", name)
|
||||
}
|
||||
|
||||
fsPerf := collect.FSPerfResults{}
|
||||
if err := json.Unmarshal(contents, &fsPerf); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal filesystem performance results from %s", name)
|
||||
fioResult := collect.FioResult{}
|
||||
if err := json.Unmarshal(contents, &fioResult); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal fio results from %s", name)
|
||||
}
|
||||
|
||||
result := &AnalyzeResult{
|
||||
Title: a.Title(),
|
||||
if len(fioResult.Jobs) == 0 {
|
||||
return nil, errors.Errorf("no jobs found in fio results from %s", name)
|
||||
}
|
||||
|
||||
fioWriteLatency := fioResult.Jobs[0].Sync
|
||||
|
||||
fsPerf := fioWriteLatency.FSPerfResults()
|
||||
if err := json.Unmarshal(contents, &fsPerf); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to unmarshal filesystem performance results from %s", name)
|
||||
}
|
||||
|
||||
for _, outcome := range hostAnalyzer.Outcomes {
|
||||
@@ -122,6 +158,10 @@ func (a *AnalyzeHostFilesystemPerformance) Analyze(getCollectedFileContents func
|
||||
}
|
||||
|
||||
func compareHostFilesystemPerformanceConditionalToActual(conditional string, fsPerf collect.FSPerfResults) (res bool, err error) {
|
||||
if conditional == FILE_NOT_COLLECTED {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
parts := strings.Split(conditional, " ")
|
||||
if len(parts) != 3 {
|
||||
return false, fmt.Errorf("conditional must have exactly 3 parts, got %d", len(parts))
|
||||
@@ -177,7 +217,7 @@ func compareHostFilesystemPerformanceConditionalToActual(conditional string, fsP
|
||||
return doCompareHostFilesystemPerformance(comparator, fsPerf.P9999, desiredDuration)
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("Unknown filesystem performance keyword %q", keyword)
|
||||
return false, fmt.Errorf("unknown filesystem performance keyword %q", keyword)
|
||||
}
|
||||
|
||||
func doCompareHostFilesystemPerformance(operator string, actual time.Duration, desired time.Duration) (bool, error) {
|
||||
@@ -194,7 +234,7 @@ func doCompareHostFilesystemPerformance(operator string, actual time.Duration, d
|
||||
return actual == desired, nil
|
||||
}
|
||||
|
||||
return false, fmt.Errorf("Unknown filesystem performance operator %q", operator)
|
||||
return false, fmt.Errorf("unknown filesystem performance operator %q", operator)
|
||||
}
|
||||
|
||||
func renderFSPerfOutcome(outcome string, fsPerf collect.FSPerfResults) string {
|
||||
|
||||
@@ -1,48 +1,315 @@
|
||||
package analyzer
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
|
||||
"github.com/replicatedhq/troubleshoot/pkg/collect"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAnalyzeHostFilesystemPerformance(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
fsPerf *collect.FSPerfResults
|
||||
fioResult string
|
||||
hostAnalyzer *troubleshootv1beta2.FilesystemPerformanceAnalyze
|
||||
result []*AnalyzeResult
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "Cover",
|
||||
fsPerf: &collect.FSPerfResults{
|
||||
Min: 200 * time.Nanosecond,
|
||||
Max: time.Second,
|
||||
Average: 55 * time.Microsecond,
|
||||
P1: 1 * time.Microsecond,
|
||||
P5: 5 * time.Microsecond,
|
||||
P10: 10 * time.Microsecond,
|
||||
P20: 20 * time.Microsecond,
|
||||
P30: 30 * time.Microsecond,
|
||||
P40: 40 * time.Microsecond,
|
||||
P50: 50 * time.Microsecond,
|
||||
P60: 60 * time.Microsecond,
|
||||
P70: 70 * time.Microsecond,
|
||||
P80: 80 * time.Microsecond,
|
||||
P90: 90 * time.Microsecond,
|
||||
P95: 95 * time.Microsecond,
|
||||
P99: 99 * time.Microsecond,
|
||||
P995: 995 * time.Microsecond,
|
||||
P999: 999 * time.Microsecond,
|
||||
P9995: 5 * time.Millisecond,
|
||||
P9999: 9 * time.Millisecond,
|
||||
},
|
||||
fioResult: `{
|
||||
"fio version" : "fio-3.28",
|
||||
"timestamp" : 1691679955,
|
||||
"timestamp_ms" : 1691679955590,
|
||||
"time" : "Thu Aug 10 15:05:55 2023",
|
||||
"global options" : {
|
||||
"rw" : "write",
|
||||
"ioengine" : "sync",
|
||||
"fdatasync" : "1",
|
||||
"directory" : "/var/lib/etcd",
|
||||
"size" : "23068672",
|
||||
"bs" : "1024"
|
||||
},
|
||||
"jobs" : [
|
||||
{
|
||||
"jobname" : "fsperf",
|
||||
"groupid" : 0,
|
||||
"error" : 0,
|
||||
"eta" : 0,
|
||||
"elapsed" : 15,
|
||||
"job options" : {
|
||||
"name" : "fsperf",
|
||||
"runtime" : "120"
|
||||
},
|
||||
"read" : {
|
||||
"io_bytes" : 0,
|
||||
"io_kbytes" : 0,
|
||||
"bw_bytes" : 0,
|
||||
"bw" : 0,
|
||||
"iops" : 0.000000,
|
||||
"runtime" : 0,
|
||||
"total_ios" : 0,
|
||||
"short_ios" : 22527,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"bw_min" : 0,
|
||||
"bw_max" : 0,
|
||||
"bw_agg" : 0.000000,
|
||||
"bw_mean" : 0.000000,
|
||||
"bw_dev" : 0.000000,
|
||||
"bw_samples" : 0,
|
||||
"iops_min" : 0,
|
||||
"iops_max" : 0,
|
||||
"iops_mean" : 0.000000,
|
||||
"iops_stddev" : 0.000000,
|
||||
"iops_samples" : 0
|
||||
},
|
||||
"write" : {
|
||||
"io_bytes" : 23068672,
|
||||
"io_kbytes" : 22528,
|
||||
"bw_bytes" : 1651182,
|
||||
"bw" : 1612,
|
||||
"iops" : 1612.483001,
|
||||
"runtime" : 13971,
|
||||
"total_ios" : 22528,
|
||||
"short_ios" : 0,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 200,
|
||||
"max" : 1000000000,
|
||||
"mean" : 55000,
|
||||
"stddev" : 12345.6789,
|
||||
"N" : 32400,
|
||||
"percentile" : {
|
||||
"1.000000" : 1000,
|
||||
"5.000000" : 5000,
|
||||
"10.000000" : 10000,
|
||||
"20.000000" : 20000,
|
||||
"30.000000" : 30000,
|
||||
"40.000000" : 40000,
|
||||
"50.000000" : 50000,
|
||||
"60.000000" : 60000,
|
||||
"70.000000" : 70000,
|
||||
"80.000000" : 80000,
|
||||
"90.000000" : 90000,
|
||||
"95.000000" : 95000,
|
||||
"99.000000" : 99000,
|
||||
"99.500000" : 995000,
|
||||
"99.900000" : 999000,
|
||||
"99.950000" : 5000000,
|
||||
"99.990000" : 9000000
|
||||
}
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 2684,
|
||||
"max" : 8710446,
|
||||
"mean" : 95169.335405,
|
||||
"stddev" : 172145.383902,
|
||||
"N" : 22528
|
||||
},
|
||||
"bw_min" : 1516,
|
||||
"bw_max" : 1706,
|
||||
"bw_agg" : 100.000000,
|
||||
"bw_mean" : 1613.629630,
|
||||
"bw_dev" : 35.708379,
|
||||
"bw_samples" : 27,
|
||||
"iops_min" : 1516,
|
||||
"iops_max" : 1706,
|
||||
"iops_mean" : 1613.629630,
|
||||
"iops_stddev" : 35.708379,
|
||||
"iops_samples" : 27
|
||||
},
|
||||
"trim" : {
|
||||
"io_bytes" : 0,
|
||||
"io_kbytes" : 0,
|
||||
"bw_bytes" : 0,
|
||||
"bw" : 0,
|
||||
"iops" : 0.000000,
|
||||
"runtime" : 0,
|
||||
"total_ios" : 0,
|
||||
"short_ios" : 0,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"bw_min" : 0,
|
||||
"bw_max" : 0,
|
||||
"bw_agg" : 0.000000,
|
||||
"bw_mean" : 0.000000,
|
||||
"bw_dev" : 0.000000,
|
||||
"bw_samples" : 0,
|
||||
"iops_min" : 0,
|
||||
"iops_max" : 0,
|
||||
"iops_mean" : 0.000000,
|
||||
"iops_stddev" : 0.000000,
|
||||
"iops_samples" : 0
|
||||
},
|
||||
"sync" : {
|
||||
"total_ios" : 0,
|
||||
"lat_ns" : {
|
||||
"min" : 200,
|
||||
"max" : 1000000000,
|
||||
"mean" : 55000,
|
||||
"stddev" : 12345.6789,
|
||||
"N" : 32400,
|
||||
"percentile" : {
|
||||
"1.000000" : 1000,
|
||||
"5.000000" : 5000,
|
||||
"10.000000" : 10000,
|
||||
"20.000000" : 20000,
|
||||
"30.000000" : 30000,
|
||||
"40.000000" : 40000,
|
||||
"50.000000" : 50000,
|
||||
"60.000000" : 60000,
|
||||
"70.000000" : 70000,
|
||||
"80.000000" : 80000,
|
||||
"90.000000" : 90000,
|
||||
"95.000000" : 95000,
|
||||
"99.000000" : 99000,
|
||||
"99.500000" : 995000,
|
||||
"99.900000" : 999000,
|
||||
"99.950000" : 5000000,
|
||||
"99.990000" : 9000000
|
||||
}
|
||||
}
|
||||
},
|
||||
"job_runtime" : 13970,
|
||||
"usr_cpu" : 1.410165,
|
||||
"sys_cpu" : 5.454545,
|
||||
"ctx" : 72137,
|
||||
"majf" : 0,
|
||||
"minf" : 16,
|
||||
"iodepth_level" : {
|
||||
"1" : 199.995561,
|
||||
"2" : 0.000000,
|
||||
"4" : 0.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"iodepth_submit" : {
|
||||
"0" : 0.000000,
|
||||
"4" : 100.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
"64" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"iodepth_complete" : {
|
||||
"0" : 0.000000,
|
||||
"4" : 100.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
"64" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"latency_ns" : {
|
||||
"2" : 0.000000,
|
||||
"4" : 0.000000,
|
||||
"10" : 0.000000,
|
||||
"20" : 0.000000,
|
||||
"50" : 0.000000,
|
||||
"100" : 0.000000,
|
||||
"250" : 0.000000,
|
||||
"500" : 0.000000,
|
||||
"750" : 0.000000,
|
||||
"1000" : 0.000000
|
||||
},
|
||||
"latency_us" : {
|
||||
"2" : 0.000000,
|
||||
"4" : 27.077415,
|
||||
"10" : 42.032138,
|
||||
"20" : 5.450994,
|
||||
"50" : 0.306286,
|
||||
"100" : 0.026634,
|
||||
"250" : 0.461648,
|
||||
"500" : 23.291016,
|
||||
"750" : 1.269531,
|
||||
"1000" : 0.035511
|
||||
},
|
||||
"latency_ms" : {
|
||||
"2" : 0.026634,
|
||||
"4" : 0.017756,
|
||||
"10" : 0.010000,
|
||||
"20" : 0.000000,
|
||||
"50" : 0.000000,
|
||||
"100" : 0.000000,
|
||||
"250" : 0.000000,
|
||||
"500" : 0.000000,
|
||||
"750" : 0.000000,
|
||||
"1000" : 0.000000,
|
||||
"2000" : 0.000000,
|
||||
">=2000" : 0.000000
|
||||
},
|
||||
"latency_depth" : 1,
|
||||
"latency_target" : 0,
|
||||
"latency_percentile" : 100.000000,
|
||||
"latency_window" : 0
|
||||
}
|
||||
],
|
||||
"disk_util" : [
|
||||
{
|
||||
"name" : "sda",
|
||||
"read_ios" : 5610,
|
||||
"write_ios" : 45550,
|
||||
"read_merges" : 0,
|
||||
"write_merges" : 568,
|
||||
"read_ticks" : 1863,
|
||||
"write_ticks" : 11605,
|
||||
"in_queue" : 14353,
|
||||
"util" : 99.435028
|
||||
}
|
||||
]
|
||||
}`,
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "etcd",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
@@ -298,12 +565,307 @@ func TestAnalyzeHostFilesystemPerformance(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "skip warn if pass first",
|
||||
fsPerf: &collect.FSPerfResults{
|
||||
P99: 9 * time.Millisecond,
|
||||
},
|
||||
fioResult: `{
|
||||
"fio version" : "fio-3.28",
|
||||
"timestamp" : 1691679955,
|
||||
"timestamp_ms" : 1691679955590,
|
||||
"time" : "Thu Aug 10 15:05:55 2023",
|
||||
"global options" : {
|
||||
"rw" : "write",
|
||||
"ioengine" : "sync",
|
||||
"fdatasync" : "1",
|
||||
"directory" : "/var/lib/etcd",
|
||||
"size" : "23068672",
|
||||
"bs" : "1024"
|
||||
},
|
||||
"jobs" : [
|
||||
{
|
||||
"jobname" : "fsperf",
|
||||
"groupid" : 0,
|
||||
"error" : 0,
|
||||
"eta" : 0,
|
||||
"elapsed" : 15,
|
||||
"job options" : {
|
||||
"name" : "fsperf",
|
||||
"runtime" : "120"
|
||||
},
|
||||
"read" : {
|
||||
"io_bytes" : 0,
|
||||
"io_kbytes" : 0,
|
||||
"bw_bytes" : 0,
|
||||
"bw" : 0,
|
||||
"iops" : 0.000000,
|
||||
"runtime" : 0,
|
||||
"total_ios" : 0,
|
||||
"short_ios" : 22527,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"bw_min" : 0,
|
||||
"bw_max" : 0,
|
||||
"bw_agg" : 0.000000,
|
||||
"bw_mean" : 0.000000,
|
||||
"bw_dev" : 0.000000,
|
||||
"bw_samples" : 0,
|
||||
"iops_min" : 0,
|
||||
"iops_max" : 0,
|
||||
"iops_mean" : 0.000000,
|
||||
"iops_stddev" : 0.000000,
|
||||
"iops_samples" : 0
|
||||
},
|
||||
"write" : {
|
||||
"io_bytes" : 23068672,
|
||||
"io_kbytes" : 22528,
|
||||
"bw_bytes" : 1651182,
|
||||
"bw" : 1612,
|
||||
"iops" : 1612.483001,
|
||||
"runtime" : 13971,
|
||||
"total_ios" : 22528,
|
||||
"short_ios" : 0,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 200,
|
||||
"max" : 1000000000,
|
||||
"mean" : 55000,
|
||||
"stddev" : 12345.6789,
|
||||
"N" : 32400,
|
||||
"percentile" : {
|
||||
"1.000000" : 1000,
|
||||
"5.000000" : 5000,
|
||||
"10.000000" : 10000,
|
||||
"20.000000" : 20000,
|
||||
"30.000000" : 30000,
|
||||
"40.000000" : 40000,
|
||||
"50.000000" : 50000,
|
||||
"60.000000" : 60000,
|
||||
"70.000000" : 70000,
|
||||
"80.000000" : 80000,
|
||||
"90.000000" : 90000,
|
||||
"95.000000" : 95000,
|
||||
"99.000000" : 99000,
|
||||
"99.500000" : 995000,
|
||||
"99.900000" : 999000,
|
||||
"99.950000" : 5000000,
|
||||
"99.990000" : 9000000
|
||||
}
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 2684,
|
||||
"max" : 8710446,
|
||||
"mean" : 95169.335405,
|
||||
"stddev" : 172145.383902,
|
||||
"N" : 22528
|
||||
},
|
||||
"bw_min" : 1516,
|
||||
"bw_max" : 1706,
|
||||
"bw_agg" : 100.000000,
|
||||
"bw_mean" : 1613.629630,
|
||||
"bw_dev" : 35.708379,
|
||||
"bw_samples" : 27,
|
||||
"iops_min" : 1516,
|
||||
"iops_max" : 1706,
|
||||
"iops_mean" : 1613.629630,
|
||||
"iops_stddev" : 35.708379,
|
||||
"iops_samples" : 27
|
||||
},
|
||||
"trim" : {
|
||||
"io_bytes" : 0,
|
||||
"io_kbytes" : 0,
|
||||
"bw_bytes" : 0,
|
||||
"bw" : 0,
|
||||
"iops" : 0.000000,
|
||||
"runtime" : 0,
|
||||
"total_ios" : 0,
|
||||
"short_ios" : 0,
|
||||
"drop_ios" : 0,
|
||||
"slat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"clat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"lat_ns" : {
|
||||
"min" : 0,
|
||||
"max" : 0,
|
||||
"mean" : 0.000000,
|
||||
"stddev" : 0.000000,
|
||||
"N" : 0
|
||||
},
|
||||
"bw_min" : 0,
|
||||
"bw_max" : 0,
|
||||
"bw_agg" : 0.000000,
|
||||
"bw_mean" : 0.000000,
|
||||
"bw_dev" : 0.000000,
|
||||
"bw_samples" : 0,
|
||||
"iops_min" : 0,
|
||||
"iops_max" : 0,
|
||||
"iops_mean" : 0.000000,
|
||||
"iops_stddev" : 0.000000,
|
||||
"iops_samples" : 0
|
||||
},
|
||||
"sync" : {
|
||||
"total_ios" : 0,
|
||||
"lat_ns" : {
|
||||
"min" : 200,
|
||||
"max" : 1000000000,
|
||||
"mean" : 55000,
|
||||
"stddev" : 12345.6789,
|
||||
"N" : 32400,
|
||||
"percentile" : {
|
||||
"1.000000" : 1000,
|
||||
"5.000000" : 5000,
|
||||
"10.000000" : 10000,
|
||||
"20.000000" : 20000,
|
||||
"30.000000" : 30000,
|
||||
"40.000000" : 40000,
|
||||
"50.000000" : 50000,
|
||||
"60.000000" : 60000,
|
||||
"70.000000" : 70000,
|
||||
"80.000000" : 80000,
|
||||
"90.000000" : 90000,
|
||||
"95.000000" : 95000,
|
||||
"99.000000" : 9000000,
|
||||
"99.500000" : 995000,
|
||||
"99.900000" : 999000,
|
||||
"99.950000" : 5000000,
|
||||
"99.990000" : 9000000
|
||||
}
|
||||
}
|
||||
},
|
||||
"job_runtime" : 13970,
|
||||
"usr_cpu" : 1.410165,
|
||||
"sys_cpu" : 5.454545,
|
||||
"ctx" : 72137,
|
||||
"majf" : 0,
|
||||
"minf" : 16,
|
||||
"iodepth_level" : {
|
||||
"1" : 199.995561,
|
||||
"2" : 0.000000,
|
||||
"4" : 0.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"iodepth_submit" : {
|
||||
"0" : 0.000000,
|
||||
"4" : 100.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
"64" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"iodepth_complete" : {
|
||||
"0" : 0.000000,
|
||||
"4" : 100.000000,
|
||||
"8" : 0.000000,
|
||||
"16" : 0.000000,
|
||||
"32" : 0.000000,
|
||||
"64" : 0.000000,
|
||||
">=64" : 0.000000
|
||||
},
|
||||
"latency_ns" : {
|
||||
"2" : 0.000000,
|
||||
"4" : 0.000000,
|
||||
"10" : 0.000000,
|
||||
"20" : 0.000000,
|
||||
"50" : 0.000000,
|
||||
"100" : 0.000000,
|
||||
"250" : 0.000000,
|
||||
"500" : 0.000000,
|
||||
"750" : 0.000000,
|
||||
"1000" : 0.000000
|
||||
},
|
||||
"latency_us" : {
|
||||
"2" : 0.000000,
|
||||
"4" : 27.077415,
|
||||
"10" : 42.032138,
|
||||
"20" : 5.450994,
|
||||
"50" : 0.306286,
|
||||
"100" : 0.026634,
|
||||
"250" : 0.461648,
|
||||
"500" : 23.291016,
|
||||
"750" : 1.269531,
|
||||
"1000" : 0.035511
|
||||
},
|
||||
"latency_ms" : {
|
||||
"2" : 0.026634,
|
||||
"4" : 0.017756,
|
||||
"10" : 0.010000,
|
||||
"20" : 0.000000,
|
||||
"50" : 0.000000,
|
||||
"100" : 0.000000,
|
||||
"250" : 0.000000,
|
||||
"500" : 0.000000,
|
||||
"750" : 0.000000,
|
||||
"1000" : 0.000000,
|
||||
"2000" : 0.000000,
|
||||
">=2000" : 0.000000
|
||||
},
|
||||
"latency_depth" : 1,
|
||||
"latency_target" : 0,
|
||||
"latency_percentile" : 100.000000,
|
||||
"latency_window" : 0
|
||||
}
|
||||
],
|
||||
"disk_util" : [
|
||||
{
|
||||
"name" : "sda",
|
||||
"read_ios" : 5610,
|
||||
"write_ios" : 45550,
|
||||
"read_merges" : 0,
|
||||
"write_merges" : 568,
|
||||
"read_ticks" : 1863,
|
||||
"write_ticks" : 11605,
|
||||
"in_queue" : 14353,
|
||||
"util" : 99.435028
|
||||
}
|
||||
]
|
||||
}`,
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "file system performance",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "fileNotCollected",
|
||||
Message: "Warn when the file was not collected",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "p99 < 10ms",
|
||||
@@ -332,27 +894,202 @@ func TestAnalyzeHostFilesystemPerformance(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bail if malformed JSON",
|
||||
fioResult: `{
|
||||
bad JSON
|
||||
}`,
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "file system performance",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "bad JSON should not be analyzed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "bail if fio ran no jobs",
|
||||
fioResult: `{
|
||||
"fio version" : "fio-3.28",
|
||||
"timestamp" : 1691679955,
|
||||
"timestamp_ms" : 1691679955590,
|
||||
"time" : "Thu Aug 10 15:05:55 2023",
|
||||
"global options" : {
|
||||
"rw" : "write",
|
||||
"ioengine" : "sync",
|
||||
"fdatasync" : "1",
|
||||
"directory" : "/var/lib/etcd",
|
||||
"size" : "23068672",
|
||||
"bs" : "1024"
|
||||
},
|
||||
"jobs" : [
|
||||
]
|
||||
}`,
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "file system performance",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "an empty Jobs array should not be analyzed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
b, err := json.Marshal(test.fsPerf)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
b := []byte(test.fioResult)
|
||||
|
||||
getCollectedFileContents := func(filename string) ([]byte, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostFilesystemPerformance{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
a := AnalyzeHostFilesystemPerformance{test.hostAnalyzer}
|
||||
result, err := a.Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
assert.Equal(t, test.result, result)
|
||||
req.Equal(test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAnalyzeHostFilesystemPerformanceNoFile(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
hostAnalyzer *troubleshootv1beta2.FilesystemPerformanceAnalyze
|
||||
result []*AnalyzeResult
|
||||
expectErr bool
|
||||
}{
|
||||
{
|
||||
name: "default behavior",
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "irrel",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "a nonexistent file should not be analyzed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
{
|
||||
name: "fail case",
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "irrel",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "fileNotCollected",
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: false,
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "Filesystem Performance",
|
||||
IsFail: true,
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "warn case",
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "irrel",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Warn: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "fileNotCollected",
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: false,
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "Filesystem Performance",
|
||||
IsWarn: true,
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "pass case",
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "irrel",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "fileNotCollected",
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: false,
|
||||
result: []*AnalyzeResult{
|
||||
{
|
||||
Title: "Filesystem Performance",
|
||||
IsPass: true,
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "fileNotCollected is only tested if it is the first result",
|
||||
hostAnalyzer: &troubleshootv1beta2.FilesystemPerformanceAnalyze{
|
||||
CollectorName: "irrel",
|
||||
Outcomes: []*troubleshootv1beta2.Outcome{
|
||||
{
|
||||
Fail: &troubleshootv1beta2.SingleOutcome{
|
||||
Message: "a nonexistent file should not be analyzed",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pass: &troubleshootv1beta2.SingleOutcome{
|
||||
When: "fileNotCollected",
|
||||
Message: "the required file was not collected",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectErr: true,
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
req := require.New(t)
|
||||
|
||||
getCollectedFileContents := func(filename string) ([]byte, error) {
|
||||
return nil, fmt.Errorf("file not found")
|
||||
}
|
||||
|
||||
a := AnalyzeHostFilesystemPerformance{test.hostAnalyzer}
|
||||
result, err := a.Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
req.NoError(err)
|
||||
}
|
||||
|
||||
req.Equal(test.result, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,9 @@ func (a *AnalyzeHostHTTP) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostHTTP) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostHTTP) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
name := filepath.Join("host-collectors/http", "result.json")
|
||||
|
||||
@@ -126,7 +126,7 @@ func TestAnalyzeHostHTTP(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostHTTP{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostHTTP{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,9 @@ func (a *AnalyzeHostHTTPLoadBalancer) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostHTTPLoadBalancer) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostHTTPLoadBalancer) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
collectorName := hostAnalyzer.CollectorName
|
||||
|
||||
@@ -24,7 +24,9 @@ func (a *AnalyzeHostIPV4Interfaces) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostIPV4Interfaces) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostIPV4Interfaces) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
contents, err := getCollectedFileContents(collect.HostIPV4InterfacesPath)
|
||||
|
||||
@@ -92,7 +92,7 @@ func TestAnalyzeIPV4Interfaces(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostIPV4Interfaces{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostIPV4Interfaces{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -40,7 +40,9 @@ func (a *AnalyzeHostKernelModules) IsExcluded() (bool, error) {
|
||||
// - a default fail will only trigger if there are no matching non-default pass outcomes.
|
||||
// - a default warn will only trigger if there are no matching non-default pass or fail outcomes.
|
||||
// - a default pass will only trigger if there are no matching non-default fail outcomes.
|
||||
func (a *AnalyzeHostKernelModules) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostKernelModules) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
contents, err := getCollectedFileContents(collect.HostKernelModulesPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -470,7 +470,7 @@ func TestAnalyzeKernelModules(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostKernelModules{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostKernelModules{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
require.Error(t, err)
|
||||
return
|
||||
|
||||
@@ -23,7 +23,9 @@ func (a *AnalyzeHostMemory) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostMemory) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostMemory) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
contents, err := getCollectedFileContents(collect.HostMemoryPath)
|
||||
|
||||
@@ -170,7 +170,7 @@ func TestAnalyzeHostMemory(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostMemory{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostMemory{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
@@ -233,7 +233,7 @@ func TestHostMemoryAnalyze(t *testing.T) {
|
||||
Outcomes: tc.outcomes,
|
||||
},
|
||||
}
|
||||
results, err := analyzer.Analyze(fn)
|
||||
results, err := analyzer.Analyze(fn, nil)
|
||||
if tc.wantErr {
|
||||
require.NotNil(t, err)
|
||||
return
|
||||
|
||||
@@ -24,7 +24,9 @@ func (a *AnalyzeHostOS) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostOS) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostOS) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
|
||||
result := AnalyzeResult{}
|
||||
result.Title = a.Title()
|
||||
|
||||
@@ -332,7 +332,7 @@ func TestAnalyzeHostOS(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostOS{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostOS{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
@@ -22,7 +22,9 @@ func (a *AnalyzeHostServices) IsExcluded() (bool, error) {
|
||||
return isExcluded(a.hostAnalyzer.Exclude)
|
||||
}
|
||||
|
||||
func (a *AnalyzeHostServices) Analyze(getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
|
||||
func (a *AnalyzeHostServices) Analyze(
|
||||
getCollectedFileContents func(string) ([]byte, error), findFiles getChildCollectedFileContents,
|
||||
) ([]*AnalyzeResult, error) {
|
||||
hostAnalyzer := a.hostAnalyzer
|
||||
|
||||
contents, err := getCollectedFileContents(collect.HostServicesPath)
|
||||
|
||||
@@ -93,7 +93,7 @@ func TestAnalyzeHostServices(t *testing.T) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
result, err := (&AnalyzeHostServices{test.hostAnalyzer}).Analyze(getCollectedFileContents)
|
||||
result, err := (&AnalyzeHostServices{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
|
||||
if test.expectErr {
|
||||
req.Error(err)
|
||||
} else {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user