Compare commits

..
103 Commits
Author SHA1 Message Date
dependabot[bot]andlnx01 c079d96efe chore(deps): bump github.com/microsoft/go-mssqldb from 1.5.0 to 1.6.0 (#1335)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 1.5.0 to 1.6.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v1.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-16 08:20:16 +12:00
dependabot[bot]andlnx01 7b797b3725 chore(deps): bump sigs.k8s.io/controller-runtime from 0.15.1 to 0.16.1 (#1336)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.15.1 to 0.16.1.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.15.1...v0.16.1)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-16 07:38:58 +12:00
Diamon Wiggins 6cbe188abe Fix incorrect result URI for pass and warn outcomes in common status analyzer (#1333)
* fix result URI
* revert examples
* fix warn outcome
2023-09-16 07:36:58 +12:00
Evans Mungai 86279b4ec4 chore(redactors): memory consumption improvements (#1332)
* Document additional go tool profiling flags

* Add a regex cache to avoid compiling regular expressions all the time

* Reduce max buffer capacity

* Prefer bytes to strings

Strings are immutable and hence we need to create a new one
all the time when operation on them

* Some more changes

* More bytes

* Use writer.Write instead of fmt.FPrintf

* Clear regex cache when resetting redactors

* Logs errors when redactors error since they get swallowed

* Add an improvement comment

* Limit the number of goroutines spawned when redacting

* Minor improvement

* Write byte slices one at a time instead of concatenating them first

* Add a test for writeBytes

* Additional tests
2023-09-15 13:09:21 -04:00
Evans Mungai 514c86d891 fix: use duration strings for http collector timeout (#1338)
* fix: use duration strings for http collector timeout

This follows the same format that all other collectors use.

* Update from PR comment
2023-09-13 19:18:03 -04:00
Evans Mungai b9f4fc4390 feat: Dry run flag to print preflight specs to std out (#1240) 2023-09-12 14:42:10 +01:00
dependabot[bot]andlnx01 53813502de chore(deps): bump goreleaser/goreleaser-action from 4 to 5 (#1334)
Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4 to 5.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-12 14:04:26 +12:00
dependabot[bot]andlnx01 597fb2996b chore(deps): bump github.com/cyphar/filepath-securejoin from 0.2.3 to 0.2.4 in /examples/sdk/helm-template (#1330)
chore(deps): bump github.com/cyphar/filepath-securejoin

Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.3 to 0.2.4.
- [Release notes](https://github.com/cyphar/filepath-securejoin/releases)
- [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4)

---
updated-dependencies:
- dependency-name: github.com/cyphar/filepath-securejoin
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 12:22:21 +01:00
dependabot[bot]andlnx01 e44aff4100 chore(deps): bump github.com/cyphar/filepath-securejoin from 0.2.3 to 0.2.4 (#1329)
chore(deps): bump github.com/cyphar/filepath-securejoin

Bumps [github.com/cyphar/filepath-securejoin](https://github.com/cyphar/filepath-securejoin) from 0.2.3 to 0.2.4.
- [Release notes](https://github.com/cyphar/filepath-securejoin/releases)
- [Commits](https://github.com/cyphar/filepath-securejoin/compare/v0.2.3...v0.2.4)

---
updated-dependencies:
- dependency-name: github.com/cyphar/filepath-securejoin
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-08 12:22:04 +01:00
dependabot[bot]andlnx01 d0d6f00c0f chore(deps): bump github.com/shirou/gopsutil/v3 from 3.23.7 to 3.23.8 (#1327)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.7 to 3.23.8.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.7...v3.23.8)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 14:29:21 +12:00
dependabot[bot]andlnx01 4460e8c639 chore(deps): bump golang.org/x/text from 0.12.0 to 0.13.0 (#1326)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.12.0 to 0.13.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.12.0...v0.13.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 14:28:56 +12:00
dependabot[bot]andlnx01 c166d46af4 chore(deps): bump sigs.k8s.io/e2e-framework from 0.2.0 to 0.3.0 (#1325)
Bumps [sigs.k8s.io/e2e-framework](https://github.com/kubernetes-sigs/e2e-framework) from 0.2.0 to 0.3.0.
- [Release notes](https://github.com/kubernetes-sigs/e2e-framework/releases)
- [Changelog](https://github.com/kubernetes-sigs/e2e-framework/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/e2e-framework/compare/v0.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/e2e-framework
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 14:28:35 +12:00
dependabot[bot]andlnx01 ded1f42b5a chore(deps): bump actions/checkout from 3 to 4 (#1324)
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-05 11:31:53 +12:00
Xav Paice 32176178a8 chore: update k8s.io to v0.28.1 (#1323)
* chore: update k8s.io to v0.28.1
* Update schemas following k8s.io deps update
2023-09-05 10:29:35 +12:00
Xav Paice 949b645336 chore: Update Go version in CONTRIBUTING.md (#1322)
Update Go version in CONTRIBUTING.md
2023-09-05 09:34:10 +12:00
Xav Paice 1f50fe3163 chore: update Go to 1.20 (#1321) 2023-09-04 18:40:28 +12:00
Archit Sharma 24c6278e5d add http collector timeouts; fixes #1064 (#1310)
* feat(collector): add http method timeouts (#1064)

Signed-off-by: Archit Sharma <archit@replicated.com>

* feat(collector) add schema updates for the http timeout (#1064)

Signed-off-by: Archit Sharma <archit@replicated.com>

* feat(collector): refactor HTTP method calls (#1064)

Signed-off-by: Archit Sharma <archit@replicated.com>

* feat(collector): add tests for HTTP type collector (#1064)

Signed-off-by: Archit Sharma <archit@replicated.com>

---------

Signed-off-by: Archit Sharma <archit@replicated.com>
2023-09-01 19:08:22 +05:30
Nick Meyer 8d527ead8c Replace FOSSA with Trivy (#1320) 2023-09-01 10:19:09 +12:00
dependabot[bot]andlnx01 1dedbcd67a chore(deps): bump go.opentelemetry.io/otel/sdk from 1.16.0 to 1.17.0 (#1318)
Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.16.0 to 1.17.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-30 14:12:19 +01:00
Evans Mungai ff03bfa9cd chore: make spec loaders internal APIs (#1313)
* chore: make specs an internal package

* Some minor improvements

* Use LoadClusterSpecs in support bundle implementation

* Remove change accidentally committed

* Use LoadFromCLIArgs in preflight CLI implementation

* Update comment

* Fix edge case where the label selector is an empty string

* Fix failing test
2023-08-30 14:02:30 +01:00
Dexter Yan b7d5a9876c feat(collector): add helm collector (#1309) 2023-08-28 11:51:57 +12:00
Evans Mungai 96c482a1f5 fix: complete mssql analyser implementation (#1290)
* fix: complete mssql analyser implementation

* Add mssql analyser tests and mssql collector logs

* Close mssql db after collecting data
2023-08-25 10:38:39 +01:00
ada mancini 543931631b Local watch script (#1304)
* local watch script for building troubleshoot
2023-08-25 15:12:22 +12:00
Dexter Yan d730be0fae feat(redact): use a scan regex for default redact rule of lines to improve cpu usage and reduce time cost (#1291) 2023-08-25 15:11:04 +12:00
Dexter Yan 38ff340883 feat(e2e): add e2e go test for support-bundler (#1265) 2023-08-25 14:43:09 +12:00
Dexter YanandEvans Mungai 04f69b3f8c fix(json_compare): solve unorderd slice deep equal (#1300)
* fix(json_compare): sort slice

* fix(json_compare): improve

* fix(json_compare): remove duplicated tests

---------

Co-authored-by: Evans Mungai <evans@replicated.com>
2023-08-24 11:48:33 +01:00
dependabot[bot]andlnx01 57b988b100 chore(deps): bump github.com/google/uuid from 1.3.0 to 1.3.1 (#1306)
Bumps [github.com/google/uuid](https://github.com/google/uuid) from 1.3.0 to 1.3.1.
- [Release notes](https://github.com/google/uuid/releases)
- [Changelog](https://github.com/google/uuid/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/uuid/compare/v1.3.0...v1.3.1)

---
updated-dependencies:
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-24 10:02:16 +01:00
dependabot[bot]andlnx01 6972789bea chore(deps): bump sigs.k8s.io/controller-runtime from 0.15.0 to 0.15.1 (#1299)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.15.0 to 0.15.1.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.15.0...v0.15.1)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-15 12:43:27 +12:00
Dexter Yan 17cbc16e05 feat(support-bundler): add leases, configmaps, service accounts and volume attachments for cluster resources collector (#1266) 2023-08-14 18:14:38 +12:00
dependabot[bot]andlnx01 87404982fe chore(deps): bump github.com/microsoft/go-mssqldb from 1.4.0 to 1.5.0 (#1296)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-09 16:03:28 +01:00
Dexter Yan 5bb4358f7a Fix(support-bundle): improve copy from host collector performance by checking daemonset pod FailedMount event and retry (#1281) 2023-08-09 22:32:14 +12:00
Pavan Sokke Nagaraj 39314ef200 chore: export error ErrInsufficientPermissionsToRun and func ShowTextResultsStructured (#1297)
* chore: move ErrInsufficientPermissions to collect

* chore: export func ShowTextResultsStructured

* chore: rename to ErrInsufficientPermissionsToRun
2023-08-08 14:17:15 -04:00
73c7dba0e1 chore(deps): bump github.com/jackc/pgx/v5 from 5.4.2 to 5.4.3 (#1294)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.4.2 to 5.4.3.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.4.2...v5.4.3)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nathan Sullivan <nathans@replicated.com>
2023-08-08 13:10:42 +10:00
dependabot[bot]andlnx01 a8f8bf9257 chore(deps): bump golang.org/x/text from 0.11.0 to 0.12.0 (#1293)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.11.0 to 0.12.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.11.0...v0.12.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-08 12:59:46 +10:00
dependabot[bot]andlnx01 08c37c7333 chore(deps): bump github.com/shirou/gopsutil/v3 from 3.23.6 to 3.23.7 (#1287)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.6 to 3.23.7.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.6...v3.23.7)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-02 07:09:28 +12:00
dependabot[bot]andlnx01 8f20b665f9 chore(deps): bump github.com/hashicorp/go-getter from 1.7.1 to 1.7.2 (#1286)
Bumps [github.com/hashicorp/go-getter](https://github.com/hashicorp/go-getter) from 1.7.1 to 1.7.2.
- [Release notes](https://github.com/hashicorp/go-getter/releases)
- [Changelog](https://github.com/hashicorp/go-getter/blob/main/.goreleaser.yml)
- [Commits](https://github.com/hashicorp/go-getter/compare/v1.7.1...v1.7.2)

---
updated-dependencies:
- dependency-name: github.com/hashicorp/go-getter
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-08-01 16:13:00 +10:00
dependabot[bot]andlnx01 638d99eaad chore(deps): bump github.com/microsoft/go-mssqldb from 1.3.0 to 1.4.0 (#1283)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-26 15:35:35 +01:00
dependabot[bot]andlnx01 25ddcf4388 chore(deps): bump k8s.io/apiserver from 0.27.3 to 0.27.4 (#1284)
Bumps [k8s.io/apiserver](https://github.com/kubernetes/apiserver) from 0.27.3 to 0.27.4.
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.27.3...v0.27.4)

---
updated-dependencies:
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-26 08:56:09 +10:00
Dexter YanandEvans Mungai 31ccbf696c Fix(test): add unit tests for util (#1273)
* feat(test): add test for util

* fix(test): add windows path test

---------

Co-authored-by: Evans Mungai <evans@replicated.com>
2023-07-24 13:51:49 +12:00
a068561af4 chore(deps): bump k8s.io/metrics from 0.27.3 to 0.27.4 (#1276)
Bumps [k8s.io/metrics](https://github.com/kubernetes/metrics) from 0.27.3 to 0.27.4.
- [Commits](https://github.com/kubernetes/metrics/compare/v0.27.3...v0.27.4)

---
updated-dependencies:
- dependency-name: k8s.io/metrics
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evans Mungai <evans@replicated.com>
2023-07-21 10:25:08 +01:00
Evans Mungai f3777bef69 feat: Add Strict flag to LoadSpecs API (#1279)
* feat: Add Strict flag to LoadSpecs API

Strict flag which can be used to toggle between true
(raising errors if a document is invalid)
and false (ignoring invalid documents, perhaps logging a warning).

* Granular error handling multidocs in secrets and configmaps

* Fix failing test
2023-07-21 10:08:16 +01:00
dependabot[bot]andlnx01 addc2ce925 chore(deps): bump k8s.io/cli-runtime from 0.27.3 to 0.27.4 (#1278)
Bumps [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) from 0.27.3 to 0.27.4.
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.27.3...v0.27.4)

---
updated-dependencies:
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-21 08:10:25 +10:00
dependabot[bot]andlnx01 247c60afd2 chore(deps): bump github.com/jackc/pgx/v5 from 5.4.1 to 5.4.2 (#1268)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.4.1 to 5.4.2.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.4.1...v5.4.2)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-20 15:55:17 +01:00
Dan Jones 8237ac991c fix: fixes #1270 (#1271)
* fix: fixes #1270
2023-07-20 13:08:31 +12:00
Evans Mungai 73201c0304 feat: Add regex host analyser (#1267)
* feat: Add regular expressions host anaylser

This anaylser is the same as the in-cluster text anaylser. You pass in
search expressions to find values in files collected in a bundle

* additional test assertion to check analyser warn
2023-07-18 07:18:53 +12:00
Dexter Yan 531edf42e2 feat(support-bundle): add host certificate collector and analyzer (#1132) 2023-07-17 17:05:05 +12:00
Dexter Yan f69ae77bc3 feat(analyzer): add detailed message for unhealthy pod (#1261)
* feat(analyzer): add detailed message for unhealthy pod
2023-07-17 08:01:40 +12:00
David Morgan b02d12ff1e JSONPath support for json compare analyzer (#1244)
This adds JSONPath support to the json compare analyzer using
k8s.io/client-go/util/jsonpath implementation.

To preserve backwards compatibility a new attribute, `JsonPath, is added
to the compare analyzer as opposed to changing how `Path` works. Only
one should be set, but preference is given to `Path`, again to maintain
backwards compatibility.

As a convience for users, if the result of running the JSONPath
expression returns a single value, that value is unwrapped from its
enclosing array and used as the comparison with `Value`. This isn't
strictly compatible with how JSONPath works (all results are wrapped in
an array), but it's easier for end users who are expecting a single
result from their JSONPath expression.
2023-07-10 13:02:00 -04:00
Martin Hrabovcin 24822b7f95 fix(collector): cluster-resources PV filename pattern (#1262) 2023-07-10 12:53:56 -04:00
Dexter Yan 784918e7ee feat(preflight): adding warning message when validating the content of preflight and host preflight spec (#1250) 2023-07-06 16:10:16 +12:00
819dd5fc26 chore(deps): bump github.com/mitchellh/go-wordwrap from 1.0.0 to 1.0.1 (#1260)
Bumps [github.com/mitchellh/go-wordwrap](https://github.com/mitchellh/go-wordwrap) from 1.0.0 to 1.0.1.
- [Commits](https://github.com/mitchellh/go-wordwrap/compare/v1.0.0...v1.0.1)

---
updated-dependencies:
- dependency-name: github.com/mitchellh/go-wordwrap
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Nathan Sullivan <nathans@replicated.com>
2023-07-06 15:53:25 +12:00
dependabot[bot]andlnx01 27e06517bf chore(deps): bump golang.org/x/text from 0.10.0 to 0.11.0 (#1259)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.10.0 to 0.11.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.10.0...v0.11.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-06 13:11:44 +10:00
dependabot[bot]andlnx01 d14e0dd18c chore(deps): bump github.com/shirou/gopsutil/v3 from 3.23.5 to 3.23.6 (#1258)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.5 to 3.23.6.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.5...v3.23.6)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-06 14:55:10 +12:00
dependabot[bot]andlnx01 d7b3dd8abb chore(deps): bump github.com/microsoft/go-mssqldb from 1.1.0 to 1.3.0 (#1255)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 1.1.0 to 1.3.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v1.1.0...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-07-06 14:52:41 +12:00
Evans Mungai f64d98b5c3 feat(examples): loading troubleshoot specs from helm chart example (#1252)
* feat(examples): loading troubleshoot specs from helm chart example
2023-06-29 13:31:59 +12:00
Dexter Yan f0efbf658a fix(message): solve the terminal UI issue of truncating the message if it is long (#1242) 2023-06-28 11:06:15 +12:00
dependabot[bot]andlnx01 ec2d14a7ad chore(deps): bump k8s.io/apiserver from 0.27.2 to 0.27.3 (#1247)
Bumps [k8s.io/apiserver](https://github.com/kubernetes/apiserver) from 0.27.2 to 0.27.3.
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.27.2...v0.27.3)

---
updated-dependencies:
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 10:56:02 +01:00
dependabot[bot]andlnx01 6385a1247f chore(deps): bump k8s.io/cli-runtime from 0.27.2 to 0.27.3 (#1246)
Bumps [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) from 0.27.2 to 0.27.3.
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.27.2...v0.27.3)

---
updated-dependencies:
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 10:38:34 +01:00
dependabot[bot]andlnx01 80a946d0c2 chore(deps): bump golang.org/x/sync from 0.2.0 to 0.3.0 (#1245)
Bumps [golang.org/x/sync](https://github.com/golang/sync) from 0.2.0 to 0.3.0.
- [Commits](https://github.com/golang/sync/compare/v0.2.0...v0.3.0)

---
updated-dependencies:
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-27 10:38:05 +01:00
ada mancini 58c428347e get cluster-resources even if negotiating RBAC fails (#1243)
* log errors negotiating and set ignoreRBAC when authorizer webhooks would fail
2023-06-27 15:07:08 +12:00
Xav Paice 2c6b1869e2 feat: add test for HostPreflight spec read (#1227) 2023-06-22 14:56:19 +01:00
Evans Mungai 944da4543a chore: Upgrade sigstore and goreleaser binaries (#1104)
* chore: Upgrade sigstore and goreleaser binaries
* Pin to goreleaser's v1 major versions
2023-06-21 07:07:48 +12:00
dependabot[bot]andlnx01 e8340d54d4 chore(deps): bump golang.org/x/text from 0.9.0 to 0.10.0 (#1221)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.9.0 to 0.10.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.9.0...v0.10.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 12:30:17 +12:00
dependabot[bot]andlnx01 0fc92122d7 chore(deps): bump k8s.io/metrics from 0.27.2 to 0.27.3 (#1234)
Bumps [k8s.io/metrics](https://github.com/kubernetes/metrics) from 0.27.2 to 0.27.3.
- [Commits](https://github.com/kubernetes/metrics/compare/v0.27.2...v0.27.3)

---
updated-dependencies:
- dependency-name: k8s.io/metrics
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 12:29:38 +12:00
dependabot[bot]andlnx01 f7f5604734 chore(deps): bump k8s.io/api from 0.27.2 to 0.27.3 (#1232)
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.27.2 to 0.27.3.
- [Commits](https://github.com/kubernetes/api/compare/v0.27.2...v0.27.3)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 12:18:29 +12:00
dependabot[bot]andlnx01 de44c21efa chore(deps): bump github.com/jackc/pgx/v5 from 5.3.1 to 5.4.1 (#1231)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.3.1 to 5.4.1.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.3.1...v5.4.1)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-20 12:17:46 +12:00
Andrew Lavery 557a1381a9 explicitly test TCPConnectAnalyze unconditional fallthrough behavior (#1226) 2023-06-16 15:01:41 +12:00
Dexter Yan fefe118943 feat(collector): checking existing service account before create running pod (#1222) 2023-06-15 15:39:18 +12:00
Dexter Yan 5b1e48258f fix(collector): solving pod stuck in terminating with CNI issue (#1196)
* feat(collector): add force delete for pods when they're done with in a collector
2023-06-15 13:59:59 +12:00
ada manciniandDiamon Wiggins 03c53cabd6 make ConfigMap collector namespace-optional (#1212)
* try to load default namespace from kubectl current context

* use  ns from kubectl context when no ns is given in the spec

* remove test prints

* Update pkg/collect/configmap.go

Co-authored-by: Diamon Wiggins <38189728+diamonwiggins@users.noreply.github.com>

---------

Co-authored-by: Diamon Wiggins <38189728+diamonwiggins@users.noreply.github.com>
2023-06-13 13:12:17 -04:00
David Rohnow a5628874b0 Add code to collect cluster endpoint data with cluster-resources collector (#1219)
added code to collect cluster endpoint data to cluster-resources collector
2023-06-13 16:33:52 +12:00
Ahmed Mousa 620fa75eb5 feat: add k8s custom metrics collector (#1174)
Collector that collects custom k8s metrics from custom.metrics.k8s.io/v1beta1/ and saves them in the bundle under the /metrics directory
2023-06-09 10:26:03 +01:00
David Rohnow 60d5b686cc Add Daemonset collection to cluster_resources (#1213)
* added daemonset collection to cluster_resources

* squash commit to remove commit that was submitted by root
2023-06-08 16:05:54 -07:00
Dexter Yan f9dbccd354 feat(support-bundle): add support labels for troubleshoot.io and troubleshoot.sh (#1203) 2023-06-08 16:05:35 +01:00
Evans Mungai 08a1075d82 chore: remove unnecessary logrus dependency (#1214)
The troubleshoot project uses klog logging library. There is room for
only one library unfortunately. Sorry logrus :)
2023-06-08 10:43:08 -04:00
dependabot[bot]andlnx01 0a855f26c2 chore(deps): bump github.com/spf13/viper from 1.15.0 to 1.16.0 (#1209)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/viper
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:54:19 +01:00
danj-replicatedandNathan Sullivan 0d1e23651a Add ability for Cluster resources analyzer to do number and size comparison (#1210)
* make CR analyzer compare ints and sizes

* schemas

* typo

* more comments

* tests for cluster resources analyzer doing number/size comparisons

* switch from humanize to k8s size parsing

* schemas

---------

Co-authored-by: Nathan Sullivan <nathans@replicated.com>
2023-06-08 07:51:11 -04:00
dependabot[bot]andlnx01 70f0e071dd chore(deps): bump github.com/shirou/gopsutil/v3 from 3.23.4 to 3.23.5 (#1208)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.4 to 3.23.5.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.4...v3.23.5)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-08 12:17:06 +01:00
5add5d6f9d chore(deps): bump github.com/microsoft/go-mssqldb from 1.0.0 to 1.1.0 (#1207)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 1.0.0 to 1.1.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v1.0.0...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evans Mungai <evans@replicated.com>
2023-06-08 11:45:19 +01:00
191e002a9b chore(deps): bump github.com/sirupsen/logrus from 1.9.0 to 1.9.3 (#1206)
Bumps [github.com/sirupsen/logrus](https://github.com/sirupsen/logrus) from 1.9.0 to 1.9.3.
- [Release notes](https://github.com/sirupsen/logrus/releases)
- [Changelog](https://github.com/sirupsen/logrus/blob/master/CHANGELOG.md)
- [Commits](https://github.com/sirupsen/logrus/compare/v1.9.0...v1.9.3)

---
updated-dependencies:
- dependency-name: github.com/sirupsen/logrus
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evans Mungai <evans@replicated.com>
2023-06-08 11:44:35 +01:00
fbacd055cd chore(deps): bump github.com/stretchr/testify from 1.8.3 to 1.8.4 (#1205)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.3 to 1.8.4.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.3...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evans Mungai <evans@replicated.com>
2023-06-08 11:44:06 +01:00
Evans Mungai 401dfe2c57 feat: add loader APIs to load specs from raw troubleshoot spec (#1202)
* feat: add loader APIs to load specs from a list of yaml docs

The change introduces a loader package that will contain loader
public APIs. The aim of these APIs will be to, given any source of
troubleshoot specs, the loaders will fetch the specs and parse out
all troubleshoot objects that can be extracted.

* Some refactoring

* Some more changes

* More changes caught when testing vendor portal

* Add tests and rename Troubleshoot kinds struct

* Additional test

* Handle ConfigMap and Secrets with multiple specs in them

* Fix failing test

* Revert multidoc split implementation

* Fix merge conflict

* Change LoadFromXXX functions to a single LoadSpecs function
2023-06-06 16:48:29 -04:00
Evans Mungai 145bad7e8e chore: add make target to build all binaries together (#1211)
Add make build target that builds all troubleshoot binaries in parallel
using -j make flag that lets make run all make sub-targets as separate jobs
2023-06-06 10:15:28 -04:00
Xav Paice a3b7975690 Update the preflight secret label to troubleshoot.sh/kind (#1204)
Partial-fix: #1070

Changes the default label for preflights to troubleshoot.sh/kind: preflight
2023-06-06 07:19:49 +12:00
ada mancini 41cd7c2aa4 watchrsync job to push binaries to a test machine (#1158)
* ignore some more stuff

* watchrsync make command like kurl project

* document watchrsync

* the actual watchrsync script

* dont need these for npm dependencies

* Revert "dont need these for npm dependencies"

This reverts commit bdb4e62c38.

* install gaze-run-interrupt with make

* watchrsync instructions
2023-06-05 10:35:25 -04:00
Dexter Yan 2b8e3fb6bb fix(collector): removed unused name in certificates collector (#1200) 2023-06-01 09:46:34 +01:00
Evans Mungai 27c68a7e53 chore: update deprecated trivy cli option (#1197) 2023-05-31 10:49:58 -04:00
dependabot[bot]andlnx01 8fb417a896 chore(deps): bump go.opentelemetry.io/otel/sdk from 1.15.1 to 1.16.0 (#1191)
Bumps [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) from 1.15.1 to 1.16.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.15.1...v1.16.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-31 09:04:13 +01:00
dependabot[bot]andlnx01 88022bb67b chore(deps): bump github.com/mattn/go-isatty from 0.0.18 to 0.0.19 (#1192)
Bumps [github.com/mattn/go-isatty](https://github.com/mattn/go-isatty) from 0.0.18 to 0.0.19.
- [Commits](https://github.com/mattn/go-isatty/compare/v0.0.18...v0.0.19)

---
updated-dependencies:
- dependency-name: github.com/mattn/go-isatty
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-31 09:01:30 +01:00
dependabot[bot]andlnx01 7304c9f20d chore(deps): bump github.com/microsoft/go-mssqldb from 0.21.0 to 1.0.0 (#1193)
Bumps [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) from 0.21.0 to 1.0.0.
- [Release notes](https://github.com/microsoft/go-mssqldb/releases)
- [Changelog](https://github.com/microsoft/go-mssqldb/blob/main/CHANGELOG.md)
- [Commits](https://github.com/microsoft/go-mssqldb/compare/v0.21.0...v1.0.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-31 17:08:12 +12:00
dependabot[bot]andlnx01 097d20edcb chore(deps): bump sigs.k8s.io/controller-runtime from 0.14.6 to 0.15.0 (#1190)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.14.6 to 0.15.0.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Changelog](https://github.com/kubernetes-sigs/controller-runtime/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.14.6...v0.15.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-31 17:06:56 +12:00
Diamon Wiggins 3b61b3025e Add regex to clusterResources analyzer (#1189)
* similar to the textAnalyze analyzer, adds support to evaluate the value at the specified yamlPath with regex or regexGroups
* fixes a typo in the shorthand name used for searching for cluster resource PVC objects
2023-05-30 17:53:03 -04:00
Xav Paice 6a9ad7842d Update preflight e2e test (#1187)
Replace the `run` collector (deprecated) with `runPod`.
2023-05-29 11:56:45 -04:00
Dexter Yan 830e357b48 fix(analyzer): fix clusterResource analyzer always uses the first object found (#1185)
* fix(analyzer): fix clusterResource analyzer  always uses the first object found
2023-05-29 17:26:37 +12:00
Dexter Yan acb1099bda feat(analyzer): add certificate analyzer (#1128)
* feat(analyzer): add cert analyzer
* feat(analyzer): add certificates tests
2023-05-29 16:40:10 +12:00
Diamon WigginsandEvans Mungai 091c4dc134 Capture runPod status and events before deleting the pod (#1172)
* adding savepoddetails function to capture runpod describe output
* update output paths for static-hi.log

---------

Co-authored-by: Evans Mungai <evans@replicated.com>
2023-05-29 10:37:27 +12:00
Evans Mungai 1939f5464d fix (support-bundle): Ensure specs are merged correctly (#1181)
When the support-bundle cli is used with --load-cluster-specs,
not all discovered specs are merged into the spec used to collect
data.

Fixes: #1179
2023-05-26 13:43:57 +01:00
dependabot[bot]andlnx01 1aeec3fa74 chore(deps): bump k8s.io/cli-runtime from 0.27.1 to 0.27.2 (#1170)
Bumps [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) from 0.27.1 to 0.27.2.
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.27.1...v0.27.2)

---
updated-dependencies:
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 13:06:14 +01:00
349fa746cc chore(deps): bump k8s.io/apiserver from 0.27.1 to 0.27.2 (#1168)
* chore(deps): bump k8s.io/apiserver from 0.27.1 to 0.27.2

Bumps [k8s.io/apiserver](https://github.com/kubernetes/apiserver) from 0.27.1 to 0.27.2.
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.27.1...v0.27.2)

---
updated-dependencies:
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Generate CRD schemas

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Evans Mungai <evans@replicated.com>
2023-05-23 12:40:31 +01:00
dependabot[bot]andlnx01 380522a5f7 chore(deps): bump go.opentelemetry.io/otel from 1.15.1 to 1.16.0 (#1169)
Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.15.1 to 1.16.0.
- [Release notes](https://github.com/open-telemetry/opentelemetry-go/releases)
- [Changelog](https://github.com/open-telemetry/opentelemetry-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/open-telemetry/opentelemetry-go/compare/v1.15.1...v1.16.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-23 12:22:06 +01:00
Martin Hrabovcin 51f626b994 fix(collector): cluster resource file names (#1165)
* fix(collector): use correct path for custom resources

* fix(collector): cluster role resource names
2023-05-23 10:11:45 +01:00
Martin Hrabovcin e22c7d7eca feat(collector): add priority class resources (#1159)
* feat(collector): add priority classes resources

* chore: use priorityclasses filename
2023-05-18 12:21:06 +01:00
Ethan Mosbaugh af4cc8a08a fix: simplify logs collector by removing goroutine which had a concurrency bug (#1155)
* fix: logs collector timeout prevent concurrent map iteration and map write

* remove goroutine

* log pod logs timeout
2023-05-18 07:43:47 +01:00
242 changed files with 22260 additions and 1849 deletions
-4
View File
@@ -1,4 +0,0 @@
version: 3
project:
id: github.com/replicatedhq/troubleshoot
+53 -25
View File
@@ -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:
@@ -162,18 +162,24 @@ jobs:
- run: chmod +x bin/preflight
- run: make preflight-e2e-test
run-examples:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: make run-examples
compile-supportbundle:
runs-on: ubuntu-latest
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:
@@ -184,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:
@@ -203,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:
@@ -216,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:
@@ -246,16 +273,16 @@ jobs:
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
@@ -272,7 +299,7 @@ jobs:
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
fetch-depth: 0
@@ -283,11 +310,12 @@ jobs:
- uses: actions/setup-go@v4
with:
go-version: "1.19"
go-version: "1.20"
- uses: sigstore/cosign-installer@main
- uses: sigstore/cosign-installer@v3
with:
cosign-release: "v1.2.1"
# DO NOT USE v2 until we decide on whether to use Rekor or not
cosign-release: "v1.13.1" # Binary version to install
- name: Get Cosign Key
run: |
@@ -303,9 +331,9 @@ jobs:
COSIGN_KEY: ${{ secrets.COSIGN_KEY }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v4
uses: goreleaser/goreleaser-action@v5
with:
version: "v0.183.0"
version: "v1.x" # Binary version to install
args: release --rm-dist --config deploy/.goreleaser.yaml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -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
-49
View File
@@ -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
+42
View File
@@ -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 .
+3
View File
@@ -7,6 +7,7 @@
*.dylib
bin
.DS_Store
node_modules/
# Test binary, build with `go test -c`
*.test
@@ -26,6 +27,8 @@ vendor
*.swp
*.swo
*~
.envrc
dist
try.sh
+39 -1
View File
@@ -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,33 @@ 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`
2. Export `REMOTES=<user>@<ip>` so that `watchrsync` knows where to sync.
3. Maybe run `export GOOS=linux` and `export GOARCH=amd64` so that you build Linux binaries.
4. run `make watchrsync` to build and sync binaries automatically on saving.
```
ssh-add --apple-use-keychain ~/.ssh/google_compute_engine
export REMOTES=ada@35.229.61.56
export GOOS=linux
export GOARCH=amd64
make watchrsync
# bin/watchrsync.js
# make support-bundle
# go build -tags "netgo containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" -installsuffix netgo -ldflags " -s -w -X github.com/replicatedhq/troubleshoot/pkg/version.version=`git describe --tags --dirty` -X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA=`git rev-parse HEAD` -X github.com/replicatedhq/troubleshoot/pkg/version.buildTime=`date -u +"%Y-%m-%dT%H:%M:%SZ"` " -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
# rsync bin/support-bundle ada@35.229.61.56:
# date
# Tue May 16 14:14:13 EDT 2023
# synced
```
### Testing
To run the tests locally run the following:
@@ -54,17 +81,25 @@ A running Kubernetes cluster as well as `jq` are required to run e2e tests.
You are able to collect CPU & memory runtime properties and store the data for analysis in a file. To do so, pass in the file paths using `--cpuprofile` and `--memprofile` flags in the CLI. Once you have your data collected, you can analyse it using [pprof visualization tool](https://github.com/google/pprof/blob/main/doc/README.md). Here is how
Run support bundle and with CPU & memory profile flags
```sh
./bin/support-bundle examples/support-bundle/sample-supportbundle.yaml --cpuprofile=cpu.prof --memprofile=mem.prof
```
Visualize using [pprof](https://github.com/google/pprof/blob/main/doc/README.md)
```sh
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
@@ -76,16 +111,19 @@ This is a rough outline of how to prepare a contribution:
- Make commits of logical units.
- When your changes are ready to merge, squash your history to 1 commit.
- For example, if you want to squash your last 3 commits and write a new commit message:
```
git reset --soft HEAD~3 &&
git commit
```
- If you want to keep the previous commit messages and concatenate them all into a new commit, you can do something like this instead:
```
git reset --soft HEAD~3 &&
git commit --edit -m"$(git log --format=%B --reverse HEAD..HEAD@{1})"
```
- Push your changes to a topic branch in your fork of the repository.
- Submit a pull request to the original repository. It will be reviewed in a timely manner.
+35 -2
View File
@@ -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
@@ -62,10 +64,27 @@ test-integration:
preflight-e2e-test:
./test/validate-preflight-e2e.sh
.PHONY: run-examples
run-examples:
./test/run-examples.sh
.PHONY: support-bundle-e2e-test
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
.PHONY: support-bundle
support-bundle:
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
@@ -207,7 +226,7 @@ longhorn:
.PHONY: scan
scan:
trivy fs \
--security-checks vuln \
--scanners vuln \
--exit-code=1 \
--severity="HIGH,CRITICAL" \
--ignore-unfixed \
@@ -220,3 +239,17 @@ lint: fmt vet
.PHONY: lint-and-fix
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
bin/watchrsync.js
.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
+8 -1
View File
@@ -61,7 +61,14 @@ A signed SBOM that includes Troubleshoot dependencies is included in each relea
The following example illustrates using [cosign](https://github.com/sigstore/cosign) to verify that **troubleshoot-sbom.tgz** has
not been tampered with.
```
```sh
$ cosign verify-blob --key key.pub --signature troubleshoot-sbom.tgz.sig troubleshoot-sbom.tgz
Verified OK
```
If you were to get an error similar to the one below, it means you are verifying an SBOM signed using cosign `v1` using a newer `v2` of the binary. This version introduced [breaking changes](https://github.com/sigstore/cosign/blob/main/CHANGELOG.md#breaking-changes) which require an additional flag `--insecure-ignore-tlog=true` to successfully verify SBOMs like so.
```sh
$ cosign verify-blob --key key.pub --signature troubleshoot-sbom.tgz.sig troubleshoot-sbom.tgz --insecure-ignore-tlog=true
WARNING: Skipping tlog verification is an insecure practice that lacks of transparency and auditability verification for the blob.
Verified OK
```
Executable
+42
View File
@@ -0,0 +1,42 @@
#!/usr/bin/env node
const gri = require('gaze-run-interrupt');
const binList = [
// 'bin/analyze',
// 'bin/preflight',
'bin/support-bundle',
// 'bin/collect'
]
const makeList = [
// 'analyze',
// 'preflight',
'support-bundle',
// 'collect'
]
const commands = [
// {
// command: 'rm',
// args: binList,
// },
{
command: 'make',
args: makeList,
},
];
commands.push({
command: "date",
args: [],
});
commands.push({
command: "echo",
args: ["synced"],
});
gri([
'cmd/**/*.go',
'pkg/**/*.go',
], commands);
+57
View File
@@ -0,0 +1,57 @@
#!/usr/bin/env node
const gri = require('gaze-run-interrupt');
if (!process.env.REMOTES) {
console.log("Usage: `REMOTES='user@h1.1.1.1,user@1.1.1.2' ./watchrsync.js`");
process.exit(1);
}
process.env.GOOS = 'linux';
process.env.GOARCH = 'amd64';
const binList = [
// 'bin/analyze',
// 'bin/preflight',
'bin/support-bundle',
// 'bin/collect'
]
const makeList = [
// 'analyze',
// 'preflight',
'support-bundle',
// 'collect'
]
const commands = [
// {
// command: 'rm',
// args: binList,
// },
{
command: 'make',
args: makeList,
},
];
process.env.REMOTES.split(",").forEach(function (remote) {
commands.push({
command: 'rsync',
args: binList.concat(`${remote}:`),
});
});
commands.push({
command: "date",
args: [],
});
commands.push({
command: "echo",
args: ["synced"],
});
gri([
'cmd/**/*.go',
'pkg/**/*.go',
], commands);
+3 -1
View File
@@ -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")
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"os"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/spf13/viper"
)
+2 -2
View File
@@ -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")
+1 -3
View File
@@ -10,10 +10,9 @@ import (
"time"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
@@ -88,7 +87,6 @@ func runCollect(v *viper.Viper, arg string) error {
multidocs := strings.Split(string(collectorContent), "\n---\n")
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
redactors, err := supportbundle.GetRedactorsFromURIs(v.GetStringSlice("redactors"))
-22
View File
@@ -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"
+6 -2
View File
@@ -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"
@@ -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
-23
View File
@@ -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
}
+1 -1
View File
@@ -7,7 +7,7 @@ import (
"net/http"
"os"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/spf13/cobra"
+19 -22
View File
@@ -7,11 +7,13 @@ import (
"path"
"time"
"github.com/mitchellh/go-wordwrap"
"github.com/pkg/errors"
ui "github.com/replicatedhq/termui/v3"
"github.com/replicatedhq/termui/v3/widgets"
"github.com/replicatedhq/troubleshoot/cmd/util"
"github.com/replicatedhq/troubleshoot/internal/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/constants"
)
var (
@@ -178,7 +180,10 @@ func drawDetails(analysisResult *analyzerunner.AnalyzeResult) {
currentTop := 4
title := widgets.NewParagraph()
title.Text = analysisResult.Title
// WrapText is set to false to prevent internal wordwrap which is not accounting for the padding
title.WrapText = false
// For long title that lead to wrapping text, the terminal width is divided by 2 and deducted by MESSAGE_TEXT_PADDING to account for the padding
title.Text = wordwrap.WrapString(analysisResult.Title, uint(termWidth/2-constants.MESSAGE_TEXT_PADDING))
title.Border = false
if analysisResult.IsPass {
title.TextStyle = ui.NewStyle(ui.ColorGreen, ui.ColorClear, ui.ModifierBold)
@@ -187,34 +192,26 @@ func drawDetails(analysisResult *analyzerunner.AnalyzeResult) {
} else if analysisResult.IsFail {
title.TextStyle = ui.NewStyle(ui.ColorRed, ui.ColorClear, ui.ModifierBold)
}
height := estimateNumberOfLines(title.Text, termWidth/2)
height := util.EstimateNumberOfLines(title.Text)
title.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(title)
currentTop = currentTop + height + 1
message := widgets.NewParagraph()
message.Text = analysisResult.Message
// WrapText is set to false to prevent internal wordwrap which is not accounting for the padding
message.WrapText = false
// For long text that lead to wrapping text, the terminal width is divided by 2 and deducted by MESSAGE_TEXT_PADDING to account for the padding
message.Text = wordwrap.WrapString(analysisResult.Message, uint(termWidth/2-constants.MESSAGE_TEXT_PADDING))
if analysisResult.URI != "" {
// Add URL to the message with wordwrap
// Add emply lines as separator
urlText := wordwrap.WrapString(fmt.Sprintf("For more information: %s", analysisResult.URI), uint(termWidth/2-constants.MESSAGE_TEXT_PADDING))
message.Text = message.Text + "\n\n" + urlText
}
height = util.EstimateNumberOfLines(message.Text) + constants.MESSAGE_TEXT_LINES_MARGIN_TO_BOTTOM
message.Border = false
height = estimateNumberOfLines(message.Text, termWidth/2) + 2
message.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(message)
currentTop = currentTop + height + 1
if analysisResult.URI != "" {
uri := widgets.NewParagraph()
uri.Text = fmt.Sprintf("For more information: %s", analysisResult.URI)
uri.Border = false
// For long urls that lead to wrapping text, make the rectangle bigger by
// increasing the calculated height by 2
height = estimateNumberOfLines(uri.Text, termWidth/2) + 2
uri.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(uri)
}
}
func estimateNumberOfLines(text string, width int) int {
lines := len(text)/width + 1
return lines
}
func showSaved(filename string) {
+3 -3
View File
@@ -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"
@@ -62,13 +62,13 @@ 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")
cmd.Flags().Bool("interactive", true, "enable/disable interactive mode")
cmd.Flags().Bool("collect-without-permissions", true, "always generate a support bundle, even if it some require additional permissions")
cmd.Flags().StringSliceP("selector", "l", []string{"troubleshoot.io/kind=support-bundle"}, "selector to filter on for loading additional support bundle specs found in secrets within the cluster")
cmd.Flags().StringSliceP("selector", "l", []string{"troubleshoot.sh/kind=support-bundle"}, "selector to filter on for loading additional support bundle specs found in secrets within the cluster")
cmd.Flags().Bool("load-cluster-specs", false, "enable/disable loading additional troubleshoot specs found within the cluster. required when no specs are provided on the command line")
cmd.Flags().String("since-time", "", "force pod logs collectors to return logs after a specific date (RFC3339)")
cmd.Flags().String("since", "", "force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.")
+18 -158
View File
@@ -17,26 +17,23 @@ import (
"github.com/fatih/color"
"github.com/mattn/go-isatty"
"github.com/pkg/errors"
privSpecs "github.com/replicatedhq/troubleshoot/internal/specs"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"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/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 {
ctx := context.Background()
if !v.GetBool("load-cluster-specs") && len(arg) < 1 {
return errors.New("flag load-cluster-specs must be set if no specs are provided on the command line")
}
@@ -79,7 +76,6 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
var mainBundle *troubleshootv1beta2.SupportBundle
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
additionalRedactors := &troubleshootv1beta2.Redactor{}
// Defining `v` below will render using `v` in reference to Viper unusable.
@@ -110,15 +106,21 @@ func runTroubleshoot(v *viper.Viper, arg []string) error {
}
if v.GetBool("load-cluster-specs") {
sbFromCluster, redactorsFromCluster, err := loadClusterSpecs()
kinds, err := loadClusterSpecs(ctx, v)
if err != nil {
return err
}
if sbFromCluster == nil {
return errors.New("no specs found in cluster")
if len(kinds.SupportBundlesV1Beta2) == 0 {
return errors.New("no support bundle specs found in cluster")
}
for _, sb := range kinds.SupportBundlesV1Beta2 {
sb := sb // Why? https://golang.org/doc/faq#closures_and_goroutines
mainBundle = supportbundle.ConcatSpec(mainBundle, &sb)
}
for _, redactor := range kinds.RedactorsV1Beta2 {
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactor.Spec.Redactors...)
}
mainBundle = supportbundle.ConcatSpec(mainBundle, sbFromCluster)
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorsFromCluster.Spec.Redactors...)
}
if mainBundle == nil {
@@ -259,160 +261,18 @@ the %s Admin Console to begin analysis.`
return nil
}
// loadClusterSpecs loads the support bundle and redactor specs from the cluster
// based on troubleshoot.io/kind=support-bundle label selector. 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) {
var parsedBundle *troubleshootv1beta2.SupportBundle
redactors := &troubleshootv1beta2.Redactor{}
v := viper.GetViper() // It's singleton, so we can use it anywhere
klog.Info("Discover troubleshoot specs from cluster")
labelSelector := strings.Join(v.GetStringSlice("selector"), ",")
parsedSelector, err := labels.Parse(labelSelector)
if err != nil {
return nil, nil, errors.Wrap(err, "unable to parse selector")
}
func loadClusterSpecs(ctx context.Context, v *viper.Viper) (*loader.TroubleshootKinds, error) {
config, err := k8sutil.GetRESTConfig()
if err != nil {
return nil, nil, errors.Wrap(err, "failed to convert kube flags to rest config")
return 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")
return 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")
}
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, 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)
}
}
}
var bundlesFromCluster []string
// Search cluster for support bundle specs
klog.V(1).Infof("Search support bundle specs from [%q] namespaces using %q selector", strings.Join(namespaces, ", "), parsedSelector.String())
for _, ns := range namespaces {
bundlesFromSecrets, err := specs.LoadFromSecretMatchingLabel(client, parsedSelector.String(), ns, specs.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, parsedSelector.String(), ns, specs.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...)
}
for _, bundle := range bundlesFromCluster {
multidocs := strings.Split(string(bundle), "\n---\n")
parsedBundle, err = supportbundle.ParseSupportBundleFromDoc([]byte(multidocs[0]))
if err != nil {
klog.Errorf("failed to parse support bundle spec: %s", err)
continue
}
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...)
}
var redactorsFromCluster []string
// Search cluster for redactor specs
klog.V(1).Infof("Search redactor specs from [%q] namespaces using %q selector", strings.Join(namespaces, ", "), parsedSelector.String())
for _, ns := range namespaces {
redactorsFromSecrets, err := specs.LoadFromSecretMatchingLabel(client, parsedSelector.String(), ns, specs.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, parsedSelector.String(), ns, specs.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 _, 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)
}
redactors.Spec.Redactors = append(redactors.Spec.Redactors, parsedRedactors...)
}
return parsedBundle, redactors, nil
return privSpecs.LoadFromCluster(ctx, client, v.GetStringSlice("selector"), v.GetString("namespace"))
}
func parseTimeFlags(v *viper.Viper) (*time.Time, error) {
@@ -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:
+163
View File
@@ -90,6 +90,53 @@ spec:
- namespace
- outcomes
type: object
certificates:
properties:
annotations:
additionalProperties:
type: string
type: object
checkName:
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
clusterPodStatuses:
properties:
annotations:
@@ -195,6 +242,10 @@ spec:
type: object
type: object
type: array
regex:
type: string
regexGroups:
type: string
strict:
type: BoolString
yamlPath:
@@ -681,6 +732,8 @@ spec:
type: BoolString
fileName:
type: string
jsonPath:
type: string
outcomes:
items:
properties:
@@ -1618,6 +1671,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:
@@ -2353,6 +2455,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:
+219 -79
View File
@@ -99,8 +99,6 @@ spec:
type: array
exclude:
type: BoolString
name:
type: string
secrets:
items:
properties:
@@ -247,6 +245,36 @@ spec:
- image
- namespace
type: object
customMetrics:
properties:
collectorName:
type: string
exclude:
type: BoolString
metricRequests:
items:
description: MetricRequest the details of the MetricValuesList
to be retrieved
properties:
namespace:
description: Namespace for which to collect the metric
values, empty for non-namespaces resources.
type: string
objectName:
description: ObjectName for which to collect metric
values, all resources when empty. Note that for
namespaced resources a Namespace has to be supplied
regardless.
type: string
resourceMetricName:
description: ResourceMetricName name of the MetricValueList
as per the APIResourceList from custom.metrics.k8s.io/v1beta1
type: string
required:
- resourceMetricName
type: object
type: array
type: object
data:
properties:
collectorName:
@@ -290,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:
@@ -304,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:
@@ -321,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:
@@ -336,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:
@@ -1915,7 +1969,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -2030,7 +2087,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -2156,7 +2216,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -2381,7 +2445,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -2558,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
@@ -2697,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
@@ -2738,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
@@ -2838,7 +2926,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -3415,7 +3507,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3530,7 +3625,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3655,7 +3753,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -3872,7 +3974,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4050,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
@@ -4188,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
@@ -4229,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
@@ -4321,7 +4429,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4935,7 +5047,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -5050,7 +5165,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -5176,7 +5294,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5401,7 +5523,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5578,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
@@ -5717,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
@@ -5758,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
@@ -5858,7 +6004,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -6227,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
@@ -6398,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
@@ -6471,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:
@@ -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:
@@ -1546,6 +1684,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 +1704,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 +1724,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:
+287 -79
View File
@@ -90,6 +90,53 @@ spec:
- namespace
- outcomes
type: object
certificates:
properties:
annotations:
additionalProperties:
type: string
type: object
checkName:
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
clusterPodStatuses:
properties:
annotations:
@@ -195,6 +242,10 @@ spec:
type: object
type: object
type: array
regex:
type: string
regexGroups:
type: string
strict:
type: BoolString
yamlPath:
@@ -681,6 +732,8 @@ spec:
type: BoolString
fileName:
type: string
jsonPath:
type: string
outcomes:
items:
properties:
@@ -1543,8 +1596,6 @@ spec:
type: array
exclude:
type: BoolString
name:
type: string
secrets:
items:
properties:
@@ -1691,6 +1742,36 @@ spec:
- image
- namespace
type: object
customMetrics:
properties:
collectorName:
type: string
exclude:
type: BoolString
metricRequests:
items:
description: MetricRequest the details of the MetricValuesList
to be retrieved
properties:
namespace:
description: Namespace for which to collect the metric
values, empty for non-namespaces resources.
type: string
objectName:
description: ObjectName for which to collect metric
values, all resources when empty. Note that for
namespaced resources a Namespace has to be supplied
regardless.
type: string
resourceMetricName:
description: ResourceMetricName name of the MetricValueList
as per the APIResourceList from custom.metrics.k8s.io/v1beta1
type: string
required:
- resourceMetricName
type: object
type: array
type: object
data:
properties:
collectorName:
@@ -1734,6 +1815,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:
@@ -1748,6 +1840,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:
@@ -1765,6 +1862,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:
@@ -1780,6 +1882,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:
@@ -3359,7 +3466,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3474,7 +3584,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3600,7 +3713,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -3825,7 +3942,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4002,6 +4123,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
@@ -4141,8 +4287,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
@@ -4182,18 +4328,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
@@ -4282,7 +4423,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4859,7 +5004,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -4974,7 +5122,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -5099,7 +5250,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5316,7 +5471,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5494,6 +5653,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
@@ -5632,8 +5798,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
@@ -5673,18 +5839,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
@@ -5765,7 +5926,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -6379,7 +6544,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -6494,7 +6662,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -6620,7 +6791,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -6845,7 +7020,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -7022,6 +7201,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
@@ -7161,8 +7365,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
@@ -7202,18 +7406,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
@@ -7302,7 +7501,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -7671,17 +7874,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
@@ -7842,7 +8038,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
@@ -7915,14 +8112,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
@@ -10270,6 +10463,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:
@@ -10285,6 +10483,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:
@@ -10300,6 +10503,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:
+410 -79
View File
@@ -121,6 +121,53 @@ spec:
- namespace
- outcomes
type: object
certificates:
properties:
annotations:
additionalProperties:
type: string
type: object
checkName:
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
clusterPodStatuses:
properties:
annotations:
@@ -226,6 +273,10 @@ spec:
type: object
type: object
type: array
regex:
type: string
regexGroups:
type: string
strict:
type: BoolString
yamlPath:
@@ -712,6 +763,8 @@ spec:
type: BoolString
fileName:
type: string
jsonPath:
type: string
outcomes:
items:
properties:
@@ -1574,8 +1627,6 @@ spec:
type: array
exclude:
type: BoolString
name:
type: string
secrets:
items:
properties:
@@ -1722,6 +1773,36 @@ spec:
- image
- namespace
type: object
customMetrics:
properties:
collectorName:
type: string
exclude:
type: BoolString
metricRequests:
items:
description: MetricRequest the details of the MetricValuesList
to be retrieved
properties:
namespace:
description: Namespace for which to collect the metric
values, empty for non-namespaces resources.
type: string
objectName:
description: ObjectName for which to collect metric
values, all resources when empty. Note that for
namespaced resources a Namespace has to be supplied
regardless.
type: string
resourceMetricName:
description: ResourceMetricName name of the MetricValueList
as per the APIResourceList from custom.metrics.k8s.io/v1beta1
type: string
required:
- resourceMetricName
type: object
type: array
type: object
data:
properties:
collectorName:
@@ -1765,6 +1846,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:
@@ -1779,6 +1871,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:
@@ -1796,6 +1893,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:
@@ -1811,6 +1913,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:
@@ -3390,7 +3497,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3505,7 +3615,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -3631,7 +3744,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -3856,7 +3973,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4033,6 +4154,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
@@ -4172,8 +4318,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
@@ -4213,18 +4359,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
@@ -4313,7 +4454,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -4890,7 +5035,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -5005,7 +5153,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -5130,7 +5281,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5347,7 +5502,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -5525,6 +5684,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
@@ -5663,8 +5829,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
@@ -5704,18 +5870,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
@@ -5796,7 +5957,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -6410,7 +6575,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -6525,7 +6693,10 @@ spec:
properties:
name:
description: The header field
name
name. This will be canonicalized
upon output, so case-variant
names will be understood as
the same header.
type: string
value:
description: The header field
@@ -6651,7 +6822,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -6876,7 +7051,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -7053,6 +7232,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
@@ -7192,8 +7396,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
@@ -7233,18 +7437,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
@@ -7333,7 +7532,11 @@ spec:
custom header to be used in HTTP probes
properties:
name:
description: The header field name
description: The header field name.
This will be canonicalized upon
output, so case-variant names
will be understood as the same
header.
type: string
value:
description: The header field value
@@ -7702,17 +7905,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
@@ -7873,7 +8069,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
@@ -7946,14 +8143,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
@@ -10268,6 +10461,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:
@@ -11003,6 +11245,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:
@@ -11127,6 +11430,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:
@@ -11262,6 +11578,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:
@@ -11277,6 +11598,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:
@@ -11292,6 +11618,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:
+5 -1
View File
@@ -28,6 +28,8 @@ preflight [url] [flags]
--context string The name of the kubeconfig context to use
--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
@@ -44,10 +46,12 @@ preflight [url] [flags]
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
-v, --v Level number for the log level verbosity
```
### SEE ALSO
* [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 3-Jan-2023
###### Auto generated by spf13/cobra on 31-Aug-2023
+36
View File
@@ -0,0 +1,36 @@
## preflight oci-fetch
Fetch a preflight from an OCI registry and print it to standard out
```
preflight oci-fetch [URI] [flags]
```
### Options
```
-h, --help help for oci-fetch
```
### Options inherited from parent commands
```
--collect-without-permissions always run preflight checks even if some require permissions that preflight does not have (default true)
--collector-image string the full name of the collector image to use
--collector-pullpolicy string the pull policy of the collector image
--cpuprofile string File path to write cpu profiling data
--debug enable debug logging
--format string output format, one of human, json, yaml. only used when interactive is set to false (default "human")
--interactive interactive preflights (default true)
--memprofile string File path to write memory profiling data
-o, --output string specify the output file path for the preflight checks
--selector string selector (label query) to filter remote collection nodes on.
--since string force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.
--since-time string force pod logs collectors to return logs after a specific date (RFC3339)
```
### SEE ALSO
* [preflight](preflight.md) - Run and retrieve preflight checks in a cluster
###### Auto generated by spf13/cobra on 31-Aug-2023
+1 -1
View File
@@ -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
+5 -3
View File
@@ -25,7 +25,8 @@ support-bundle [urls...] [flags]
--collect-without-permissions always generate a support bundle, even if it some require additional permissions (default true)
--context string The name of the kubeconfig context to use
--cpuprofile string File path to write cpu profiling data
--debug enable debug logging
--debug enable debug logging. This is equivalent to --v=0
--disable-compression If true, opt-out of response compression for all requests to the server
-h, --help help for support-bundle
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--interactive enable/disable interactive mode (default true)
@@ -38,13 +39,14 @@ support-bundle [urls...] [flags]
--redact enable/disable default redactions (default true)
--redactors strings names of the additional redactors to use
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-l, --selector strings selector to filter on for loading additional support bundle specs found in secrets within the cluster (default [troubleshoot.io/kind=support-bundle])
-l, --selector strings selector to filter on for loading additional support bundle specs found in secrets within the cluster (default [troubleshoot.sh/kind=support-bundle])
-s, --server string The address and port of the Kubernetes API server
--since string force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.
--since-time string force pod logs collectors to return logs after a specific date (RFC3339)
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
-v, --v Level number for the log level verbosity
```
### SEE ALSO
@@ -53,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 3-Jan-2023
###### Auto generated by spf13/cobra on 31-Aug-2023
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+25 -5
View File
@@ -7,10 +7,21 @@ spec:
- data:
name: config/replicas.txt
data: "5"
- run:
collectorName: "static-hi"
image: 'alpine:3'
command: ["echo", "hi static!"]
- runPod:
collectorName: "static-hi-1"
podSpec:
containers:
- name: static-hi
image: alpine:3
command: ["echo", "hi static!"]
## This collector is intentionally duplicated to test same pod should be terminated after success
- runPod:
collectorName: "static-hi-2"
podSpec:
containers:
- name: static-hi
image: alpine:3
command: ["echo", "hi static!"]
analyzers:
- clusterVersion:
outcomes:
@@ -44,7 +55,16 @@ spec:
message: You have at least 5 replicas
- textAnalyze:
checkName: Said hi!
fileName: /static-hi.log
fileName: /static-hi-1.log
regex: 'hi static'
outcomes:
- fail:
message: Didn't say hi.
- pass:
message: Said hi!
- textAnalyze:
checkName: Said hi!
fileName: /static-hi-2.log
regex: 'hi static'
outcomes:
- fail:
-1
View File
@@ -19,4 +19,3 @@ spec:
message: At least 16 CPU cores preferred
- pass:
message: This server has sufficient CPU cores
+14
View File
@@ -0,0 +1,14 @@
## Parse troubleshoot specs from a helm chart
This is an example of using troubleshoot's `loader.LoadSpecs` API to load specs from rendered manifests in a helm chart. The chart in this example contains a kubernetes `Secret` & `ConfigMap` with troubleshoot specs, as well as a troubleshoot custom resource. The custom resource is behind a values flag and does not get rendered by default. The code adds this flag to ensure that the manifest is rendered so as to load it.
The manifests are rendered with the equivalent of `helm template --values values.yaml` where the output is a YAML multidoc. `loader.LoadSpecs` will take the YAML multidoc as an input and extract troubleshoot specs inside kuberenetes `Secrets` and `ConfigMap`s, and any troubleshoot custom resources found.
This application always uses the local version of troubleshoot so as to build using the latest version of the library. This ensures that the example is kept in sync with new features.
### Running
```go
go mod tidy # sync go modules
go run main.go # run the application. This should print out a YAML multidoc of the loaded troubleshoot specs
```
+73
View File
@@ -0,0 +1,73 @@
module helm-template
go 1.20
// Always use the local version of troubleshoot so as to build using
// the latest version of the library. This will ensure the example
// is kept in sync with new features
replace github.com/replicatedhq/troubleshoot v0.0.0 => ../../../
require (
github.com/replicatedhq/troubleshoot v0.0.0
helm.sh/helm/v3 v3.12.3
sigs.k8s.io/yaml v1.3.0
)
require (
github.com/BurntSushi/toml v1.2.1 // 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/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // 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
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
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-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.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
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/spf13/cast v1.5.1 // 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
golang.org/x/crypto v0.11.0 // indirect
golang.org/x/net v0.13.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.10.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
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.28.1 // indirect
k8s.io/apiextensions-apiserver v0.28.1 // indirect
k8s.io/apimachinery v0.28.1 // indirect
k8s.io/client-go v0.28.1 // indirect
k8s.io/klog/v2 v2.100.1 // 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.1 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
+218
View File
@@ -0,0 +1,218 @@
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=
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ=
github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0=
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/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
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/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/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
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=
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
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/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
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-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=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
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=
github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM=
github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
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.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=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
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/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/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/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/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=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo=
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
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=
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.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
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-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-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-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
golang.org/x/net v0.13.0 h1:Nvo8UFsZ8X3BhAC9699Z1j7XQ3rsZnUUm7jfBEk1ueY=
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8=
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
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-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.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.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
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.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.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-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/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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
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.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.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-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.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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
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.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108=
k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg=
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.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY=
k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw=
k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8=
k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE=
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-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.1 h1:9UvgKD4ZJGcj24vefUFgZFP3xej/3igL9BsOUTb/+4c=
sigs.k8s.io/controller-runtime v0.15.1/go.mod h1:7ngYvp1MLT+9GeZ+6lH3LOlcHkp/+tzA/fmHa4iq9kk=
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=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
+115
View File
@@ -0,0 +1,115 @@
package main
import (
"context"
"fmt"
"log"
"strings"
tsloader "github.com/replicatedhq/troubleshoot/pkg/loader"
"helm.sh/helm/v3/pkg/chart"
"helm.sh/helm/v3/pkg/chart/loader"
"helm.sh/helm/v3/pkg/chartutil"
"helm.sh/helm/v3/pkg/engine"
"sigs.k8s.io/yaml"
)
func main() {
// Load chart from tarball
// The helm loader package has a few other ways to load a chart, such as from a directory `loader.LoadDir()`
// or from an archive in memory `loader.LoadArchive()` etc.
chart, err := loader.LoadFile("mychart-0.1.0.tgz")
if err != nil {
log.Fatalf("error loading at chart: %v", err)
}
// Render chart to manifests. Equivalent to `helm template --values values.yaml`
renderedManifests, err := renderChartToManifests(chart, chartutil.Values{
"preflight": true,
"includeTroubleshootCRs": true,
})
if err != nil {
log.Fatalf("error rendering chart: %v", err)
}
fmt.Println("############# Raw helm manifests #############")
fmt.Println(renderedManifests)
// Load rendered manifests into a slice of troubleshoot specs
// 'tsKinds' will contain all the specs. This object will the the
// input of other troubleshoot APIs such as ones used to collect
// bundles, analyze bundles, redact etc.
ctx := context.Background()
tsKinds, err := tsloader.LoadSpecs(ctx, tsloader.LoadOptions{
RawSpec: renderedManifests,
})
if err != nil {
log.Fatalf("error loading troubleshoot specs: %v", err)
}
// Ensure we have the correct number of specs
if len(tsKinds.PreflightsV1Beta2) != 1 {
log.Fatalf("expected 1 preflight, got %d", len(tsKinds.PreflightsV1Beta2))
}
if len(tsKinds.SupportBundlesV1Beta2) != 1 {
log.Fatalf("expected 1 supportbundle, got %d", len(tsKinds.SupportBundlesV1Beta2))
}
if len(tsKinds.RedactorsV1Beta2) != 1 {
log.Fatalf("expected 1 redactor, got %d", len(tsKinds.RedactorsV1Beta2))
}
// Print the specs as yaml
fmt.Println("---\n############# Support bundle #############")
printSpecAsYaml(tsKinds.SupportBundlesV1Beta2[0])
fmt.Println("---\n############# Preflight #############")
printSpecAsYaml(tsKinds.PreflightsV1Beta2[0])
fmt.Println("---\n############# Redactor #############")
printSpecAsYaml(tsKinds.RedactorsV1Beta2[0])
}
func renderChartToManifests(chart *chart.Chart, inputValues chartutil.Values) (string, error) {
options := chartutil.ReleaseOptions{
Name: "my-release", // Not mandatory, but this is how helm sets the release name
}
// Pull in imported values from dependencies to the parent chart
// https://helm.sh/docs/topics/charts/#importing-child-values-via-dependencies
if err := chartutil.ProcessDependencies(chart, chartutil.Values{}); err != nil {
return "", fmt.Errorf("failed to process chart %q dependencies: %w", chart.Name(), err)
}
// Gather all values necessary to render the templates
// imported values, values from the chart and user provided values
rValues, err := chartutil.ToRenderValues(chart, inputValues, options, nil)
if err != nil {
return "", fmt.Errorf("failed to render template values: %w", err)
}
// Render the chart templates. This will include non YAML files as well
renderedTemplates, err := engine.Render(chart, rValues)
if err != nil {
return "", fmt.Errorf("failed to render template: %w", err)
}
// Combine all rendered templates into a single yaml multidoc string
// Only pick up YAML files, ignore any others. Troubleshoot loader
// expects only valid YAML input
var out strings.Builder
for k, v := range renderedTemplates {
if strings.HasSuffix(k, ".yaml") || strings.HasSuffix(k, ".yml") {
// Add the multidoc split marker
out.WriteString(fmt.Sprintf("---\n# Source: %s\n%s\n", k, v))
}
}
return out.String(), nil
}
func printSpecAsYaml(v any) {
b, err := yaml.Marshal(v)
if err != nil {
log.Fatalf("error marshalling troubleshoot specs: %v", err)
}
fmt.Println(string(b))
}
Binary file not shown.
+87 -57
View File
@@ -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,68 +15,97 @@ 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.3.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.18
github.com/mattn/go-isatty v0.0.19
github.com/mholt/archiver/v3 v3.5.1
github.com/microsoft/go-mssqldb v0.21.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.4
github.com/sirupsen/logrus v1.9.0
github.com/shirou/gopsutil/v3 v3.23.8
github.com/spf13/cobra v1.7.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.15.0
github.com/stretchr/testify v1.8.2
github.com/spf13/viper v1.16.0
github.com/stretchr/testify v1.8.4
github.com/tj/go-spin v1.1.0
go.opentelemetry.io/otel v1.15.1
go.opentelemetry.io/otel/sdk v1.15.1
golang.org/x/sync v0.2.0
go.opentelemetry.io/otel v1.17.0
go.opentelemetry.io/otel/sdk v1.17.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/sync v0.3.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.27.1
k8s.io/apiextensions-apiserver v0.27.0
k8s.io/apimachinery v0.27.1
k8s.io/apiserver v0.27.1
k8s.io/cli-runtime v0.27.1
k8s.io/client-go v0.27.1
k8s.io/api v0.28.1
k8s.io/apiextensions-apiserver v0.28.1
k8s.io/apimachinery v0.28.1
k8s.io/apiserver v0.28.1
k8s.io/cli-runtime v0.28.1
k8s.io/client-go v0.28.1
k8s.io/klog/v2 v2.100.1
oras.land/oras-go v1.2.3
sigs.k8s.io/controller-runtime v0.14.6
sigs.k8s.io/controller-runtime v0.16.1
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-20190719163853-cb61b32ac6fe // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/s2a-go v0.1.3 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // 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/shoenig/go-m1cpu v0.1.5 // 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/sylabs/sif/v2 v2.11.1 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
go.opentelemetry.io/otel/trace v1.15.1 // indirect
go.uber.org/atomic v1.10.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.9.0 // indirect
golang.org/x/tools v0.7.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.17.0 // indirect
go.opentelemetry.io/otel/trace v1.17.0 // indirect
golang.org/x/mod v0.10.0 // indirect
golang.org/x/tools v0.9.3 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230525234035-dd9d682886f9 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230525234030-28d5490b6b19 // indirect
k8s.io/component-base v0.28.1 // indirect
k8s.io/kubectl v0.28.1 // indirect
)
require (
@@ -101,7 +130,7 @@ 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/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v23.0.1+incompatible // indirect
github.com/docker/docker v23.0.3+incompatible // indirect
@@ -123,11 +152,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.7.1 // indirect
github.com/googleapis/gax-go/v2 v2.8.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
@@ -151,7 +179,7 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-testing-interface v1.14.1 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.1
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/locker v1.0.1 // indirect
github.com/moby/spdystream v0.2.0 // indirect
@@ -169,53 +197,55 @@ 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.6 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // 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.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.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.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/afero v1.9.5 // 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/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/yusufpapurcu/wmi v1.2.2 // 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.8.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/oauth2 v0.7.0 // indirect
golang.org/x/sys v0.7.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/crypto v0.12.0 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.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.114.0 // indirect
google.golang.org/api v0.122.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.54.0 // indirect
google.golang.org/genproto v0.0.0-20230526161137-0005af68ea54 // indirect
google.golang.org/grpc v1.55.0 // indirect
google.golang.org/protobuf v1.30.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-20230327201221-f5883ff37f0c // indirect
helm.sh/helm/v3 v3.12.3
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/metrics v0.28.1
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 (
+396 -151
View File
File diff suppressed because it is too large Load Diff
+51
View File
@@ -0,0 +1,51 @@
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, key string) ([]byte, error) {
foundConfigMap, err := client.CoreV1().ConfigMaps(ns).Get(ctx, name, metav1.GetOptions{})
if err != nil {
return nil, errors.Wrap(err, "failed to get configmap")
}
spec, ok := foundConfigMap.Data[key]
if !ok {
return nil, errors.Errorf("spec not found in configmap %s", name)
}
klog.V(1).InfoS("Loaded spec from config map", "name",
foundConfigMap.Name, "namespace", foundConfigMap.Namespace, "data key", key,
)
return []byte(spec), 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 {
+50
View File
@@ -0,0 +1,50 @@
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, key 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")
}
spec, ok := foundSecret.Data[key]
if !ok {
return nil, errors.Errorf("spec not found in secret %s", name)
}
klog.V(1).InfoS("Loaded spec from secret", "name",
foundSecret.Name, "namespace", foundSecret.Namespace, "data key", key,
)
return spec, 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 {
+259
View File
@@ -0,0 +1,259 @@
package specs
import (
"context"
"fmt"
"io"
"net/http"
"net/url"
"os"
"reflect"
"strings"
"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
}
func LoadFromCLIArgs(ctx context.Context, client kubernetes.Interface, args []string, vp *viper.Viper) (*loader.TroubleshootKinds, error) {
rawSpecs := []string{}
for _, v := range args {
if strings.HasPrefix(v, "secret/") {
// format secret/namespace-name/secret-name
pathParts := strings.Split(v, "/")
if len(pathParts) != 3 {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Errorf("path %s must have 3 components", v))
}
spec, err := LoadFromSecret(ctx, client, pathParts[1], pathParts[2], "preflight-spec")
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, errors.Wrap(err, "failed to get spec from secret"))
}
rawSpecs = append(rawSpecs, string(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.PullPreflightFromOCI(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, string(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))
}
req, err := http.NewRequest("GET", v, nil)
if err != nil {
// exit code: should this be catch all or spec issues...?
return nil, types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, err)
}
req.Header.Set("User-Agent", "Replicated_Preflight/v1beta2")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// exit code: should this be catch all or spec issues...?
return nil, types.NewExitCodeError(constants.EXIT_CODE_CATCH_ALL, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, types.NewExitCodeError(constants.EXIT_CODE_SPEC_ISSUES, err)
}
rawSpecs = append(rawSpecs, string(body))
}
}
}
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
}
// 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,
})
}
+203
View File
@@ -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`),
},
}
}
+12 -3
View File
@@ -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)
}
}
+1 -1
View File
@@ -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:
+2 -2
View File
@@ -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
@@ -40,3 +40,15 @@ func AppName(name string) string {
return strings.Join(casedWords, " ")
}
func SplitYAML(doc string) []string {
return strings.Split(doc, "\n---\n")
}
func EstimateNumberOfLines(text string) int {
n := strings.Count(text, "\n")
if len(text) > 0 && !strings.HasSuffix(text, "\n") {
n++
}
return n
}
+196
View File
@@ -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)
}
})
}
}
+5 -1
View File
@@ -79,7 +79,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,6 +218,8 @@ 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:
@@ -232,6 +234,8 @@ func getAnalyzer(analyzer *troubleshootv1beta2.Analyze) Analyzer {
return &AnalyzeSysctl{analyzer: analyzer.Sysctl}
case analyzer.ClusterResource != nil:
return &AnalyzeClusterResource{analyzer: analyzer.ClusterResource}
case analyzer.Certificates != nil:
return &AnalyzeCertificates{analyzer: analyzer.Certificates}
default:
return nil
}
+132
View File
@@ -0,0 +1,132 @@
package analyzer
import (
"encoding/json"
"fmt"
"regexp"
"strconv"
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
type AnalyzeCertificates struct {
analyzer *troubleshootv1beta2.CertificatesAnalyze
}
func (a *AnalyzeCertificates) Title() string {
title := a.analyzer.CheckName
if title == "" {
return "Certificates Verification"
}
return title
}
func (a *AnalyzeCertificates) IsExcluded() (bool, error) {
return isExcluded(a.analyzer.Exclude)
}
func (a *AnalyzeCertificates) Analyze(getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
result, err := a.AnalyzeCertificates(a.analyzer, getFile)
if err != nil {
return nil, err
}
return result, nil
}
func (a *AnalyzeCertificates) AnalyzeCertificates(analyzer *troubleshootv1beta2.CertificatesAnalyze, getCollectedFileContents func(string) ([]byte, error)) ([]*AnalyzeResult, error) {
certificatesInfo, err := getCollectedFileContents("certificates/certificates.json")
if err != nil {
return nil, errors.Wrap(err, "failed to get contents of certificates.json")
}
collectorCertificates := []collect.CertCollection{}
if err := json.Unmarshal(certificatesInfo, &collectorCertificates); err != nil {
return nil, errors.Wrap(err, "failed to parse certificates.json")
}
return a.analyzeAnalyzeCertificatesResult(collectorCertificates, analyzer.Outcomes)
}
func (a *AnalyzeCertificates) analyzeAnalyzeCertificatesResult(certificates []collect.CertCollection, outcomes []*troubleshootv1beta2.Outcome) ([]*AnalyzeResult, error) {
var results []*AnalyzeResult
for _, cert := range certificates {
var passResults []*AnalyzeResult
for _, certChain := range cert.CertificateChain {
when := ""
message := ""
source := ""
if cert.Source.ConfigMapName != "" {
source = fmt.Sprintf("obtained from %s configmap within %s namespace", cert.Source.ConfigMapName, cert.Source.Namespace)
}
if cert.Source.SecretName != "" {
source = fmt.Sprintf("obtained from %s secret within %s namespace", cert.Source.SecretName, cert.Source.Namespace)
}
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, %s", certChain.CertName, 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, %s", certChain.CertName, message, source)
// return the result immediately if the certificate is invalid
results = append(results, &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 %s in %d days, %s", certChain.CertName, message, warnMatchDays, source)
// discard passResults if the certificate is going to expire in certain days
passResults = []*AnalyzeResult{}
results = append(results, &result)
}
}
}
}
// append passResults if the certificate is valid and not going to expire in certain days
results = append(results, passResults...)
}
}
return results, nil
}
+172
View File
@@ -0,0 +1,172 @@
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 Test_certificates(t *testing.T) {
tests := []struct {
name string
analyzer troubleshootv1beta2.CertificatesAnalyze
expectResult []*AnalyzeResult
getFile getFile
filePath, file string
}{
{
name: "pass case",
analyzer: troubleshootv1beta2.CertificatesAnalyze{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "certificate is valid",
},
},
},
},
expectResult: []*AnalyzeResult{
{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "Certificates Verification",
Message: "ca.crt certificate is valid, obtained from kube-root-ca.crt configmap within kurl namespace",
},
},
filePath: "certificates/certificates.json",
file: `[{
"source": {
"configMap": "kube-root-ca.crt",
"namespace": "kurl"
},
"certificateChain": [
{
"certificate": "ca.crt",
"subject": "CN=kubernetes",
"subjectAlternativeNames": [
"kubernetes"
],
"issuer": "CN=kubernetes",
"notAfter": "2033-04-16T00:30:20Z",
"notBefore": "2023-04-19T00:30:20Z",
"isValid": true,
"isCA": true
}
]
}]`,
},
{
name: "failed case",
analyzer: troubleshootv1beta2.CertificatesAnalyze{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "notAfter < Today",
Message: "certificate has expired",
},
},
},
},
expectResult: []*AnalyzeResult{
{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "Certificates Verification",
Message: "ca.crt certificate has expired, obtained from kube-root-ca.crt configmap within kurl namespace",
},
},
filePath: "certificates/certificates.json",
file: `[{
"source": {
"configMap": "kube-root-ca.crt",
"namespace": "kurl"
},
"certificateChain": [
{
"certificate": "ca.crt",
"subject": "CN=kubernetes",
"subjectAlternativeNames": [
"kubernetes"
],
"issuer": "CN=kubernetes",
"notAfter": "2023-04-16T00:30:20Z",
"notBefore": "2021-04-19T00:30:20Z",
"isValid": false,
"isCA": true
}
]
}]`,
},
{
name: "warning case",
analyzer: troubleshootv1beta2.CertificatesAnalyze{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Warn: &troubleshootv1beta2.SingleOutcome{
When: "notAfter < Today + 15 days",
Message: "certificate is about to expire",
},
},
},
},
expectResult: []*AnalyzeResult{
{
IsPass: false,
IsWarn: true,
IsFail: false,
Title: "Certificates Verification",
Message: "ca.crt certificate is about to expire in 15 days, obtained from kube-root-ca.crt configmap within kurl namespace",
},
},
filePath: "certificates/certificates.json",
file: fmt.Sprintf(`[{
"source": {
"configMap": "kube-root-ca.crt",
"namespace": "kurl"
},
"certificateChain": [
{
"certificate": "ca.crt",
"subject": "CN=kubernetes",
"subjectAlternativeNames": [
"kubernetes"
],
"issuer": "CN=kubernetes",
"notAfter": "%s",
"notBefore": "2021-04-16T00:30:20Z",
"isValid": true,
"isCA": true
}
]
}]`, time.Now().AddDate(0, 0, 5).Format("2006-01-02T15:04:05Z")),
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
req := require.New(t)
if test.getFile == nil {
test.getFile = func(n string) ([]byte, error) {
assert.Equal(t, n, test.filePath)
return []byte(test.file), nil
}
}
a := AnalyzeCertificates{
analyzer: &test.analyzer,
}
actual, err := a.AnalyzeCertificates(&test.analyzer, test.getFile)
t.Log(actual)
req.NoError(err)
assert.Equal(t, test.expectResult, actual)
})
}
}
+43 -5
View File
@@ -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)
+298 -1
View File
@@ -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 {
+9 -9
View File
@@ -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) {
@@ -47,7 +48,7 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
}
}
match, err := compareActualToWhen(outcome.Fail.When, readyReplicas, exists)
match, err := compareActualToWhen(outcome.Fail.When, readyReplicas)
if err != nil {
return nil, errors.Wrap(err, "failed to parse fail range")
}
@@ -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
}
@@ -87,7 +88,7 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
}
}
match, err := compareActualToWhen(outcome.Warn.When, readyReplicas, exists)
match, err := compareActualToWhen(outcome.Warn.When, readyReplicas)
if err != nil {
return nil, errors.Wrap(err, "failed to parse warn range")
}
@@ -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
}
@@ -127,7 +128,7 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
}
}
match, err := compareActualToWhen(outcome.Pass.When, readyReplicas, exists)
match, err := compareActualToWhen(outcome.Pass.When, readyReplicas)
if err != nil {
return nil, errors.Wrap(err, "failed to parse pass range")
}
@@ -145,9 +146,8 @@ func commonStatus(outcomes []*troubleshootv1beta2.Outcome, name string, iconKey
return result, nil
}
func compareActualToWhen(when string, actual int, exists bool) (bool, error) {
func compareActualToWhen(when string, actual int) (bool, error) {
parts := strings.Split(strings.TrimSpace(when), " ")
// we can make this a lot more flexible
if len(parts) != 2 {
return false, errors.New("unable to parse when range")
+30
View File
@@ -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
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"
}
}
]
}
@@ -0,0 +1,213 @@
{
"kind": "PersistentVolumeClaimList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "1463098"
},
"items": [
{
"kind": "PersistentVolumeClaim",
"apiVersion": "v1",
"metadata": {
"name": "data-postgresql-0",
"namespace": "default",
"uid": "b733694c-a969-4763-9960-d3465c9fccd5",
"resourceVersion": "1364772",
"creationTimestamp": "2023-05-15T21:22:00Z",
"labels": {
"app.kubernetes.io/component": "primary",
"app.kubernetes.io/instance": "some-app",
"app.kubernetes.io/name": "postgresql"
},
"annotations": {
"pv.kubernetes.io/bind-completed": "yes",
"pv.kubernetes.io/bound-by-controller": "yes",
"volume.beta.kubernetes.io/storage-provisioner": "rancher.io/local-path",
"volume.kubernetes.io/selected-node": "k3d-mycluster-server-0"
},
"finalizers": [
"kubernetes.io/pvc-protection"
],
"managedFields": [
{
"manager": "k3s",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-05-15T21:22:07Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:pv.kubernetes.io/bind-completed": {},
"f:pv.kubernetes.io/bound-by-controller": {},
"f:volume.beta.kubernetes.io/storage-provisioner": {},
"f:volume.kubernetes.io/selected-node": {}
},
"f:labels": {
".": {},
"f:app.kubernetes.io/component": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/name": {}
}
},
"f:spec": {
"f:accessModes": {},
"f:resources": {
"f:requests": {
".": {},
"f:storage": {}
}
},
"f:volumeMode": {},
"f:volumeName": {}
}
}
},
{
"manager": "k3s",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-05-15T21:22:07Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:accessModes": {},
"f:capacity": {
".": {},
"f:storage": {}
},
"f:phase": {}
}
},
"subresource": "status"
}
]
},
"spec": {
"accessModes": [
"ReadWriteOnce"
],
"resources": {
"requests": {
"storage": "8Gi"
}
},
"volumeName": "pvc-b733694c-a969-4763-9960-d3465c9fccd5",
"storageClassName": "local-path",
"volumeMode": "Filesystem"
},
"status": {
"phase": "Bound",
"accessModes": [
"ReadWriteOnce"
],
"capacity": {
"storage": "8Gi"
}
}
},
{
"kind": "PersistentVolumeClaim",
"apiVersion": "v1",
"metadata": {
"name": "redis-data-redis-replicas-0",
"namespace": "default",
"uid": "4e0ec7d1-5ff1-4054-bede-4cbffec0f595",
"resourceVersion": "1450618",
"creationTimestamp": "2023-05-25T15:45:35Z",
"labels": {
"app.kubernetes.io/component": "replica",
"app.kubernetes.io/instance": "some-app",
"app.kubernetes.io/name": "redis"
},
"annotations": {
"pv.kubernetes.io/bind-completed": "yes",
"pv.kubernetes.io/bound-by-controller": "yes",
"volume.beta.kubernetes.io/storage-provisioner": "rancher.io/local-path",
"volume.kubernetes.io/selected-node": "k3d-mycluster-server-0"
},
"finalizers": [
"kubernetes.io/pvc-protection"
],
"managedFields": [
{
"manager": "k3s",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-05-25T15:45:41Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:metadata": {
"f:annotations": {
".": {},
"f:pv.kubernetes.io/bind-completed": {},
"f:pv.kubernetes.io/bound-by-controller": {},
"f:volume.beta.kubernetes.io/storage-provisioner": {},
"f:volume.kubernetes.io/selected-node": {}
},
"f:labels": {
".": {},
"f:app.kubernetes.io/component": {},
"f:app.kubernetes.io/instance": {},
"f:app.kubernetes.io/name": {}
}
},
"f:spec": {
"f:accessModes": {},
"f:resources": {
"f:requests": {
".": {},
"f:storage": {}
}
},
"f:volumeMode": {},
"f:volumeName": {}
}
}
},
{
"manager": "k3s",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-05-25T15:45:41Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:status": {
"f:accessModes": {},
"f:capacity": {
".": {},
"f:storage": {}
},
"f:phase": {}
}
},
"subresource": "status"
}
]
},
"spec": {
"accessModes": [
"ReadWriteMany"
],
"resources": {
"requests": {
"storage": "8Gi"
}
},
"volumeName": "pvc-4e0ec7d1-5ff1-4054-bede-4cbffec0f595",
"storageClassName": "local-path",
"volumeMode": "Filesystem"
},
"status": {
"phase": "Bound",
"accessModes": [
"ReadWriteMany"
],
"capacity": {
"storage": "8Gi"
}
}
}
]
}
+5 -1
View File
@@ -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
}
+3 -1
View File
@@ -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)
+1 -1
View File
@@ -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 {
+3 -1
View File
@@ -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
+1 -1
View File
@@ -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 {
+146
View File
@@ -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)
})
}
}
+3 -1
View File
@@ -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)
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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")
+1 -1
View File
@@ -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 {
+3 -1
View File
@@ -27,7 +27,9 @@ 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
collectorName := hostAnalyzer.CollectorName
@@ -345,7 +345,7 @@ func TestAnalyzeHostFilesystemPerformance(t *testing.T) {
return b, nil
}
result, err := (&AnalyzeHostFilesystemPerformance{test.hostAnalyzer}).Analyze(getCollectedFileContents)
result, err := (&AnalyzeHostFilesystemPerformance{test.hostAnalyzer}).Analyze(getCollectedFileContents, nil)
if test.expectErr {
req.Error(err)
} else {
+3 -1
View File
@@ -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")
+1 -1
View File
@@ -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 {
+3 -1
View File
@@ -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
+3 -1
View File
@@ -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)
+1 -1
View File
@@ -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 {
+3 -1
View File
@@ -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 {
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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)

Some files were not shown because too many files have changed in this diff Show More