Compare commits

...
93 Commits
Author SHA1 Message Date
Dexter Yan 51c07b42c3 feat(analyzer): let cluster resource case insensitive to fix name inconsistent (#1547)
* feat(analyzer): let cluster resource case insensitive
2024-05-22 11:37:39 +12:00
bd7bae6302 chore(deps): bump the security group with 9 updates (#1549)
* ---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiextensions-apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: k8s.io/kubelet
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/metrics
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

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

* Regenerate CR 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>
2024-05-21 12:07:50 +00:00
dependabot[bot]andlnx01 9d41460d33 chore(deps): bump helm.sh/helm/v3 from 3.14.4 to 3.15.0 in /examples/sdk/helm-template in the security group (#1548)
---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-21 00:19:08 +00:00
Gerard Nguyen fb0f81d076 bug: [sc-103753] Host analysers are not deduplicating during multiple spec merges #1485 (#1542)
* dedupe host collector and analyzer

* dedup analyzer

* add unit test

* use generic
2024-05-17 09:34:29 +10:00
Evans Mungai 78bbea18ac feat: Prefer embedded-cluster over k0s when detecting distro (#1544)
* feat: Prefer embedded-cluster over k0s when detecting distro

* Implement check for embedded cluster detection
2024-05-15 09:26:03 +01:00
dependabot[bot]andlnx01 224d55b076 chore(deps): bump the security group with 2 updates (#1545)
Bumps the security group with 2 updates: [github.com/containers/image/v5](https://github.com/containers/image) and [github.com/fatih/color](https://github.com/fatih/color).


Updates `github.com/containers/image/v5` from 5.30.0 to 5.30.1
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.30.0...v5.30.1)

Updates `github.com/fatih/color` from 1.16.0 to 1.17.0
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.16.0...v1.17.0)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/fatih/color
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-14 00:18:29 +00:00
dependabot[bot]andlnx01 db967d2896 chore(deps): bump the security group with 4 updates (#1543)
Bumps the security group with 4 updates: [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil), [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime), [golang.org/x/net](https://github.com/golang/net) and [golang.org/x/text](https://github.com/golang/text).


Updates `github.com/shirou/gopsutil/v3` from 3.24.3 to 3.24.4
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.3...v3.24.4)

Updates `sigs.k8s.io/controller-runtime` from 0.18.0 to 0.18.2
- [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.18.0...v0.18.2)

Updates `golang.org/x/net` from 0.24.0 to 0.25.0
- [Commits](https://github.com/golang/net/compare/v0.24.0...v0.25.0)

Updates `golang.org/x/text` from 0.14.0 to 0.15.0
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-05-07 00:18:35 +00:00
Gerard Nguyen 088f0321e7 feat: [sc-103119] URI is not replacing the spec but merging instead (#1541)
* only replace spec that has uri

* add unit test

* fix unit tests from code review
2024-05-03 11:36:27 +01:00
Evans Mungai aeaac7a70f Revert "feat: URI is not replacing the spec but merging instead (#1537) (#1539)
Revert "feat: [sc-103119] URI is not replacing the spec but merging instead (#1537)"

This reverts commit c2f72ecd0c.
2024-05-01 14:38:46 +01:00
Gerard Nguyen 6b368f2221 feat: [sc-103754] Be able to detect search domain misconfiguration #1391 (#1534)
* new collector dns

* implement DNS collector

* add dns service and endpoints check

* add nil check on retrieve endpoints
2024-05-01 07:04:20 +10:00
Dexter YanandGerard Nguyen cb5db1733a feat(analyzer): make sure ReplicaSetStatus has valid result (#1538)
* feat(analyzer): make sure ReplicaSetStatus has valid result
---------

Co-authored-by: Gerard Nguyen <gerard@replicated.com>
2024-05-01 09:02:45 +12:00
Gerard Nguyen c2f72ecd0c feat: [sc-103119] URI is not replacing the spec but merging instead (#1537)
fix uri spec to replace origin spec
2024-04-30 14:13:35 +12:00
Dexter Yan f3bad5f409 fix(collector): fix helm collector with a nil error return to error list (#1535) 2024-04-29 12:19:34 +12:00
dependabot[bot]andlnx01 f438467003 chore(deps): bump the security group across 1 directory with 5 updates (#1531)
Bumps the security group with 5 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb) | `1.7.0` | `1.7.1` |
| [github.com/vmware-tanzu/velero](https://github.com/vmware-tanzu/velero) | `1.13.1` | `1.13.2` |
| [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` |
| [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.25.0` | `1.26.0` |
| [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) | `0.17.3` | `0.18.0` |



Updates `github.com/microsoft/go-mssqldb` from 1.7.0 to 1.7.1
- [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.7.0...v1.7.1)

Updates `github.com/vmware-tanzu/velero` from 1.13.1 to 1.13.2
- [Release notes](https://github.com/vmware-tanzu/velero/releases)
- [Changelog](https://github.com/vmware-tanzu/velero/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vmware-tanzu/velero/compare/v1.13.1...v1.13.2)

Updates `go.opentelemetry.io/otel` from 1.25.0 to 1.26.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.25.0...v1.26.0)

Updates `go.opentelemetry.io/otel/sdk` from 1.25.0 to 1.26.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.25.0...v1.26.0)

Updates `sigs.k8s.io/controller-runtime` from 0.17.3 to 0.18.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.17.3...v0.18.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/vmware-tanzu/velero
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-26 15:35:07 +12:00
Evans Mungai a374b0a3ab feat: Detect EC as a distribution (#1529) 2024-04-25 17:18:52 +01:00
Evans Mungai 6aaba59ebd feat: Detect k0s distribution in analyser (#1527) 2024-04-25 15:29:37 +01:00
Andrew Lavery f18b5d754e update k8s imports to v0.30.0 and address changed function signature (#1528)
* update k8s imports to v0.30.0 and address changed function signature

* update schemas
2024-04-24 23:05:37 +09:00
dependabot[bot]andlnx01 2ede46ed58 chore(deps): bump the security group with 2 updates (#1524)
Bumps the security group with 2 updates: [github.com/hashicorp/go-getter](https://github.com/hashicorp/go-getter) and [helm.sh/helm/v3](https://github.com/helm/helm).


Updates `github.com/hashicorp/go-getter` from 1.7.3 to 1.7.4
- [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.3...v1.7.4)

Updates `helm.sh/helm/v3` from 3.14.3 to 3.14.4
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.3...v3.14.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 14:58:32 +12:00
dependabot[bot]andlnx01 07d1747d81 chore(deps): bump helm.sh/helm/v3 from 3.14.3 to 3.14.4 in /examples/sdk/helm-template in the security group (#1525)
chore(deps): bump helm.sh/helm/v3

Bumps the security group in /examples/sdk/helm-template with 1 update: [helm.sh/helm/v3](https://github.com/helm/helm).


Updates `helm.sh/helm/v3` from 3.14.3 to 3.14.4
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.3...v3.14.4)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-16 00:18:04 +00:00
Evans MungaiandDexter Yan db871e6889 feat: node metrics analyser (#1520)
* feat: node metrics analyser

The analyser only checks PVC usage at the moment. More analysers
can be added on a need to have basis

* Add tests

* Fix flaky test by waiting for goldpinger pods to start

* Fix how outcomes get checked

* Fix catch all outcome condition

* Fix test

* feat: node metrics analyser

The analyser only checks PVC usage at the moment. More analysers
can be added on a need to have basis

* Add tests

* Fix flaky test by waiting for goldpinger pods to start

* Fix how outcomes get checked

* Fix catch all outcome condition

* Fix test

* Regenerate schemas

* Fix failing test

---------

Co-authored-by: Dexter Yan <yanshaocong@gmail.com>
2024-04-09 12:14:10 +01:00
dependabot[bot]andlnx01 dc4403811b chore(deps): bump the security group with 6 updates (#1522)
Bumps the security group with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.24.0` | `1.25.0` |
| [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.24.0` | `1.25.0` |
| [golang.org/x/mod](https://github.com/golang/mod) | `0.16.0` | `0.17.0` |
| [golang.org/x/sync](https://github.com/golang/sync) | `0.6.0` | `0.7.0` |
| [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) | `0.17.2` | `0.17.3` |
| [golang.org/x/net](https://github.com/golang/net) | `0.22.0` | `0.24.0` |


Updates `go.opentelemetry.io/otel` from 1.24.0 to 1.25.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.24.0...v1.25.0)

Updates `go.opentelemetry.io/otel/sdk` from 1.24.0 to 1.25.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.24.0...v1.25.0)

Updates `golang.org/x/mod` from 0.16.0 to 0.17.0
- [Commits](https://github.com/golang/mod/compare/v0.16.0...v0.17.0)

Updates `golang.org/x/sync` from 0.6.0 to 0.7.0
- [Commits](https://github.com/golang/sync/compare/v0.6.0...v0.7.0)

Updates `sigs.k8s.io/controller-runtime` from 0.17.2 to 0.17.3
- [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.17.2...v0.17.3)

Updates `golang.org/x/net` from 0.22.0 to 0.24.0
- [Commits](https://github.com/golang/net/compare/v0.22.0...v0.24.0)

---
updated-dependencies:
- dependency-name: go.opentelemetry.io/otel
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: golang.org/x/sync
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-09 00:18:07 +00:00
Ethan Mosbaugh 6f7acec7b3 feat: distribution analyzer support for kind (#1521) 2024-04-07 09:24:42 +12:00
Evans Mungai 123d17ab4a feat: node metrics collector (#1516)
* feat: node metrics collector

A collector to collect node metrics served by the API server as
per the documented API https://kubernetes.io/docs/reference/instrumentation/node-metrics/

* Update CRD schemas

* Add tests

* Remove clean from build target

* Update comments

* Commit missing tests

* Remove unnecessary log in tests
2024-04-02 14:59:55 +01:00
dependabot[bot]andlnx01 867c70619c chore(deps): bump the security group with 2 updates (#1519)
Bumps the security group with 2 updates: [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) and [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil).


Updates `github.com/go-sql-driver/mysql` from 1.8.0 to 1.8.1
- [Release notes](https://github.com/go-sql-driver/mysql/releases)
- [Changelog](https://github.com/go-sql-driver/mysql/blob/v1.8.1/CHANGELOG.md)
- [Commits](https://github.com/go-sql-driver/mysql/compare/v1.8.0...v1.8.1)

Updates `github.com/shirou/gopsutil/v3` from 3.24.2 to 3.24.3
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.2...v3.24.3)

---
updated-dependencies:
- dependency-name: github.com/go-sql-driver/mysql
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-02 00:18:00 +00:00
Evans Mungai c9830de736 chore: Update CLI prompt to run command as root (#1517) 2024-03-28 19:13:33 +00:00
Evans Mungai ca5ff88964 chore: Update code generator and controller tools (#1515) 2024-03-28 11:52:15 +00:00
Evans Mungai e6aff48f1b feat: Prompt for privileged user if host collectors present in spec (#1513)
* feat: Prompt for privileged user if host collectors present

* Prompt preflight checks that have host collectors

* Show cursor before prompting
2024-03-28 11:51:19 +00:00
Gerard Nguyen 76c52d2b93 New JSON field in HTTP request collector if any (#1511)
* add new raw_json field to http collector

* add unit test
2024-03-28 17:08:51 +11:00
dependabot[bot]andlnx01 bece801ba8 chore(deps): bump github.com/distribution/distribution/v3 from 3.0.0-20221208165359-362910506bc2 to 3.0.0-alpha.1 (#1466)
chore(deps): bump github.com/distribution/distribution/v3

Bumps [github.com/distribution/distribution/v3](https://github.com/distribution/distribution) from 3.0.0-20221208165359-362910506bc2 to 3.0.0-alpha.1.
- [Release notes](https://github.com/distribution/distribution/releases)
- [Commits](https://github.com/distribution/distribution/commits/v3.0.0-alpha.1)

---
updated-dependencies:
- dependency-name: github.com/distribution/distribution/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>
2024-03-25 20:00:07 +13:00
dependabot[bot]andlnx01 72701fa4d2 chore(deps): bump github.com/docker/docker from 25.0.3+incompatible to 25.0.5+incompatible (#1510)
chore(deps): bump github.com/docker/docker

Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.3+incompatible to 25.0.5+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.3...v25.0.5)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-21 00:18:26 +00:00
dependabot[bot]andlnx01 7eae0fe687 chore(deps): bump the security group with 8 updates (#1509)
Bumps the security group with 8 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/vmware-tanzu/velero](https://github.com/vmware-tanzu/velero) | `1.13.0` | `1.13.1` |
| [k8s.io/api](https://github.com/kubernetes/api) | `0.29.2` | `0.29.3` |
| [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.29.2` | `0.29.3` |
| [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.29.2` | `0.29.3` |
| [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.29.2` | `0.29.3` |
| [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) | `0.29.2` | `0.29.3` |
| [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.29.2` | `0.29.3` |
| [k8s.io/metrics](https://github.com/kubernetes/metrics) | `0.29.2` | `0.29.3` |


Updates `github.com/vmware-tanzu/velero` from 1.13.0 to 1.13.1
- [Release notes](https://github.com/vmware-tanzu/velero/releases)
- [Changelog](https://github.com/vmware-tanzu/velero/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vmware-tanzu/velero/compare/v1.13.0...v1.13.1)

Updates `k8s.io/api` from 0.29.2 to 0.29.3
- [Commits](https://github.com/kubernetes/api/compare/v0.29.2...v0.29.3)

Updates `k8s.io/apiextensions-apiserver` from 0.29.2 to 0.29.3
- [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases)
- [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.29.2...v0.29.3)

Updates `k8s.io/apimachinery` from 0.29.2 to 0.29.3
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.2...v0.29.3)

Updates `k8s.io/apiserver` from 0.29.2 to 0.29.3
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.29.2...v0.29.3)

Updates `k8s.io/cli-runtime` from 0.29.2 to 0.29.3
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.29.2...v0.29.3)

Updates `k8s.io/client-go` from 0.29.2 to 0.29.3
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.29.2...v0.29.3)

Updates `k8s.io/metrics` from 0.29.2 to 0.29.3
- [Commits](https://github.com/kubernetes/metrics/compare/v0.29.2...v0.29.3)

---
updated-dependencies:
- dependency-name: github.com/vmware-tanzu/velero
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiextensions-apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/metrics
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-19 00:17:50 +00:00
Gerard Nguyen 6f839b389d Quick fix to prevent panic on nil collector result (#1508)
* quick fix to prevent panic on nil collector result
* do not save pod details on error
2024-03-18 16:42:52 +11:00
dependabot[bot]andlnx01 ebe98ff2f1 chore(deps): bump the go_modules group group with 2 updates (#1507)
Bumps the go_modules group group with 2 updates: google.golang.org/protobuf and [helm.sh/helm/v3](https://github.com/helm/helm).


Updates `google.golang.org/protobuf` from 1.31.0 to 1.33.0

Updates `helm.sh/helm/v3` from 3.14.2 to 3.14.3
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.2...v3.14.3)

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
  dependency-group: go_modules-security-group
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  dependency-group: go_modules-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 00:17:47 +00:00
dependabot[bot]andlnx01 59624e88fd chore(deps): bump the go_modules group group in /examples/sdk/helm-template with 2 updates (#1506)
chore(deps): bump the go_modules group group

Bumps the go_modules group group in /examples/sdk/helm-template with 2 updates: [helm.sh/helm/v3](https://github.com/helm/helm) and google.golang.org/protobuf.


Updates `helm.sh/helm/v3` from 3.14.2 to 3.14.3
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.2...v3.14.3)

Updates `google.golang.org/protobuf` from 1.31.0 to 1.33.0

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  dependency-group: go_modules-security-group
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
  dependency-group: go_modules-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-14 00:17:18 +00:00
Evans Mungai 15446996f9 fix: Parse v1beta1 troubleshoot specs when using loader API (#1501) 2024-03-13 11:39:29 +00:00
dependabot[bot]andlnx01 c4237b6c40 chore(deps): bump the security group with 4 updates (#1503)
Bumps the security group with 4 updates: [github.com/containers/image/v5](https://github.com/containers/image), [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql), [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) and [golang.org/x/exp](https://github.com/golang/exp).


Updates `github.com/containers/image/v5` from 5.29.2 to 5.30.0
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.29.2...v5.30.0)

Updates `github.com/go-sql-driver/mysql` from 1.7.1 to 1.8.0
- [Release notes](https://github.com/go-sql-driver/mysql/releases)
- [Changelog](https://github.com/go-sql-driver/mysql/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-sql-driver/mysql/compare/v1.7.1...v1.8.0)

Updates `github.com/jackc/pgx/v5` from 5.5.4 to 5.5.5
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.5.4...v5.5.5)

Updates `golang.org/x/exp` from 0.0.0-20231006140011-7918f672742d to 0.0.0-20240222234643-814bf88cf225
- [Commits](https://github.com/golang/exp/commits)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: github.com/go-sql-driver/mysql
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: golang.org/x/exp
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-12 00:17:13 +00:00
Evans Mungai d0685ea81a fix: flaky goldpinger e2e test (#1499)
Installing the chart at times takes too long. We'll increase the time
that we wait for the application to be healthy
2024-03-07 17:19:22 +00:00
Gerard Nguyen 742e92f1ee New Event Analyzer (#1474)
* add new Event analyzer
2024-03-07 08:31:45 +13:00
Gerard Nguyen 553d709043 fix panic in Velero analyzer when there's no Velero deployment found (#1497)
* fix panic in Velero analyzer when there's no Velero deployment found

* do not omit error in find files
2024-03-05 21:58:37 +11:00
dependabot[bot]andlnx01 29435b1c15 chore(deps): bump the security group with 5 updates (#1498)
Bumps the security group with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) | `5.5.3` | `5.5.4` |
| [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) | `3.24.1` | `3.24.2` |
| [github.com/stretchr/testify](https://github.com/stretchr/testify) | `1.8.4` | `1.9.0` |
| [golang.org/x/mod](https://github.com/golang/mod) | `0.15.0` | `0.16.0` |
| [golang.org/x/net](https://github.com/golang/net) | `0.21.0` | `0.22.0` |


Updates `github.com/jackc/pgx/v5` from 5.5.3 to 5.5.4
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.5.3...v5.5.4)

Updates `github.com/shirou/gopsutil/v3` from 3.24.1 to 3.24.2
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.24.1...v3.24.2)

Updates `github.com/stretchr/testify` from 1.8.4 to 1.9.0
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.4...v1.9.0)

Updates `golang.org/x/mod` from 0.15.0 to 0.16.0
- [Commits](https://github.com/golang/mod/compare/v0.15.0...v0.16.0)

Updates `golang.org/x/net` from 0.21.0 to 0.22.0
- [Commits](https://github.com/golang/net/compare/v0.21.0...v0.22.0)

---
updated-dependencies:
- dependency-name: github.com/jackc/pgx/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: golang.org/x/mod
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-05 00:17:14 +00:00
dependabot[bot]andlnx01 a9b889e033 chore(deps): bump the security group with 3 updates (#1495)
Bumps the security group with 3 updates: [github.com/microsoft/go-mssqldb](https://github.com/microsoft/go-mssqldb), [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) and [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go).


Updates `github.com/microsoft/go-mssqldb` from 1.6.0 to 1.7.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.6.0...v1.7.0)

Updates `go.opentelemetry.io/otel` from 1.23.1 to 1.24.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.23.1...v1.24.0)

Updates `go.opentelemetry.io/otel/sdk` from 1.23.1 to 1.24.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.23.1...v1.24.0)

---
updated-dependencies:
- dependency-name: github.com/microsoft/go-mssqldb
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 18:05:45 +00:00
Xav PaiceandSalah Al Saleh 4a84e26f21 Update dependabot.yml (#1494)
* Update dependabot.yml

* update dependabot.yml

* add another label

---------

Co-authored-by: Salah Al Saleh <sg.alsaleh@gmail.com>
2024-02-27 15:44:07 +00:00
Salah Al Saleh 2eb3aa9883 Add delay between approving and merging PR in the automated PRs manager (#1493) 2024-02-28 03:06:31 +13:00
dependabot[bot]andlnx01 ffd357c1e8 chore(deps): bump the go_modules group across 2 directories with 1 update (#1492)
Bumps the go_modules group with 1 update in the / directory: [helm.sh/helm/v3](https://github.com/helm/helm).


Updates `helm.sh/helm/v3` from 3.14.1 to 3.14.2
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.1...v3.14.2)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  dependency-group: go_modules-security-group
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-27 06:05:54 +00:00
Salah Al Saleh 09287f624f Fix workflow name in automated PRs manager (#1491) 2024-02-26 15:16:39 -08:00
dependabot[bot]andlnx01 cd7f2dc74d chore(deps): bump helm.sh/helm/v3 from 3.14.1 to 3.14.2 in /examples/sdk/helm-template (#1490)
chore(deps): bump helm.sh/helm/v3 in /examples/sdk/helm-template

Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.14.1 to 3.14.2.
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.1...v3.14.2)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-26 22:41:19 +00:00
Salah Al Saleh 8132936e3e Fix automated PRs manager workflow (#1489)
* Fix automated PRs manager workflow
2024-02-26 14:30:21 -08:00
Xav PaiceandSalah Al Saleh b49d1050c9 feat: add dependabot auto merge (#1473)
* feat: add dependabot auto merge & grouping

Adds grouping for Dependabot PRs, meaning we no longer need to manually group PRs that fail tests due to incompatible groups.

Adds auto-merge of Dependabot PRs when they pass all tests.

* roll back dependabot label changes

* use secrets.GITHUB_TOKEN for automated PRs from Dependabot

* Automerge Dependabot PRS, use REPLICATED_GH_PAT for secret

* amend and simplify auto-dependabot job

* simplify PR jobs

* remove CODEOWNER ownership for go.mod

* Update .github/workflows/automated-prs-manager.yaml

Co-authored-by: Salah Al Saleh <sg.alsaleh@gmail.com>

---------

Co-authored-by: Salah Al Saleh <sg.alsaleh@gmail.com>
2024-02-23 12:28:39 +13:00
Xav Paice 27f867bd4e Update dependabot.yml (#1482) 2024-02-22 19:33:50 +13:00
Xav Paice f4d2cfb749 update Helm example for CVE (#1481) 2024-02-22 13:56:19 +13:00
dependabot[bot]andlnx01 8620e001d7 chore(deps): bump the security group with 16 updates (#1478)
Bumps the security group with 16 updates:

| Package | From | To |
| --- | --- | --- |
| [github.com/containers/image/v5](https://github.com/containers/image) | `5.29.0` | `5.29.2` |
| [github.com/google/uuid](https://github.com/google/uuid) | `1.4.0` | `1.6.0` |
| [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) | `3.23.12` | `3.24.1` |
| [github.com/vmware-tanzu/velero](https://github.com/vmware-tanzu/velero) | `1.10.3` | `1.13.0` |
| [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) | `1.23.0` | `1.23.1` |
| [go.opentelemetry.io/otel/sdk](https://github.com/open-telemetry/opentelemetry-go) | `1.23.0` | `1.23.1` |
| [k8s.io/api](https://github.com/kubernetes/api) | `0.29.1` | `0.29.2` |
| [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) | `0.29.0` | `0.29.2` |
| [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) | `0.29.1` | `0.29.2` |
| [k8s.io/apiserver](https://github.com/kubernetes/apiserver) | `0.29.0` | `0.29.2` |
| [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) | `0.29.1` | `0.29.2` |
| [k8s.io/client-go](https://github.com/kubernetes/client-go) | `0.29.1` | `0.29.2` |
| [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) | `0.17.0` | `0.17.2` |
| [golang.org/x/net](https://github.com/golang/net) | `0.19.0` | `0.21.0` |
| [helm.sh/helm/v3](https://github.com/helm/helm) | `3.14.0` | `3.14.1` |
| [k8s.io/metrics](https://github.com/kubernetes/metrics) | `0.29.0` | `0.29.2` |


Updates `github.com/containers/image/v5` from 5.29.0 to 5.29.2
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.29.0...v5.29.2)

Updates `github.com/google/uuid` from 1.4.0 to 1.6.0
- [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.4.0...v1.6.0)

Updates `github.com/shirou/gopsutil/v3` from 3.23.12 to 3.24.1
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.12...v3.24.1)

Updates `github.com/vmware-tanzu/velero` from 1.10.3 to 1.13.0
- [Release notes](https://github.com/vmware-tanzu/velero/releases)
- [Changelog](https://github.com/vmware-tanzu/velero/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vmware-tanzu/velero/compare/v1.10.3...v1.13.0)

Updates `go.opentelemetry.io/otel` from 1.23.0 to 1.23.1
- [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.23.0...v1.23.1)

Updates `go.opentelemetry.io/otel/sdk` from 1.23.0 to 1.23.1
- [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.23.0...v1.23.1)

Updates `k8s.io/api` from 0.29.1 to 0.29.2
- [Commits](https://github.com/kubernetes/api/compare/v0.29.1...v0.29.2)

Updates `k8s.io/apiextensions-apiserver` from 0.29.0 to 0.29.2
- [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases)
- [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.29.0...v0.29.2)

Updates `k8s.io/apimachinery` from 0.29.1 to 0.29.2
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.29.1...v0.29.2)

Updates `k8s.io/apiserver` from 0.29.0 to 0.29.2
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.29.0...v0.29.2)

Updates `k8s.io/cli-runtime` from 0.29.1 to 0.29.2
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.29.1...v0.29.2)

Updates `k8s.io/client-go` from 0.29.1 to 0.29.2
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.29.1...v0.29.2)

Updates `sigs.k8s.io/controller-runtime` from 0.17.0 to 0.17.2
- [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.17.0...v0.17.2)

Updates `golang.org/x/net` from 0.19.0 to 0.21.0
- [Commits](https://github.com/golang/net/compare/v0.19.0...v0.21.0)

Updates `helm.sh/helm/v3` from 3.14.0 to 3.14.1
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.14.0...v3.14.1)

Updates `k8s.io/metrics` from 0.29.0 to 0.29.2
- [Commits](https://github.com/kubernetes/metrics/compare/v0.29.0...v0.29.2)

---
updated-dependencies:
- dependency-name: github.com/containers/image/v5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: github.com/google/uuid
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: github.com/shirou/gopsutil/v3
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: github.com/vmware-tanzu/velero
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: go.opentelemetry.io/otel/sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiextensions-apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/apiserver
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/cli-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: sigs.k8s.io/controller-runtime
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: golang.org/x/net
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: security
- dependency-name: helm.sh/helm/v3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
- dependency-name: k8s.io/metrics
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: security
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-20 16:23:56 +13:00
dependabot[bot]andlnx01 bb9a2931a1 chore(deps): bump github.com/opencontainers/image-spec from 1.1.0-rc6 to 1.1.0 (#1479)
chore(deps): bump github.com/opencontainers/image-spec

Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc6 to 1.1.0.
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc6...v1.1.0)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/image-spec
  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>
2024-02-20 16:23:10 +13:00
Xav Paice 7c6788c0c5 Update dependabot.yml (#1477) 2024-02-20 15:42:17 +13:00
Ethan Mosbaugh e24ca642aa feat: sonobuoy collector (#1469) 2024-02-16 06:56:15 -08:00
dependabot[bot]andlnx01 7dc9d6dfe4 chore(deps): bump github.com/fatih/color from 1.15.0 to 1.16.0 (#1467)
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.15.0 to 1.16.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.15.0...v1.16.0)

---
updated-dependencies:
- dependency-name: github.com/fatih/color
  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>
2024-02-15 11:09:12 +00:00
dependabot[bot]andlnx01 118b2edc0a chore(deps): bump golang.org/x/mod from 0.14.0 to 0.15.0 (#1468)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.14.0 to 0.15.0.
- [Commits](https://github.com/golang/mod/compare/v0.14.0...v0.15.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  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>
2024-02-15 11:07:30 +00:00
dependabot[bot]andlnx01 84d51481da chore(deps): bump oras.land/oras-go from 1.2.4 to 1.2.5 (#1464)
Bumps [oras.land/oras-go](https://github.com/oras-project/oras-go) from 1.2.4 to 1.2.5.
- [Release notes](https://github.com/oras-project/oras-go/releases)
- [Commits](https://github.com/oras-project/oras-go/compare/v1.2.4...v1.2.5)

---
updated-dependencies:
- dependency-name: oras.land/oras-go
  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>
2024-02-15 10:47:46 +00:00
Evans Mungai fad7a26156 fix: improve flaky goldpinger test (#1463)
We do not need to check if goldpinger pinged or not. At times it would have successful pings that lead to test failures. Its enough to just check that we have analysis results
2024-02-09 16:33:52 +00:00
Gerard Nguyen 772d867093 update correct K8S API group for batch and policy (#1461) 2024-02-09 08:17:55 +13:00
Gerard Nguyen 5daf6d6c89 Feat: new collector run-daemonset (#1460)
* feat: new collector run-daemonset
2024-02-09 08:16:32 +13:00
Xav Paice 8b491b5702 Downgrade Velero to v1.10 (#1462)
In order to be compatible with KOTS, downgrade Velero to 1.10.

This removes some features from the Velero collector, but unblocks KOTS from being able
to import Troubleshoot.

We should be wary of updating Velero in the future to prevent this recurring.

sc-98475
2024-02-09 08:13:26 +13:00
18efea6616 chore(deps): bump go.opentelemetry.io/otel from 1.19.0 to 1.23.0 (#1459)
* chore(deps): bump go.opentelemetry.io/otel from 1.19.0 to 1.23.0

Bumps [go.opentelemetry.io/otel](https://github.com/open-telemetry/opentelemetry-go) from 1.19.0 to 1.23.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.19.0...v1.23.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>

* bump go.opentelemetry.io/otel/sdk

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Xav Paice <xav@replicated.com>
2024-02-07 11:35:41 +00:00
dependabot[bot]andlnx01 48fc8b2e84 chore(deps): bump k8s.io/klog/v2 from 2.110.1 to 2.120.1 (#1453)
Bumps [k8s.io/klog/v2](https://github.com/kubernetes/klog) from 2.110.1 to 2.120.1.
- [Release notes](https://github.com/kubernetes/klog/releases)
- [Changelog](https://github.com/kubernetes/klog/blob/main/RELEASE.md)
- [Commits](https://github.com/kubernetes/klog/compare/v2.110.1...v2.120.1)

---
updated-dependencies:
- dependency-name: k8s.io/klog/v2
  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>
2024-02-07 11:35:06 +00:00
Evans Mungai e2adfa3774 fix: Correct selector used to find installer specs when redacting (#1456) 2024-02-07 10:36:15 +00:00
Xav Paice 41134ca621 Revert "chore(deps): bump github.com/vmware-tanzu/velero from 1.12.0 to 1.13.0" (#1458)
Revert "chore(deps): bump github.com/vmware-tanzu/velero from 1.12.0 to 1.13.…"

This reverts commit d4c1e9cc04.
2024-02-07 13:21:01 +13:00
dependabot[bot]andlnx01 05a852d68c chore(deps): bump github.com/jackc/pgx/v5 from 5.5.2 to 5.5.3 (#1452)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.5.2 to 5.5.3.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.5.2...v5.5.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>
2024-02-06 20:41:43 +13:00
dependabot[bot]andlnx01 90d04b1f7d chore(deps): bump github.com/opencontainers/image-spec from 1.1.0-rc5 to 1.1.0-rc6 (#1454)
chore(deps): bump github.com/opencontainers/image-spec

Bumps [github.com/opencontainers/image-spec](https://github.com/opencontainers/image-spec) from 1.1.0-rc5 to 1.1.0-rc6.
- [Release notes](https://github.com/opencontainers/image-spec/releases)
- [Changelog](https://github.com/opencontainers/image-spec/blob/main/RELEASES.md)
- [Commits](https://github.com/opencontainers/image-spec/compare/v1.1.0-rc5...v1.1.0-rc6)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/image-spec
  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>
2024-02-06 20:41:13 +13:00
dependabot[bot]andlnx01 de0a2c631c chore(deps): bump helm.sh/helm/v3 from 3.13.3 to 3.14.0 (#1451)
Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  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>
2024-02-06 20:40:48 +13:00
Evans Mungai 2def517d39 chore: additional ceph collector commands (#1450)
* Collect text representations of the ceph data which are easier to read
* Collect ceph df command output
2024-02-06 10:04:25 +13:00
Xav PaiceandEvans Mungai fe6b1c7448 Add workaround for EKS version string (#1449)
* Add workaround for EKS version string

The EKS version string returned is not semver compliant.  To work around this, we remove
the suffix for version strings that contain -eks-.

Fixes #1441

* Add parsing version test cases

* Rename function

---------

Co-authored-by: Evans Mungai <evans@replicated.com>
2024-02-06 10:04:01 +13:00
Xav Paice 710366c8e5 bump containerd to patch for CVE-2024-21626 (#1445) 2024-02-01 17:16:51 +13:00
dependabot[bot]andlnx01 96529106c7 chore(deps): bump github.com/opencontainers/runc from 1.1.10 to 1.1.12 (#1444)
Bumps [github.com/opencontainers/runc](https://github.com/opencontainers/runc) from 1.1.10 to 1.1.12.
- [Release notes](https://github.com/opencontainers/runc/releases)
- [Changelog](https://github.com/opencontainers/runc/blob/v1.1.12/CHANGELOG.md)
- [Commits](https://github.com/opencontainers/runc/compare/v1.1.10...v1.1.12)

---
updated-dependencies:
- dependency-name: github.com/opencontainers/runc
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-01 14:43:58 +13:00
Gerard Nguyen 39b371991e feat: add timeout to run host collector (#1435)
* feat: add timeout to run host collector

* return error on invalid timeout

* return -1 on context deadline exceeded
2024-01-31 12:46:01 +00:00
dependabot[bot]andlnx01 d4c1e9cc04 chore(deps): bump github.com/vmware-tanzu/velero from 1.12.0 to 1.13.0 (#1437)
Bumps [github.com/vmware-tanzu/velero](https://github.com/vmware-tanzu/velero) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/vmware-tanzu/velero/releases)
- [Changelog](https://github.com/vmware-tanzu/velero/blob/main/CHANGELOG.md)
- [Commits](https://github.com/vmware-tanzu/velero/compare/v1.12.0...v1.13.0)

---
updated-dependencies:
- dependency-name: github.com/vmware-tanzu/velero
  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>
2024-01-30 13:33:35 +00:00
dependabot[bot]andlnx01 70a0024a76 chore(deps): bump k8s.io/cli-runtime from 0.29.0 to 0.29.1 (#1439)
Bumps [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) from 0.29.0 to 0.29.1.
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.29.0...v0.29.1)

---
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>
2024-01-30 13:33:23 +00:00
dependabot[bot]andlnx01 62984cba40 chore(deps): bump github.com/hashicorp/go-getter from 1.7.2 to 1.7.3 (#1438)
Bumps [github.com/hashicorp/go-getter](https://github.com/hashicorp/go-getter) from 1.7.2 to 1.7.3.
- [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.2...v1.7.3)

---
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>
2024-01-30 12:59:29 +00:00
Diamon WigginsandEvans Mungai 1447e18c56 feat: Allow templating of outcome messages for the JSON/YAML compare analyzers (#1432)
* feat: allow templating of the outcome message for the JSON and YAML Compare analyzers

* Update pkg/analyze/json_compare.go

Co-authored-by: Evans Mungai <evans@replicated.com>
2024-01-26 10:56:57 -05:00
Evans Mungai 37a5cce8ce chore: minor updates to docs and Makefile (#1433)
* Deprecate old Makefile targets
* Name Makefile targets to point to files they 'make' as per convention
* Update the contributing doc
* Update CLI docs left behind
2024-01-25 18:55:51 +00:00
dependabot[bot]andlnx01 80de5e3d12 chore(deps): bump github.com/spf13/cobra from 1.7.0 to 1.8.0 (#1422)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  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>
2024-01-23 19:05:54 +13:00
dependabot[bot]andlnx01 c1eddca1e5 chore(deps): bump github.com/gorilla/handlers from 1.5.1 to 1.5.2 (#1428)
Bumps [github.com/gorilla/handlers](https://github.com/gorilla/handlers) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/gorilla/handlers/releases)
- [Commits](https://github.com/gorilla/handlers/compare/v1.5.1...v1.5.2)

---
updated-dependencies:
- dependency-name: github.com/gorilla/handlers
  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>
2024-01-23 15:31:01 +13:00
dependabot[bot]andlnx01 19a04dc24e chore(deps): bump sigs.k8s.io/controller-runtime from 0.16.3 to 0.17.0 (#1429)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.16.3 to 0.17.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.16.3...v0.17.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>
2024-01-23 15:30:10 +13:00
dependabot[bot]andlnx01 5d51207f4d chore(deps): bump sigs.k8s.io/yaml from 1.3.0 to 1.4.0 (#1430)
Bumps [sigs.k8s.io/yaml](https://github.com/kubernetes-sigs/yaml) from 1.3.0 to 1.4.0.
- [Release notes](https://github.com/kubernetes-sigs/yaml/releases)
- [Changelog](https://github.com/kubernetes-sigs/yaml/blob/master/RELEASE.md)
- [Commits](https://github.com/kubernetes-sigs/yaml/compare/v1.3.0...v1.4.0)

---
updated-dependencies:
- dependency-name: sigs.k8s.io/yaml
  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>
2024-01-23 15:28:29 +13:00
dependabot[bot]andlnx01 8d727ea31f chore(deps): bump github.com/jackc/pgx/v5 from 5.4.3 to 5.5.2 (#1426)
Bumps [github.com/jackc/pgx/v5](https://github.com/jackc/pgx) from 5.4.3 to 5.5.2.
- [Changelog](https://github.com/jackc/pgx/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jackc/pgx/compare/v5.4.3...v5.5.2)

---
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>
2024-01-18 12:51:45 +00:00
dependabot[bot]andlnx01 b46f89af7f chore(deps): bump github.com/shirou/gopsutil/v3 from 3.23.9 to 3.23.12 (#1423)
Bumps [github.com/shirou/gopsutil/v3](https://github.com/shirou/gopsutil) from 3.23.9 to 3.23.12.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.23.9...v3.23.12)

---
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>
2024-01-18 12:17:29 +00:00
dependabot[bot]andlnx01 5ad108fab6 chore(deps): bump github.com/spf13/viper from 1.17.0 to 1.18.2 (#1421)
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.17.0 to 1.18.2.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.17.0...v1.18.2)

---
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>
2024-01-18 12:08:40 +00:00
Akash Shrivastava 361e12e691 feat: [ISSUE-1401]: Added helm get values option in Helm collector (#1402)
* feat: [ISSUE-1401]: Added helm get values option in Helm collector

Signed-off-by: Akash Shrivastava <akash.shrivastava@harness.io>

* Made changes in error handling

Signed-off-by: Akash Shrivastava <akash.shrivastava@harness.io>

* feat: [ISSUE-1401]: Added test cases and fixes

Signed-off-by: Akash Shrivastava <akash.shrivastava@harness.io>

* fixed test case

Signed-off-by: Akash Shrivastava <akash.shrivastava@harness.io>

---------

Signed-off-by: Akash Shrivastava <akash.shrivastava@harness.io>
2024-01-16 19:12:43 +00:00
Xav Paice e542f4fd0a bump k8s.io packages to v0.29.0 (#1419)
* bump k8s.io packages to v0.29.0

* update Go to 1.21

* update schemas
2024-01-08 17:24:41 +00:00
Evans Mungai e4363a1e50 fix (supportbundle): Add default collectors when expected (#1418)
* fix (supportbundle): Add default collectors when expected

* Remove unnecessary change

* Add default collectors to a empty spec

* Add more tests
2024-01-08 11:32:04 +00:00
dependabot[bot]andlnx01 b5996d06ba chore(deps): bump github.com/go-logr/logr from 1.2.4 to 1.4.1 (#1412)
Bumps [github.com/go-logr/logr](https://github.com/go-logr/logr) from 1.2.4 to 1.4.1.
- [Release notes](https://github.com/go-logr/logr/releases)
- [Changelog](https://github.com/go-logr/logr/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-logr/logr/compare/v1.2.4...v1.4.1)

---
updated-dependencies:
- dependency-name: github.com/go-logr/logr
  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>
2024-01-02 16:05:18 +00:00
dependabot[bot]andlnx01 b1b6299ed5 chore(deps): bump golang.org/x/mod from 0.13.0 to 0.14.0 (#1414)
Bumps [golang.org/x/mod](https://github.com/golang/mod) from 0.13.0 to 0.14.0.
- [Commits](https://github.com/golang/mod/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/mod
  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>
2024-01-02 16:04:29 +00:00
dependabot[bot]andlnx01 7681cc249c chore(deps): bump sigs.k8s.io/controller-runtime from 0.16.2 to 0.16.3 (#1416)
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.16.2 to 0.16.3.
- [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.16.2...v0.16.3)

---
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>
2024-01-02 16:03:33 +00:00
dependabot[bot]andlnx01 cad5e8179c chore(deps): bump helm.sh/helm/v3 from 3.12.3 to 3.13.3 (#1410)
Bumps [helm.sh/helm/v3](https://github.com/helm/helm) from 3.12.3 to 3.13.3.
- [Release notes](https://github.com/helm/helm/releases)
- [Commits](https://github.com/helm/helm/compare/v3.12.3...v3.13.3)

---
updated-dependencies:
- dependency-name: helm.sh/helm/v3
  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-12-29 08:03:59 +13:00
Andrew Laveryandlnx01 4c77bcb7cc Update containers/image, oras-go, and docker (#1411)
* chore(deps): bump github.com/containers/image/v5 from 5.25.0 to 5.29.0

Bumps [github.com/containers/image/v5](https://github.com/containers/image) from 5.25.0 to 5.29.0.
- [Release notes](https://github.com/containers/image/releases)
- [Commits](https://github.com/containers/image/compare/v5.25.0...v5.29.0)

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

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

* regenerate files

* bump oras-go

* changes from 'make test'

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-12-28 13:31:05 -05:00
128 changed files with 66014 additions and 15749 deletions
+5 -1
View File
@@ -14,4 +14,8 @@
## RULES
* @replicatedhq/troubleshoot
*.md @replicatedhq/cre
*.md @replicatedhq/cre
go.mod
go.sum
/examples/sdk/helm-template/go.mod
/examples/sdk/helm-template/go.sum
+21 -3
View File
@@ -10,10 +10,28 @@ updates:
labels:
- "dependencies"
- "go"
- "type::chore"
- "type::security"
schedule:
interval: "weekly"
groups:
security:
update-types:
- "patch"
- "minor"
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/examples/sdk/helm-template" # Location of package manifests
labels:
- "dependencies"
- "go"
- "type::security"
schedule:
interval: "weekly"
groups:
security:
update-types:
- "patch"
- "minor"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
# Workflow files stored in the
@@ -22,6 +40,6 @@ updates:
labels:
- "dependencies"
- "github-actions"
- "type::chore"
- "type::security"
schedule:
interval: "weekly"
@@ -0,0 +1,97 @@
name: Automated PRs Manager
on:
schedule:
- cron: "0 */6 * * *" # every 6 hours
workflow_dispatch: {}
jobs:
list-prs:
runs-on: ubuntu-latest
outputs:
prs: ${{ steps.list-prs.outputs.prs }}
env:
GH_TOKEN: ${{ secrets.REPLICATED_GH_PAT }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: List PRs
id: list-prs
run: |
set -euo pipefail
# list prs that are less than 24h old and exclude prs from forks
dependabot_prs=$(
gh pr list \
--author 'dependabot[bot]' \
--json url,createdAt,headRefName,headRepository,headRepositoryOwner \
-q '.[] | select((.createdAt | fromdateiso8601 > now - 24*60*60) and .headRepositoryOwner.login == "replicatedhq" and .headRepository.name == "troubleshoot")'
)
prs=$(echo "$dependabot_prs" | jq -sc '. | unique')
echo "prs=$prs" >> "$GITHUB_OUTPUT"
process-prs:
needs: list-prs
runs-on: ubuntu-latest
if: needs.list-prs.outputs.prs != '[]'
strategy:
matrix:
pr: ${{ fromJson(needs.list-prs.outputs.prs) }}
fail-fast: false
max-parallel: 1
env:
GH_TOKEN: ${{ secrets.REPLICATED_GH_PAT }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ matrix.pr.headRefName }}
- name: Process PR
run: |
set -euo pipefail
echo "Ensuring required labels..."
gh pr edit "${{ matrix.pr.url }}" --add-label "type::security"
echo "Checking status of tests..."
run_id=$(gh run list --branch "${{ matrix.pr.headRefName }}" --workflow build-test-deploy --limit 1 --json databaseId -q '.[0].databaseId')
# If there are still pending jobs, skip.
num_of_pending_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[] | select(.conclusion == "") | .name' | wc -l)
if [ "$num_of_pending_jobs" -gt 0 ]; then
echo "There are still pending jobs. Skipping."
exit 0
fi
# If all checks passed, approve and merge.
if gh run view "$run_id" --json jobs -q '.jobs[] | select(.name == "validate-success") | .conclusion' | grep -q "success"; then
if gh pr checks "${{ matrix.pr.url }}"; then
echo "All tests passed. Approving and merging."
echo -e "LGTM :thumbsup: \n\nThis PR was automatically approved and merged by the [automated-prs-manager](https://github.com/replicatedhq/troubleshoot/blob/main/.github/workflows/automated-prs-manager.yaml) GitHub action" > body.txt
gh pr review --approve "${{ matrix.pr.url }}" --body-file body.txt
sleep 10
gh pr merge --auto --squash "${{ matrix.pr.url }}"
exit 0
else
echo "Some checks did not pass. Skipping."
exit 0
fi
fi
# If more than half of the jobs are successful, re-run the failed jobs.
num_of_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[].name ' | wc -l)
num_of_successful_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[] | select(.conclusion == "success") | .name' | wc -l)
if [ "$num_of_successful_jobs" -gt $((num_of_jobs / 2)) ]; then
echo "More than half of the jobs are successful. Re-running failed jobs."
gh run rerun "$run_id" --failed
exit 0
fi
echo "Less than half of the jobs are successful. Skipping."
+49 -10
View File
@@ -1,3 +1,5 @@
name: build-test-deploy
on:
pull_request:
types:
@@ -30,7 +32,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
@@ -47,7 +49,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
@@ -59,7 +61,7 @@ jobs:
- uses: replicatedhq/action-k3s@main
id: k3s
with:
version: v1.23.6-k3s1
version: v1.24.1-k3s1
- run: make test-integration
@@ -68,7 +70,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
@@ -84,7 +86,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
@@ -173,7 +175,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
@@ -228,7 +230,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
@@ -248,7 +250,7 @@ jobs:
steps:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
@@ -281,7 +283,7 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
@@ -312,7 +314,7 @@ jobs:
- uses: actions/setup-go@v5
with:
go-version: "1.20"
go-version: "1.21"
- uses: sigstore/cosign-installer@v3
with:
@@ -348,3 +350,40 @@ jobs:
uses: rajatjindal/krew-release-bot@v0.0.46
with:
krew_template_file: deploy/krew/support-bundle.yaml
# summary jobs, these jobs will only run if all the other jobs have succeeded
validate-pr-tests:
runs-on: ubuntu-latest
needs:
- test
- test-integration
- run-examples
- compile-collect
- validate-preflight
- validate-preflight-e2e
- validate-supportbundle
- validate-supportbundle-e2e
- validate-supportbundle-e2e-go-test
- ensure-schemas-are-generated
steps:
- run: echo "All PR tests passed"
# this job will validate that the validation did not fail and that all pr-tests succeed
# it is used for the github branch protection rule
validate-success:
runs-on: ubuntu-latest
needs:
- validate-pr-tests
if: always()
steps:
# https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
# if the validate-pr-tests job was not successful, this job will fail
- name: fail if validate-pr-tests job was not successful
if: needs.validate-pr-tests.result != 'success'
run: exit 1
# if the validate-pr-tests job was successful, this job will succeed
- name: succeed if validate-pr-tests job succeeded
if: needs.validate-pr-tests.result == 'success'
run: echo "Validation succeeded"
+2
View File
@@ -17,6 +17,8 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.21
- name: Install Go deps
run: go mod download
+1
View File
@@ -10,3 +10,4 @@ linters:
- gocyclo
- gofmt
- gosec
- govet
+4 -4
View File
@@ -23,12 +23,12 @@ To get started we recommend:
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
5. Run `make run-troubleshoot` to generate a support bundle with the `sample-troubleshoot.yaml` in the root of the repo
3. Fork and clone repo
4. Run `make clean build` to generate binaries
5. Run `make run-support-bundle` to generate a support bundle with the `sample-troubleshoot.yaml` in the root of the repo
> Note: recent versions of Go support easy cross-compilation. For example, to cross-compile a Linux binary from MacOS:
> `GOOS=linux GOARCH=amd64 make support-bundle preflight`
> `GOOS=linux GOARCH=amd64 make clean build`
6. Install [golangci-lint] linter and run `make lint` to execute additional code linters.
+73 -45
View File
@@ -39,8 +39,8 @@ BUILDPATHS = ./pkg/... ./cmd/... ./internal/...
E2EPATHS = ./test/e2e/...
TESTFLAGS ?= -v -coverprofile cover.out
.DEFAULT: all
all: test build
.DEFAULT_GOAL := all
all: clean build test
.PHONY: ffi
ffi: fmt vet
@@ -80,28 +80,38 @@ support-bundle-e2e-go-test:
go test ${BUILDFLAGS} ${E2EPATHS} -v; \
fi
# Build all binaries in parallel ( -j )
build:
@echo "Build cli binaries"
$(MAKE) -j support-bundle preflight analyze collect
rebuild: clean build
mod-tidy:
# Build all binaries in parallel ( -j )
build: tidy
@echo "Build cli binaries"
$(MAKE) -j bin/support-bundle bin/preflight bin/analyze bin/collect
.PHONY: clean
clean:
@rm -f bin/analyze
@rm -f bin/support-bundle
@rm -f bin/collect
@rm -f bin/preflight
@rm -f bin/troubleshoot.h
@rm -f bin/troubleshoot.so
@rm -f bin/schemagen
@rm -f bin/docsgen
.PHONY: tidy
tidy:
go mod tidy
.PHONY: support-bundle
support-bundle:
bin/support-bundle:
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
.PHONY: preflight
preflight:
bin/preflight:
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
.PHONY: analyze
analyze:
bin/analyze:
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/analyze github.com/replicatedhq/troubleshoot/cmd/analyze
.PHONY: collect
collect:
bin/collect:
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/collect github.com/replicatedhq/troubleshoot/cmd/collect
.PHONY: fmt
@@ -138,27 +148,27 @@ check-schemas: generate schemas
fi
.PHONY: schemas
schemas: fmt vet openapischema
go build ${LDFLAGS} -o bin/schemagen github.com/replicatedhq/troubleshoot/cmd/schemagen
schemas: fmt vet openapischema bin/schemagen
./bin/schemagen --output-dir ./schemas
bin/schemagen:
go build ${LDFLAGS} -o bin/schemagen github.com/replicatedhq/troubleshoot/cmd/schemagen
.PHONY: docs
docs: fmt vet
go build ${LDFLAGS} -o bin/docsgen github.com/replicatedhq/troubleshoot/cmd/docsgen
docs: fmt vet bin/docsgen
./bin/docsgen
bin/docsgen:
go build ${LDFLAGS} -o bin/docsgen github.com/replicatedhq/troubleshoot/cmd/docsgen
controller-gen:
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.11.2
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0
CONTROLLER_GEN=$(shell which controller-gen)
.PHONY: client-gen
client-gen:
ifeq (, $(shell which client-gen 2>/dev/null))
go install k8s.io/code-generator/cmd/client-gen@v0.28.2
CLIENT_GEN=$(shell go env GOPATH)/bin/client-gen
else
go install k8s.io/code-generator/cmd/client-gen@v0.28.8
CLIENT_GEN=$(shell which client-gen)
endif
.PHONY: release
release: export GITHUB_TOKEN = $(shell echo ${GITHUB_TOKEN_TROUBLESHOOT})
@@ -180,15 +190,15 @@ local-release:
docker push localhost:32000/preflight:alpha
.PHONY: run-preflight
run-preflight: preflight
run-preflight: bin/preflight
./bin/preflight ./examples/preflight/sample-preflight.yaml
.PHONY: run-troubleshoot
run-troubleshoot: support-bundle
.PHONY: run-support-bundle
run-support-bundle: bin/support-bundle
./bin/support-bundle ./examples/support-bundle/sample-supportbundle.yaml
.PHONY: run-analyze
run-analyze: analyze
run-analyze: bin/analyze
./bin/analyze --analyzers ./examples/support-bundle/sample-analyzers.yaml ./support-bundle.tar.gz
.PHONY: init-sbom
@@ -212,20 +222,6 @@ sbom: sbom/assets/troubleshoot-sbom.tgz
cosign sign-blob -key cosign.key sbom/assets/troubleshoot-sbom.tgz > sbom/assets/troubleshoot-sbom.tgz.sig
cosign public-key -key cosign.key -outfile sbom/assets/key.pub
longhorn:
git clone https://github.com/longhorn/longhorn-manager.git
cd longhorn-manager && git checkout v1.2.2 && cd ..
rm -rf pkg/longhorn
mv longhorn-manager/k8s/pkg pkg/longhorn
mv longhorn-manager/types pkg/longhorn/types
mv longhorn-manager/util pkg/longhorn/util
rm -rf pkg/longhorn/util/daemon
rm -rf pkg/longhorn/util/server
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/k8s\/pkg/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn/g"
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/types/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn\/types/g"
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/util/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn\/util/g"
rm -rf longhorn-manager
.PHONY: scan
scan:
trivy fs \
@@ -236,11 +232,11 @@ scan:
./
.PHONY: lint
lint: fmt vet
lint:
golangci-lint run --new -c .golangci.yaml ${BUILDPATHS}
.PHONY: lint-and-fix
lint-and-fix: fmt vet
lint-and-fix:
golangci-lint run --new --fix -c .golangci.yaml ${BUILDPATHS}
.PHONY: watch
@@ -256,3 +252,35 @@ watchrsync: 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 --no-save gaze-run-interrupt@~2.0.0
######## Lagacy make targets ###########
# Deprecated: These can be removed
.PHONY: support-bundle
support-bundle: clean bin/support-bundle
.PHONY: preflight
preflight: clean bin/preflight
.PHONY: analyze
analyze: clean bin/analyze
.PHONY: collect
collect: clean bin/collect
.PHONY: run-troubleshoot
run-troubleshoot: run-support-bundle
longhorn:
git clone https://github.com/longhorn/longhorn-manager.git
cd longhorn-manager && git checkout v1.2.2 && cd ..
rm -rf pkg/longhorn
mv longhorn-manager/k8s/pkg pkg/longhorn
mv longhorn-manager/types pkg/longhorn/types
mv longhorn-manager/util pkg/longhorn/util
rm -rf pkg/longhorn/util/daemon
rm -rf pkg/longhorn/util/server
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/k8s\/pkg/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn/g"
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/types/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn\/types/g"
find pkg/longhorn -type f | xargs sed -i "s/github.com\/longhorn\/longhorn-manager\/util/github.com\/replicatedhq\/troubleshoot\/pkg\/longhorn\/util/g"
rm -rf longhorn-manager
+59 -34
View File
@@ -106,6 +106,22 @@ func runTroubleshoot(v *viper.Viper, args []string) error {
})
}
if interactive {
c := color.New()
c.Println(fmt.Sprintf("\r%s\r", cursor.ClearEntireLine()))
}
if interactive {
if len(mainBundle.Spec.HostCollectors) > 0 && !util.IsRunningAsRoot() {
fmt.Print(cursor.Show())
if util.PromptYesNo(util.HOST_COLLECTORS_RUN_AS_ROOT_PROMPT) {
fmt.Println("Exiting...")
return nil
}
fmt.Print(cursor.Hide())
}
}
var wg sync.WaitGroup
collectorCB := func(c chan interface{}, msg string) { c <- msg }
progressChan := make(chan interface{})
@@ -174,11 +190,6 @@ func runTroubleshoot(v *viper.Viper, args []string) error {
nonInteractiveOutput := analysisOutput{}
if interactive {
c := color.New()
c.Println(fmt.Sprintf("\r%s\r", cursor.ClearEntireLine()))
}
response, err := supportbundle.CollectSupportBundleFromSpec(&mainBundle.Spec, additionalRedactors, createOpts)
if err != nil {
return errors.Wrap(err, "failed to run collect and analyze process")
@@ -234,35 +245,42 @@ the %s Admin Console to begin analysis.`
// loadSupportBundleSpecsFromURIs loads support bundle specs from URIs
func loadSupportBundleSpecsFromURIs(ctx context.Context, kinds *loader.TroubleshootKinds) error {
remoteRawSpecs := []string{}
moreKinds := loader.NewTroubleshootKinds()
// iterate through original kinds and replace any support bundle spec with provided uri spec
for _, s := range kinds.SupportBundlesV1Beta2 {
if s.Spec.Uri != "" && util.IsURL(s.Spec.Uri) {
// We are using LoadSupportBundleSpec function here since it handles prompting
// users to accept insecure connections
// There is an opportunity to refactor this code in favour of the Loader APIs
// TODO: Pass ctx to LoadSupportBundleSpec
rawSpec, err := supportbundle.LoadSupportBundleSpec(s.Spec.Uri)
if err != nil {
// In the event a spec can't be loaded, we'll just skip it and print a warning
klog.Warningf("unable to load support bundle from URI: %q: %v", s.Spec.Uri, err)
continue
}
remoteRawSpecs = append(remoteRawSpecs, string(rawSpec))
if s.Spec.Uri == "" || !util.IsURL(s.Spec.Uri) {
moreKinds.SupportBundlesV1Beta2 = append(moreKinds.SupportBundlesV1Beta2, s)
continue
}
// We are using LoadSupportBundleSpec function here since it handles prompting
// users to accept insecure connections
// There is an opportunity to refactor this code in favour of the Loader APIs
// TODO: Pass ctx to LoadSupportBundleSpec
rawSpec, err := supportbundle.LoadSupportBundleSpec(s.Spec.Uri)
if err != nil {
// add back original spec
moreKinds.SupportBundlesV1Beta2 = append(moreKinds.SupportBundlesV1Beta2, s)
// In the event a spec can't be loaded, we'll just skip it and print a warning
klog.Warningf("unable to load support bundle from URI: %q: %v", s.Spec.Uri, err)
continue
}
k, err := loader.LoadSpecs(ctx, loader.LoadOptions{RawSpec: string(rawSpec)})
if err != nil {
// add back original spec
moreKinds.SupportBundlesV1Beta2 = append(moreKinds.SupportBundlesV1Beta2, s)
klog.Warningf("unable to load spec: %v", err)
continue
}
// finally append the uri spec
moreKinds.SupportBundlesV1Beta2 = append(moreKinds.SupportBundlesV1Beta2, k.SupportBundlesV1Beta2...)
}
if len(remoteRawSpecs) == 0 {
return nil
}
kinds.SupportBundlesV1Beta2 = moreKinds.SupportBundlesV1Beta2
moreKinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
RawSpecs: remoteRawSpecs,
})
if err != nil {
return err
}
kinds.Add(moreKinds)
return nil
}
@@ -315,11 +333,12 @@ func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface)
mainBundle.Spec.HostCollectors = util.Append(mainBundle.Spec.HostCollectors, hc.Spec.Collectors)
}
if mainBundle.Spec.Collectors != nil {
// If we have in-cluster collectors, ensure cluster info and cluster resources
// collectors are in the merged spec. We need to add them here so when we --dry-run,
// these collectors are included. supportbundle.runCollectors duplicates this bit.
// We'll need to refactor it out later when its clearer what other code depends on this logic e.g KOTS
if !(len(mainBundle.Spec.HostCollectors) > 0 && len(mainBundle.Spec.Collectors) == 0) {
// Always add default collectors unless we only have host collectors
// We need to add them here so when we --dry-run, these collectors
// are included. supportbundle.runCollectors duplicates this bit.
// We'll need to refactor it out later when its clearer what other
// code depends on this logic e.g KOTS
mainBundle.Spec.Collectors = collect.EnsureCollectorInList(
mainBundle.Spec.Collectors,
troubleshootv1beta2.Collect{ClusterInfo: &troubleshootv1beta2.ClusterInfo{}},
@@ -343,6 +362,12 @@ func loadSpecs(ctx context.Context, args []string, client kubernetes.Interface)
additionalRedactors.Spec.Redactors = util.Append(additionalRedactors.Spec.Redactors, r.Spec.Redactors)
}
// dedupe specs
mainBundle.Spec.Collectors = util.Dedup(mainBundle.Spec.Collectors)
mainBundle.Spec.Analyzers = util.Dedup(mainBundle.Spec.Analyzers)
mainBundle.Spec.HostCollectors = util.Dedup(mainBundle.Spec.HostCollectors)
mainBundle.Spec.HostAnalyzers = util.Dedup(mainBundle.Spec.HostAnalyzers)
return mainBundle, additionalRedactors, nil
}
+286 -5
View File
@@ -9,13 +9,17 @@ import (
"testing"
"time"
"github.com/replicatedhq/troubleshoot/internal/testutils"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/httputil"
"github.com/replicatedhq/troubleshoot/pkg/loader"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
testclient "k8s.io/client-go/kubernetes/fake"
)
var orig = `
func templSpec() string {
return `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
@@ -27,6 +31,7 @@ spec:
name: kube-root-ca.crt
namespace: default
`
}
func Test_loadSupportBundleSpecsFromURIs(t *testing.T) {
// Run a webserver to serve the spec
@@ -42,7 +47,7 @@ spec:
}))
defer srv.Close()
orig := strings.ReplaceAll(orig, "$MY_URI", srv.URL)
orig := strings.ReplaceAll(templSpec(), "$MY_URI", srv.URL)
ctx := context.Background()
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{RawSpec: orig})
@@ -54,8 +59,73 @@ spec:
err = loadSupportBundleSpecsFromURIs(ctx, kinds)
require.NoError(t, err)
require.Len(t, kinds.SupportBundlesV1Beta2, 2)
assert.NotNil(t, kinds.SupportBundlesV1Beta2[1].Spec.Collectors[0].ClusterInfo)
require.Len(t, kinds.SupportBundlesV1Beta2, 1)
assert.NotNil(t, kinds.SupportBundlesV1Beta2[0].Spec.Collectors[0].ClusterInfo)
}
func Test_loadMultipleSupportBundleSpecsWithNoURIs(t *testing.T) {
ctx := context.Background()
client := testclient.NewSimpleClientset()
specs := []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-1
spec:
collectors:
- clusterInfo:{}`), testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-2
spec:
collectors:
- clusterInfo: {}`)}
sb, _, err := loadSpecs(ctx, specs, client)
require.NoError(t, err)
require.Len(t, sb.Spec.Collectors, 2)
}
func Test_loadMultipleSupportBundleSpecsWithURIs(t *testing.T) {
ctx := context.Background()
client := testclient.NewSimpleClientset()
specFile := testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-file
spec:
collectors:
- logs:
name: podlogs/kotsadm
selector:
- app=kotsadm
`)
// Run a webserver to serve the spec
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(`
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb-uri
spec:
collectors:
- clusterInfo: {}`))
}))
defer srv.Close()
orig := strings.ReplaceAll(templSpec(), "$MY_URI", srv.URL)
specUri := testutils.ServeFromFilePath(t, orig)
specs := []string{specFile, specUri}
sb, _, err := loadSpecs(ctx, specs, client)
require.NoError(t, err)
assert.NotNil(t, sb.Spec.Collectors[0].Logs)
assert.Nil(t, sb.Spec.Collectors[1].ConfigMap) // original spec gone
assert.NotNil(t, sb.Spec.Collectors[1].ClusterInfo) // new spec from URI
}
func Test_loadSupportBundleSpecsFromURIs_TimeoutError(t *testing.T) {
@@ -66,7 +136,7 @@ func Test_loadSupportBundleSpecsFromURIs_TimeoutError(t *testing.T) {
ctx := context.Background()
kinds, err := loader.LoadSpecs(ctx, loader.LoadOptions{
RawSpec: strings.ReplaceAll(orig, "$MY_URI", srv.URL),
RawSpec: strings.ReplaceAll(templSpec(), "$MY_URI", srv.URL),
})
require.NoError(t, err)
@@ -90,3 +160,214 @@ func Test_loadSupportBundleSpecsFromURIs_TimeoutError(t *testing.T) {
assert.JSONEq(t, string(beforeJSON), string(afterJSON))
}
func Test_loadSupportBundleSpecs(t *testing.T) {
tests := []struct {
name string
args []string
expected troubleshootv1beta2.SupportBundleSpec
}{
{
name: "empty collectors array in spec, default collectors added",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors: []
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
},
},
{
name: "no collectors defined in spec, default collectors added",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
analyzers: []
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
Analyzers: []*troubleshootv1beta2.Analyze{},
},
},
{
name: "collectors present but defaults missing, default collectors added",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
collectors:
- logs: {}
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
Logs: &troubleshootv1beta2.Logs{},
},
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
},
},
{
name: "empty support bundle spec adds default collectors",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
Collectors: []*troubleshootv1beta2.Collect{
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
},
},
{
name: "sb spec with host collectors does not add default collectors",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
hostCollectors:
- cpu: {}
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
HostCollectors: []*troubleshootv1beta2.HostCollect{
{
CPU: &troubleshootv1beta2.CPU{},
},
},
},
},
{
name: "host collector spec with collectors does not add default collectors",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
spec:
collectors:
- cpu: {}
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
HostCollectors: []*troubleshootv1beta2.HostCollect{
{
CPU: &troubleshootv1beta2.CPU{},
},
},
},
},
{
name: "sb spec with host and in-cluster collectors adds default collectors",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
hostCollectors:
- cpu: {}
collectors:
- logs: {}
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
HostCollectors: []*troubleshootv1beta2.HostCollect{
{
CPU: &troubleshootv1beta2.CPU{},
},
},
Collectors: []*troubleshootv1beta2.Collect{
{
Logs: &troubleshootv1beta2.Logs{},
},
{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
},
},
},
{
name: "sb spec with host collectors and empty in-cluster collectors does not default collectors",
args: []string{testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
spec:
hostCollectors:
- cpu: {}
collectors: []
`)},
expected: troubleshootv1beta2.SupportBundleSpec{
HostCollectors: []*troubleshootv1beta2.HostCollect{
{
CPU: &troubleshootv1beta2.CPU{},
},
},
Collectors: []*troubleshootv1beta2.Collect{},
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ctx := context.Background()
client := testclient.NewSimpleClientset()
sb, _, err := loadSpecs(ctx, test.args, client)
require.NoError(t, err)
assert.Equal(t, test.expected, sb.Spec)
})
}
}
func Test_loadDuplicatedBundleSpecs(t *testing.T) {
spec := testutils.ServeFromFilePath(t, `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: sb
spec:
collectors:
- helm: {}
analyzers:
- clusterVersion: {}
hostCollectors:
- cpu: {}
hostAnalyzers:
- cpu: {}
`)
args := []string{spec, spec}
ctx := context.Background()
client := testclient.NewSimpleClientset()
sb, _, err := loadSpecs(ctx, args, client)
require.NoError(t, err)
assert.Len(t, sb.Spec.Collectors, 1+2) // default clusterInfo + clusterResources
assert.Len(t, sb.Spec.Analyzers, 1)
assert.Len(t, sb.Spec.HostCollectors, 1)
assert.Len(t, sb.Spec.HostAnalyzers, 1)
}
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: analyzers.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
@@ -21,14 +20,19 @@ spec:
description: Analyzer is the Schema for the analyzers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: collectors.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
@@ -21,14 +20,19 @@ spec:
description: Collector is the Schema for the collectors API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -164,10 +168,10 @@ spec:
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.
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:
@@ -188,10 +192,10 @@ spec:
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.
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:
@@ -210,10 +214,10 @@ spec:
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.
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:
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: preflights.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
@@ -21,14 +20,19 @@ spec:
description: Preflight is the Schema for the preflights API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -836,10 +840,10 @@ spec:
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.
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:
@@ -860,10 +864,10 @@ spec:
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.
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:
@@ -882,10 +886,10 @@ spec:
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.
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:
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: redactors.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
@@ -21,14 +20,19 @@ spec:
description: Redactor is the Schema for the redaction API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: supportbundles.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
@@ -21,14 +20,19 @@ spec:
description: SupportBundle is the Schema for the SupportBundles API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -867,10 +871,10 @@ spec:
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.
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:
@@ -891,10 +895,10 @@ spec:
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.
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:
@@ -913,10 +917,10 @@ spec:
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.
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:
+131 -8
View File
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: analyzers.troubleshoot.sh
spec:
group: troubleshoot.sh
@@ -21,14 +20,19 @@ spec:
description: Analyzer is the Schema for the analyzers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -559,6 +563,65 @@ spec:
required:
- outcomes
type: object
event:
properties:
annotations:
additionalProperties:
type: string
type: object
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
kind:
type: string
namespace:
type: string
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
reason:
type: string
regex:
type: string
strict:
type: BoolString
required:
- collectorName
- outcomes
- reason
type: object
goldpinger:
properties:
annotations:
@@ -982,6 +1045,66 @@ spec:
- collectorName
- outcomes
type: object
nodeMetrics:
properties:
annotations:
additionalProperties:
type: string
type: object
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
filters:
properties:
pvc:
properties:
nameRegex:
type: string
namespace:
type: string
type: object
type: object
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:
- collectorName
- outcomes
type: object
nodeResources:
properties:
annotations:
File diff suppressed because it is too large Load Diff
+49 -46
View File
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: hostcollectors.troubleshoot.sh
spec:
group: troubleshoot.sh
@@ -21,14 +20,19 @@ spec:
description: HostCollector is the Schema for the collectors API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -1155,9 +1159,9 @@ spec:
- path
type: object
filesystemPerformance:
description: FilesystemPerformance benchmarks sequential write
latency on a single file. The optional background IOPS feature
attempts to mimic real-world conditions by running read and
description: |-
FilesystemPerformance benchmarks sequential write latency on a single file.
The optional background IOPS feature attempts to mimic real-world conditions by running read and
write workloads prior to and during benchmark execution.
properties:
backgroundIOPSWarmupSeconds:
@@ -1165,34 +1169,33 @@ spec:
write workloads prior to starting the benchmarks.
type: integer
backgroundReadIOPS:
description: The target read IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background read jobs.
description: |-
The target read IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background read jobs.
type: integer
backgroundReadIOPSJobs:
description: Number of threads to use for background read
IOPS. This should be set high enough to reach the target
specified in BackgrounReadIOPS.
description: |-
Number of threads to use for background read IOPS. This should be set high enough to reach
the target specified in BackgrounReadIOPS.
type: integer
backgroundWriteIOPS:
description: The target write IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background write jobs.
description: |-
The target write IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background write jobs.
type: integer
backgroundWriteIOPSJobs:
description: 'Number of threads to use for background write
IOPS. This should be set high enough to reach the target
specified in BackgroundWriteIOPS. Example: If BackgroundWriteIOPS
is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at
least 2.'
description: |-
Number of threads to use for background write IOPS. This should be set high enough to reach
the target specified in BackgroundWriteIOPS.
Example: If BackgroundWriteIOPS is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at least 2.
type: integer
collectorName:
type: string
datasync:
description: Whether to call datasync on the file after
each write. Skipped if Sync is also true. Does not apply
to background IOPS task.
description: |-
Whether to call datasync on the file after each write. Skipped if Sync is also true. Does not
apply to background IOPS task.
type: boolean
directory:
description: The directory where the benchmark will create
@@ -1204,16 +1207,14 @@ spec:
exclude:
type: BoolString
fileSize:
description: The size of the file used in the benchmark.
The number of IO operations for the benchmark will be
FileSize / OperationSizeBytes. Accepts valid Kubernetes
resource units such as Mi.
description: |-
The size of the file used in the benchmark. The number of IO operations for the benchmark
will be FileSize / OperationSizeBytes. Accepts valid Kubernetes resource units such as Mi.
type: string
operationSize:
description: The size of each write operation performed
while benchmarking. This does not apply to the background
IOPS feature if enabled, since those must be fixed at
4096.
description: |-
The size of each write operation performed while benchmarking. This does not apply to the
background IOPS feature if enabled, since those must be fixed at 4096.
format: int64
type: integer
sync:
@@ -1261,9 +1262,9 @@ spec:
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.
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
@@ -1281,9 +1282,9 @@ spec:
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.
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
@@ -1301,9 +1302,9 @@ spec:
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.
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
@@ -1386,6 +1387,8 @@ spec:
type: object
outputDir:
type: string
timeout:
type: string
required:
- args
- command
+85 -85
View File
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: hostpreflights.troubleshoot.sh
spec:
group: troubleshoot.sh
@@ -21,14 +20,19 @@ spec:
description: HostPreflight is the Schema for the hostpreflights API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -1155,9 +1159,9 @@ spec:
- path
type: object
filesystemPerformance:
description: FilesystemPerformance benchmarks sequential write
latency on a single file. The optional background IOPS feature
attempts to mimic real-world conditions by running read and
description: |-
FilesystemPerformance benchmarks sequential write latency on a single file.
The optional background IOPS feature attempts to mimic real-world conditions by running read and
write workloads prior to and during benchmark execution.
properties:
backgroundIOPSWarmupSeconds:
@@ -1165,34 +1169,33 @@ spec:
write workloads prior to starting the benchmarks.
type: integer
backgroundReadIOPS:
description: The target read IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background read jobs.
description: |-
The target read IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background read jobs.
type: integer
backgroundReadIOPSJobs:
description: Number of threads to use for background read
IOPS. This should be set high enough to reach the target
specified in BackgrounReadIOPS.
description: |-
Number of threads to use for background read IOPS. This should be set high enough to reach
the target specified in BackgrounReadIOPS.
type: integer
backgroundWriteIOPS:
description: The target write IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background write jobs.
description: |-
The target write IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background write jobs.
type: integer
backgroundWriteIOPSJobs:
description: 'Number of threads to use for background write
IOPS. This should be set high enough to reach the target
specified in BackgroundWriteIOPS. Example: If BackgroundWriteIOPS
is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at
least 2.'
description: |-
Number of threads to use for background write IOPS. This should be set high enough to reach
the target specified in BackgroundWriteIOPS.
Example: If BackgroundWriteIOPS is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at least 2.
type: integer
collectorName:
type: string
datasync:
description: Whether to call datasync on the file after
each write. Skipped if Sync is also true. Does not apply
to background IOPS task.
description: |-
Whether to call datasync on the file after each write. Skipped if Sync is also true. Does not
apply to background IOPS task.
type: boolean
directory:
description: The directory where the benchmark will create
@@ -1204,16 +1207,14 @@ spec:
exclude:
type: BoolString
fileSize:
description: The size of the file used in the benchmark.
The number of IO operations for the benchmark will be
FileSize / OperationSizeBytes. Accepts valid Kubernetes
resource units such as Mi.
description: |-
The size of the file used in the benchmark. The number of IO operations for the benchmark
will be FileSize / OperationSizeBytes. Accepts valid Kubernetes resource units such as Mi.
type: string
operationSize:
description: The size of each write operation performed
while benchmarking. This does not apply to the background
IOPS feature if enabled, since those must be fixed at
4096.
description: |-
The size of each write operation performed while benchmarking. This does not apply to the
background IOPS feature if enabled, since those must be fixed at 4096.
format: int64
type: integer
sync:
@@ -1261,9 +1262,9 @@ spec:
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.
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
@@ -1281,9 +1282,9 @@ spec:
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.
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
@@ -1301,9 +1302,9 @@ spec:
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.
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
@@ -1386,6 +1387,8 @@ spec:
type: object
outputDir:
type: string
timeout:
type: string
required:
- args
- command
@@ -1602,44 +1605,43 @@ spec:
- path
type: object
filesystemPerformance:
description: RemoteFilesystemPerformance benchmarks sequential
write latency on a single file. The optional background IOPS
feature attempts to mimic real-world conditions by running
read and write workloads prior to and during benchmark execution.
description: |-
RemoteFilesystemPerformance benchmarks sequential write latency on a single file.
The optional background IOPS feature attempts to mimic real-world conditions by running read and
write workloads prior to and during benchmark execution.
properties:
backgroundIOPSWarmupSeconds:
description: How long to run the background IOPS read and
write workloads prior to starting the benchmarks.
type: integer
backgroundReadIOPS:
description: The target read IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background read jobs.
description: |-
The target read IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background read jobs.
type: integer
backgroundReadIOPSJobs:
description: Number of threads to use for background read
IOPS. This should be set high enough to reach the target
specified in BackgrounReadIOPS.
description: |-
Number of threads to use for background read IOPS. This should be set high enough to reach
the target specified in BackgrounReadIOPS.
type: integer
backgroundWriteIOPS:
description: The target write IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background write jobs.
description: |-
The target write IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background write jobs.
type: integer
backgroundWriteIOPSJobs:
description: 'Number of threads to use for background write
IOPS. This should be set high enough to reach the target
specified in BackgroundWriteIOPS. Example: If BackgroundWriteIOPS
is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at
least 2.'
description: |-
Number of threads to use for background write IOPS. This should be set high enough to reach
the target specified in BackgroundWriteIOPS.
Example: If BackgroundWriteIOPS is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at least 2.
type: integer
collectorName:
type: string
datasync:
description: Whether to call datasync on the file after
each write. Skipped if Sync is also true. Does not apply
to background IOPS task.
description: |-
Whether to call datasync on the file after each write. Skipped if Sync is also true. Does not
apply to background IOPS task.
type: boolean
directory:
description: The directory where the benchmark will create
@@ -1651,16 +1653,14 @@ spec:
exclude:
type: BoolString
fileSize:
description: The size of the file used in the benchmark.
The number of IO operations for the benchmark will be
FileSize / OperationSizeBytes. Accepts valid Kubernetes
resource units such as Mi.
description: |-
The size of the file used in the benchmark. The number of IO operations for the benchmark
will be FileSize / OperationSizeBytes. Accepts valid Kubernetes resource units such as Mi.
type: string
operationSize:
description: The size of each write operation performed
while benchmarking. This does not apply to the background
IOPS feature if enabled, since those must be fixed at
4096.
description: |-
The size of each write operation performed while benchmarking. This does not apply to the
background IOPS feature if enabled, since those must be fixed at 4096.
format: int64
type: integer
sync:
@@ -1701,9 +1701,9 @@ spec:
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.
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
@@ -1721,9 +1721,9 @@ spec:
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.
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
@@ -1741,9 +1741,9 @@ spec:
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.
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
File diff suppressed because it is too large Load Diff
+12 -8
View File
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: redactors.troubleshoot.sh
spec:
group: troubleshoot.sh
@@ -21,14 +20,19 @@ spec:
description: Redactor is the Schema for the redaction API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -3,8 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.11.2
creationTimestamp: null
controller-gen.kubebuilder.io/version: v0.14.0
name: remotecollectors.troubleshoot.sh
spec:
group: troubleshoot.sh
@@ -21,14 +20,19 @@ spec:
description: RemoteCollector is the Schema for the remote collectors API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
@@ -109,44 +113,43 @@ spec:
- path
type: object
filesystemPerformance:
description: RemoteFilesystemPerformance benchmarks sequential
write latency on a single file. The optional background IOPS
feature attempts to mimic real-world conditions by running
read and write workloads prior to and during benchmark execution.
description: |-
RemoteFilesystemPerformance benchmarks sequential write latency on a single file.
The optional background IOPS feature attempts to mimic real-world conditions by running read and
write workloads prior to and during benchmark execution.
properties:
backgroundIOPSWarmupSeconds:
description: How long to run the background IOPS read and
write workloads prior to starting the benchmarks.
type: integer
backgroundReadIOPS:
description: The target read IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background read jobs.
description: |-
The target read IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background read jobs.
type: integer
backgroundReadIOPSJobs:
description: Number of threads to use for background read
IOPS. This should be set high enough to reach the target
specified in BackgrounReadIOPS.
description: |-
Number of threads to use for background read IOPS. This should be set high enough to reach
the target specified in BackgrounReadIOPS.
type: integer
backgroundWriteIOPS:
description: The target write IOPS to run while benchmarking.
This is a limit and there is no guarantee it will be reached.
This is the total IOPS for all background write jobs.
description: |-
The target write IOPS to run while benchmarking. This is a limit and there is no guarantee
it will be reached. This is the total IOPS for all background write jobs.
type: integer
backgroundWriteIOPSJobs:
description: 'Number of threads to use for background write
IOPS. This should be set high enough to reach the target
specified in BackgroundWriteIOPS. Example: If BackgroundWriteIOPS
is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at
least 2.'
description: |-
Number of threads to use for background write IOPS. This should be set high enough to reach
the target specified in BackgroundWriteIOPS.
Example: If BackgroundWriteIOPS is 100 and write latency is 10ms then a single job would
barely be able to reach 100 IOPS so this should be at least 2.
type: integer
collectorName:
type: string
datasync:
description: Whether to call datasync on the file after
each write. Skipped if Sync is also true. Does not apply
to background IOPS task.
description: |-
Whether to call datasync on the file after each write. Skipped if Sync is also true. Does not
apply to background IOPS task.
type: boolean
directory:
description: The directory where the benchmark will create
@@ -158,16 +161,14 @@ spec:
exclude:
type: BoolString
fileSize:
description: The size of the file used in the benchmark.
The number of IO operations for the benchmark will be
FileSize / OperationSizeBytes. Accepts valid Kubernetes
resource units such as Mi.
description: |-
The size of the file used in the benchmark. The number of IO operations for the benchmark
will be FileSize / OperationSizeBytes. Accepts valid Kubernetes resource units such as Mi.
type: string
operationSize:
description: The size of each write operation performed
while benchmarking. This does not apply to the background
IOPS feature if enabled, since those must be fixed at
4096.
description: |-
The size of each write operation performed while benchmarking. This does not apply to the
background IOPS feature if enabled, since those must be fixed at 4096.
format: int64
type: integer
sync:
@@ -208,9 +209,9 @@ spec:
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.
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
@@ -228,9 +229,9 @@ spec:
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.
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
@@ -248,9 +249,9 @@ spec:
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.
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
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -42,7 +42,7 @@ An initially unintended benefit of using the Aggregation Layer is that any HostC
* [microk8s implementation](https://github.com/canonical/microk8s/blob/master/build-scripts/patches/0000-Kubelite-integration.patch) - bundles slightly modified binaries
* [k0s uses upstream binaries statically compiled](https://docs.k0sproject.io/v1.23.8+k0s.0/architecture/) - bundles statically compiled binaries that self extract and uses a process monitor to run them
2. Can you in fact push metadat like "Status" into an api-server or do we have to write directly to etcd?
2. Can you in fact push metadata like "Status" into an api-server or do we have to write directly to etcd?
* If we can't push to the api-server is just writing the information directly into etcd something we can do and have a reasonable expectation of compatibility?
+1 -1
View File
@@ -54,4 +54,4 @@ preflight [url] [flags]
* [preflight oci-fetch](preflight_oci-fetch.md) - Fetch a preflight from an OCI registry and print it to standard out
* [preflight version](preflight_version.md) - Print the current version and exit
###### Auto generated by spf13/cobra on 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+3 -2
View File
@@ -9,7 +9,8 @@ preflight oci-fetch [URI] [flags]
### Options
```
-h, --help help for oci-fetch
-h, --help help for oci-fetch
-v, --v Level number for the log level verbosity
```
### Options inherited from parent commands
@@ -33,4 +34,4 @@ preflight oci-fetch [URI] [flags]
* [preflight](preflight.md) - Run and retrieve preflight checks in a cluster
###### Auto generated by spf13/cobra on 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+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 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+3 -2
View File
@@ -27,6 +27,7 @@ support-bundle [urls...] [flags]
--cpuprofile string File path to write cpu profiling data
--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
--dry-run print support bundle spec without collecting anything
-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)
@@ -34,7 +35,7 @@ support-bundle [urls...] [flags]
--load-cluster-specs enable/disable loading additional troubleshoot specs found within the cluster. required when no specs are provided on the command line
--memprofile string File path to write memory profiling data
-n, --namespace string If present, the namespace scope for this CLI request
--no-uri When this flag is used, Troubleshoot does not attempt to retrieve the bundle referenced by the uri: field in the spec.`
--no-uri When this flag is used, Troubleshoot does not attempt to retrieve the spec referenced by the uri: field`
-o, --output string specify the output file path for the support bundle
--redact enable/disable default redactions (default true)
--redactors strings names of the additional redactors to use
@@ -55,4 +56,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 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+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 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+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 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+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 31-Aug-2023
###### Auto generated by spf13/cobra on 25-Jan-2024
+3
View File
@@ -75,6 +75,9 @@ spec:
- pass:
when: "== oke"
message: OKE is a supported distribution
- pass:
when: "== kind"
message: Kind is a supported distribution
- warn:
message: Unable to determine the distribution of Kubernetes
- nodeResources:
+28 -29
View File
@@ -1,6 +1,6 @@
module helm-template
go 1.20
go 1.22.0
// Always use the local version of troubleshoot so as to build using
// the latest version of the library. This will ensure the example
@@ -9,29 +9,28 @@ 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
helm.sh/helm/v3 v3.15.0
sigs.k8s.io/yaml v1.4.0
)
require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/BurntSushi/toml v1.3.2 // 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.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-logr/logr v1.4.1 // 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/go-openapi/swag v0.22.10 // 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/golang/protobuf v1.5.4 // 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/google/uuid v1.6.0 // 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
@@ -44,30 +43,30 @@ require (
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/spf13/cast v1.6.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
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.31.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // indirect
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.33.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.2 // indirect
k8s.io/apiextensions-apiserver v0.28.1 // indirect
k8s.io/apimachinery v0.28.2 // indirect
k8s.io/client-go v0.28.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/controller-runtime v0.16.2 // indirect
k8s.io/api v0.30.0 // indirect
k8s.io/apiextensions-apiserver v0.30.0 // indirect
k8s.io/apimachinery v0.30.0 // indirect
k8s.io/client-go v0.30.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/controller-runtime v0.18.2 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
)
+76 -63
View File
@@ -1,5 +1,5 @@
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/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=
@@ -14,39 +14,45 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.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/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI=
github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
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-openapi/swag v0.22.10 h1:4y86NVn7Z2yYd6pfS4Z+Nyh3aAUL3Nul+LMbhFKy0gA=
github.com/go-openapi/swag v0.22.10/go.mod h1:Cnn8BYtRlx6BNE3DPN86f/xkapGIcLWzh3CLEb4C1jI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
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/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
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/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
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/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/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=
@@ -61,6 +67,7 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
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/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
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=
@@ -80,20 +87,25 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/ginkgo/v2 v2.17.1 h1:V++EzdbhI4ZV4ev0UTIj0PzhzOcReJFyJaLjtSF55M8=
github.com/onsi/ginkgo/v2 v2.17.1/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
github.com/onsi/gomega v1.32.0 h1:JRYU78fJ1LPxlckP6Txi/EYqJvjtMrDC04/MM5XRHPk=
github.com/onsi/gomega v1.32.0/go.mod h1:a4x4gW6Pz2yK1MAmvluYme5lvYTn61afQ2ETw/8n4Lg=
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
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/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0=
github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
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=
@@ -103,7 +115,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/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=
@@ -119,23 +132,22 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
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.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
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.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4=
golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI=
golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8=
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=
@@ -148,38 +160,39 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
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.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
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/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-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.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
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/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
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.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
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=
@@ -193,27 +206,27 @@ 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.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
k8s.io/apiextensions-apiserver v0.28.1 h1:l2ThkBRjrWpw4f24uq0Da2HaEgqJZ7pcgiEUTKSmQZw=
k8s.io/apiextensions-apiserver v0.28.1/go.mod h1:sVvrI+P4vxh2YBBcm8n2ThjNyzU4BQGilCQ/JAY5kGs=
k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-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.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU=
sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU=
helm.sh/helm/v3 v3.15.0 h1:gcLxHeFp0Hfo7lYi6KIZ84ZyvlAnfFRSJ8lTL3zvG5U=
helm.sh/helm/v3 v3.15.0/go.mod h1:fvfoRcB8UKRUV5jrIfOTaN/pG1TPhuqSb56fjYdTKXg=
k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA=
k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE=
k8s.io/apiextensions-apiserver v0.30.0 h1:jcZFKMqnICJfRxTgnC4E+Hpcq8UEhT8B2lhBcQ+6uAs=
k8s.io/apiextensions-apiserver v0.30.0/go.mod h1:N9ogQFGcrbWqAY9p2mUAL5mGxsLqwgtUce127VtRX5Y=
k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA=
k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ=
k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
sigs.k8s.io/controller-runtime v0.18.2 h1:RqVW6Kpeaji67CY5nPEfRz6ZfFMk0lWQlNrLqlNpx+Q=
sigs.k8s.io/controller-runtime v0.18.2/go.mod h1:tuAt1+wbVsXIT8lPtk5RURxqAnq7xkpv2Mhttslg7Hw=
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=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
+114 -107
View File
@@ -1,61 +1,63 @@
module github.com/replicatedhq/troubleshoot
go 1.20
go 1.22.0
require (
github.com/ahmetalpbalkan/go-cursor v0.0.0-20131010032410-8136607ea412
github.com/apparentlymart/go-cidr v1.1.0
github.com/blang/semver/v4 v4.0.0
github.com/containers/image/v5 v5.25.0
github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2
github.com/fatih/color v1.15.0
github.com/go-logr/logr v1.2.4
github.com/containers/image/v5 v5.30.1
github.com/distribution/distribution/v3 v3.0.0-alpha.1
github.com/fatih/color v1.17.0
github.com/go-logr/logr v1.4.1
github.com/go-redis/redis/v7 v7.4.1
github.com/go-sql-driver/mysql v1.7.1
github.com/go-sql-driver/mysql v1.8.1
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.1
github.com/gorilla/handlers v1.5.1
github.com/hashicorp/go-getter v1.7.2
github.com/google/uuid v1.6.0
github.com/gorilla/handlers v1.5.2
github.com/hashicorp/go-getter v1.7.4
github.com/hashicorp/go-multierror v1.1.1
github.com/jackc/pgx/v5 v5.4.3
github.com/jackc/pgx/v5 v5.5.5
github.com/longhorn/go-iscsi-helper v0.0.0-20210330030558-49a327fb024e
github.com/manifoldco/promptui v0.9.0
github.com/mattn/go-isatty v0.0.19
github.com/mattn/go-isatty v0.0.20
github.com/mholt/archiver/v3 v3.5.1
github.com/microsoft/go-mssqldb v1.6.0
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b
github.com/microsoft/go-mssqldb v1.7.1
github.com/opencontainers/image-spec v1.1.0
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.9
github.com/spf13/cobra v1.7.0
github.com/shirou/gopsutil/v3 v3.24.4
github.com/spf13/cobra v1.8.0
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.17.0
github.com/stretchr/testify v1.8.4
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
github.com/tj/go-spin v1.1.0
github.com/vmware-tanzu/velero v1.12.0
go.opentelemetry.io/otel v1.19.0
go.opentelemetry.io/otel/sdk v1.19.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/mod v0.12.0
golang.org/x/sync v0.4.0
github.com/vmware-tanzu/velero v1.13.2
go.opentelemetry.io/otel v1.26.0
go.opentelemetry.io/otel/sdk v1.26.0
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
golang.org/x/mod v0.17.0
golang.org/x/sync v0.7.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.28.2
k8s.io/apiextensions-apiserver v0.28.1
k8s.io/apimachinery v0.28.2
k8s.io/apiserver v0.28.1
k8s.io/cli-runtime v0.28.2
k8s.io/client-go v0.28.2
k8s.io/klog/v2 v2.100.1
oras.land/oras-go v1.2.3
sigs.k8s.io/controller-runtime v0.16.2
k8s.io/api v0.30.1
k8s.io/apiextensions-apiserver v0.30.1
k8s.io/apimachinery v0.30.1
k8s.io/apiserver v0.30.1
k8s.io/cli-runtime v0.30.1
k8s.io/client-go v0.30.1
k8s.io/klog/v2 v2.120.1
oras.land/oras-go v1.2.5
sigs.k8s.io/controller-runtime v0.18.2
sigs.k8s.io/e2e-framework v0.3.0
)
require (
cloud.google.com/go/compute/metadata v0.2.3 // indirect
dario.cat/mergo v1.0.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
github.com/MakeNowJust/heredoc v1.0.0 // indirect
github.com/Masterminds/goutils v1.1.1 // indirect
@@ -64,19 +66,24 @@ require (
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/containerd/cgroups/v3 v3.0.2 // indirect
github.com/containerd/errdefs v0.1.0 // indirect
github.com/containerd/log v0.1.0 // 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/cpuguy83/go-md2man/v2 v2.0.3 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.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-gorp/gorp/v3 v3.1.0 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-containerregistry v0.19.0 // indirect
github.com/google/s2a-go v0.1.7 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
github.com/gorilla/websocket v1.5.0 // 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
@@ -86,84 +93,86 @@ require (
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/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/moby/sys/user v0.1.0 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/rubenv/sql-migrate v1.3.1 // indirect
github.com/rubenv/sql-migrate v1.5.2 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sagikazarmark/locafero v0.3.0 // indirect
github.com/sagikazarmark/locafero v0.4.0 // indirect
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/sylabs/sif/v2 v2.11.1 // indirect
github.com/sylabs/sif/v2 v2.15.1 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // 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/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect
go.opentelemetry.io/otel/metric v1.19.0 // indirect
go.opentelemetry.io/otel/trace v1.19.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/tools v0.13.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 // indirect
k8s.io/component-base v0.28.1 // indirect
k8s.io/kubectl v0.28.1 // indirect
golang.org/x/tools v0.18.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect
k8s.io/component-base v0.30.1 // indirect
k8s.io/kubectl v0.30.0 // indirect
)
require (
cloud.google.com/go v0.110.7 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/iam v1.1.1 // indirect
cloud.google.com/go/storage v1.30.1 // indirect
cloud.google.com/go v0.110.10 // indirect
cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/iam v1.1.5 // indirect
cloud.google.com/go/storage v1.35.1 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.11.4 // indirect
github.com/Microsoft/hcsshim v0.12.0-rc.3 // indirect
github.com/andybalholm/brotli v1.0.1 // indirect
github.com/aws/aws-sdk-go v1.44.253 // indirect
github.com/aws/aws-sdk-go v1.48.10 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d // indirect
github.com/c9s/goprocinfo v0.0.0-20170724085704-0010a05ce49f // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/containerd v1.7.11 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containerd/containerd v1.7.13 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
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/containers/ocicrypt v1.1.9 // indirect
github.com/containers/storage v1.53.0 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/docker/cli v23.0.3+incompatible // indirect
github.com/docker/docker v23.0.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/cli v25.0.3+incompatible // indirect
github.com/docker/docker v25.0.5+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.1 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-metrics v0.0.1 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/go-errors/errors v1.4.2 // indirect
github.com/go-ole/go-ole v1.2.6 // 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/go-openapi/swag v0.22.10 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/go-cmp v0.6.0 // 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.12.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
@@ -175,83 +184,81 @@ require (
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.17.0 // indirect
github.com/klauspost/pgzip v1.2.6-0.20220930104621-17e8dac29df8 // indirect
github.com/klauspost/compress v1.17.7 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
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.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
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect
github.com/moby/sys/mountinfo v0.7.1 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect
github.com/nwaples/rardecode v1.1.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
github.com/opencontainers/runtime-spec v1.2.0 // 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.1.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pierrec/lz4/v4 v4.1.2 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/prometheus/client_golang v1.18.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.45.0 // indirect
github.com/prometheus/procfs v0.12.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/spf13/afero v1.10.0 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/tklauser/go-sysconf v0.3.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/vbatts/tar-split v0.11.5 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xlab/treeprint v1.2.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.opencensus.io v0.24.0 // indirect
go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/net v0.17.0
golang.org/x/oauth2 v0.12.0 // indirect
golang.org/x/sys v0.15.0 // indirect
golang.org/x/term v0.15.0 // indirect
golang.org/x/text v0.14.0
golang.org/x/time v0.3.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0
golang.org/x/oauth2 v0.18.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/term v0.20.0 // indirect
golang.org/x/text v0.15.0
golang.org/x/time v0.5.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/api v0.143.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb // indirect
google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect
google.golang.org/api v0.153.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 // indirect
google.golang.org/grpc v1.59.0 // indirect
google.golang.org/protobuf v1.33.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
helm.sh/helm/v3 v3.12.3
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
k8s.io/metrics v0.28.2
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2
helm.sh/helm/v3 v3.15.0
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/kubelet v0.30.1
k8s.io/metrics v0.30.1
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
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.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
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.4.0
)
replace (
+328 -468
View File
File diff suppressed because it is too large Load Diff
+13 -1
View File
@@ -41,9 +41,13 @@ func FileDir() string {
// Generates a temporary filename
func TempFilename(prefix string) string {
return filepath.Join(os.TempDir(), generateTempName(prefix))
}
func generateTempName(prefix string) string {
randBytes := make([]byte, 16)
rand.Read(randBytes)
return filepath.Join(os.TempDir(), fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(randBytes)))
return fmt.Sprintf("%s_%s", prefix, hex.EncodeToString(randBytes))
}
func CreateTestFile(t *testing.T, path string) {
@@ -78,3 +82,11 @@ func AsJSON(t *testing.T, v interface{}) string {
return string(b)
}
}
func ServeFromFilePath(t *testing.T, data string) string {
t.Helper()
path := filepath.Join(t.TempDir(), generateTempName("testfile"))
CreateTestFileWithData(t, path, data)
return path
}
+90 -7
View File
@@ -1,14 +1,22 @@
package util
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"net/url"
"os"
"os/user"
"strings"
"text/template"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)
const HOST_COLLECTORS_RUN_AS_ROOT_PROMPT = "Some host collectors need to be run as root.\nDo you want to exit and rerun the command using sudo?"
func HomeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
@@ -54,13 +62,9 @@ func EstimateNumberOfLines(text string) int {
}
// Append appends elements in src to target.
// We have this function because of how append()
// treats nil slices the same as empty slices.
// An empty array in YAML like below is not the
// same as when the array is not specified.
//
// spec:
// collectors: []
// We have this function because of how the
// builtin append() function works. It treats
// target nil slices the same as empty slices.
func Append[T any](target []T, src []T) []T {
// Do nothing only if src is nil
if src == nil {
@@ -86,3 +90,82 @@ func IsInCluster() bool {
return true
}
// RenderTemplate renders a template and returns the result as a string
func RenderTemplate(tpl string, data interface{}) (string, error) {
// Create a new template and parse the letter into it
t, err := template.New("data").Parse(tpl)
if err != nil {
return "", err
}
// Create a new buffer
buf := new(bytes.Buffer)
// Execute the template and write the bytes to the buffer
err = t.Execute(buf, data)
if err != nil {
return "", err
}
// Return the string representation of the buffer
return buf.String(), nil
}
func IsRunningAsRoot() bool {
currentUser, err := user.Current()
if err != nil {
return false
}
// Check if the user ID is 0 (root's UID)
return currentUser.Uid == "0"
}
func PromptYesNo(question string) bool {
reader := bufio.NewReader(os.Stdin)
for {
fmt.Printf("%s (yes/no): ", question)
response, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading response:", err)
continue
}
response = strings.TrimSpace(response)
response = strings.ToLower(response)
if response == "yes" || response == "y" {
return true
} else if response == "no" || response == "n" {
return false
} else {
fmt.Println("Please type 'yes' or 'no'.")
}
}
}
func Dedup[T any](objs []T) []T {
seen := make(map[string]bool)
out := []T{}
if len(objs) == 0 {
return objs
}
for _, o := range objs {
data, err := json.Marshal(o)
if err != nil {
out = append(out, o)
continue
}
key := string(data)
if _, ok := seen[key]; !ok {
out = append(out, o)
seen[key] = true
}
}
return out
}
+56
View File
@@ -246,3 +246,59 @@ func TestAppend(t *testing.T) {
})
}
}
func TestRenderTemplate(t *testing.T) {
tests := []struct {
name string
tpl string
data interface{}
want string
wantErr bool
}{
{
name: "empty template and data",
tpl: "",
data: nil,
want: "",
wantErr: false,
},
{
name: "empty template with data",
tpl: "",
data: map[string]string{"Name": "World"},
want: "",
wantErr: false,
},
{
name: "empty data with template with no keys",
tpl: "Hello, World!",
data: nil,
want: "Hello, World!",
wantErr: false,
},
{
name: "simple template",
tpl: "Hello, {{ .Name }}!",
data: map[string]string{"Name": "World"},
want: "Hello, World!",
wantErr: false,
},
{
name: "template with missing key",
tpl: "Hello, {{ .Name }}!",
data: map[string]string{"Name2": "World"},
want: "Hello, <no value>!",
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := RenderTemplate(tt.tpl, tt.data)
if (err != nil) != tt.wantErr {
t.Errorf("RenderTemplate() error = %v, wantErr %v", err, tt.wantErr)
return
}
assert.Equal(t, tt.want, got, "RenderTemplate() = %v, want %v", got, tt.want)
})
}
}
+4
View File
@@ -246,6 +246,10 @@ func getAnalyzer(analyzer *troubleshootv1beta2.Analyze) Analyzer {
return &AnalyzeCertificates{analyzer: analyzer.Certificates}
case analyzer.Goldpinger != nil:
return &AnalyzeGoldpinger{analyzer: analyzer.Goldpinger}
case analyzer.Event != nil:
return &AnalyzeEvent{analyzer: analyzer.Event}
case analyzer.NodeMetrics != nil:
return &AnalyzeNodeMetrics{analyzer: analyzer.NodeMetrics}
default:
return nil
}
+11 -1
View File
@@ -42,7 +42,7 @@ func analyzeClusterVersion(analyzer *troubleshootv1beta2.ClusterVersion, getColl
return nil, errors.Wrap(err, "failed to parse cluster_version.json")
}
k8sVersion, err := semver.Make(strings.TrimLeft(collectorClusterVersion.String, "v"))
k8sVersion, err := parseK8sVersionString(collectorClusterVersion.String)
if err != nil {
return nil, errors.Wrap(err, "failed to parse semver from cluster_version.json")
}
@@ -58,6 +58,16 @@ func title(checkName string) string {
return checkName
}
func parseK8sVersionString(version string) (semver.Version, error) {
// Workaround for https://github.com/aws/containers-roadmap/issues/1404
// for EKS, replace pre-release gitVersion string with the release version
if strings.Contains(version, "-eks-") {
version = strings.Split(version, "-")[0]
}
return semver.Make(strings.TrimLeft(version, "v"))
}
func analyzeClusterVersionResult(k8sVersion semver.Version, outcomes []*troubleshootv1beta2.Outcome, checkName string) (*AnalyzeResult, error) {
for _, outcome := range outcomes {
when := ""
+39
View File
@@ -6,6 +6,7 @@ import (
"github.com/blang/semver/v4"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
)
func Test_analyzeClusterVersionResult(t *testing.T) {
@@ -103,3 +104,41 @@ func Test_analyzeClusterVersionResult(t *testing.T) {
})
}
}
func Test_parseVersionString(t *testing.T) {
tests := []struct {
name string
rawVersion string
want semver.Version
wantErr bool
}{
{
name: "valid version",
rawVersion: "1.17.0",
want: semver.MustParse("1.17.0"),
},
{
name: "valid version with v prefix",
rawVersion: "v1.17.0",
want: semver.MustParse("1.17.0"),
},
{
name: "invalid version",
rawVersion: "v1.17",
want: semver.Version{},
wantErr: true,
},
{
name: "EKS version",
rawVersion: "v1.25.16-eks-8cb36c9",
want: semver.MustParse("1.25.16"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := parseK8sVersionString(tt.rawVersion)
assert.Equal(t, tt.wantErr, err != nil, "parseVersionString() error = %v, wantErr %v", err, tt.wantErr)
assert.Equal(t, tt.want, got, "parseVersionString() = %v, want %v", got, tt.want)
})
}
}
+34
View File
@@ -0,0 +1,34 @@
package analyzer
import "fmt"
type ComparisonOperator int
const (
Unknown ComparisonOperator = iota
Equal
NotEqual
GreaterThan
GreaterThanOrEqual
LessThan
LessThanOrEqual
)
func ParseComparisonOperator(s string) (ComparisonOperator, error) {
switch s {
case "=", "==", "===":
return Equal, nil
case "!=", "!==":
return NotEqual, nil
case "<":
return LessThan, nil
case ">":
return GreaterThan, nil
case "<=":
return LessThanOrEqual, nil
case ">=":
return GreaterThanOrEqual, nil
}
return Unknown, fmt.Errorf("unknown operator: %s", s)
}
+79
View File
@@ -0,0 +1,79 @@
package analyzer
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseComparisonOperator(t *testing.T) {
tests := []struct {
name string
input string
want ComparisonOperator
wantErr bool
}{
{
name: "equal",
input: "=",
want: Equal,
},
{
name: "equal",
input: "==",
want: Equal,
},
{
name: "equal",
input: "===",
want: Equal,
},
{
name: "not equal",
input: "!=",
want: NotEqual,
},
{
name: "not equal",
input: "!==",
want: NotEqual,
},
{
name: "less than",
input: "<",
want: LessThan,
},
{
name: "greater than",
input: ">",
want: GreaterThan,
},
{
name: "less than or equal",
input: "<=",
want: LessThanOrEqual,
},
{
name: "greater than or equal",
input: ">=",
want: GreaterThanOrEqual,
},
{
name: "invalid operator 1",
input: "",
wantErr: true,
},
{
name: "invalid operator 2",
input: "gibberish",
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := ParseComparisonOperator(tt.input)
assert.Equal(t, tt.want, got, "ParseOperator() = %v, want %v", got, tt.want)
assert.Equalf(t, tt.wantErr, err != nil, "ParseOperator() error = %v, wantErr %v", err, tt.wantErr)
})
}
}
+65 -29
View File
@@ -13,40 +13,46 @@ import (
)
type providers struct {
microk8s bool
dockerDesktop bool
eks bool
gke bool
digitalOcean bool
openShift bool
tanzu bool
kurl bool
aks bool
ibm bool
minikube bool
rke2 bool
k3s bool
oke bool
microk8s bool
dockerDesktop bool
eks bool
gke bool
digitalOcean bool
openShift bool
tanzu bool
kurl bool
aks bool
ibm bool
minikube bool
rke2 bool
k3s bool
oke bool
kind bool
k0s bool
embeddedCluster bool
}
type Provider int
const (
unknown Provider = iota
microk8s Provider = iota
dockerDesktop Provider = iota
eks Provider = iota
gke Provider = iota
digitalOcean Provider = iota
openShift Provider = iota
tanzu Provider = iota
kurl Provider = iota
aks Provider = iota
ibm Provider = iota
minikube Provider = iota
rke2 Provider = iota
k3s Provider = iota
oke Provider = iota
unknown Provider = iota
microk8s Provider = iota
dockerDesktop Provider = iota
eks Provider = iota
gke Provider = iota
digitalOcean Provider = iota
openShift Provider = iota
tanzu Provider = iota
kurl Provider = iota
aks Provider = iota
ibm Provider = iota
minikube Provider = iota
rke2 Provider = iota
k3s Provider = iota
oke Provider = iota
kind Provider = iota
k0s Provider = iota
embeddedCluster Provider = iota
)
type AnalyzeDistribution struct {
@@ -132,6 +138,15 @@ func ParseNodesForProviders(nodes []corev1.Node) (providers, string) {
foundProviders.oke = true
stringProvider = "oke"
}
if k == "node.k0sproject.io/role" {
foundProviders.k0s = true
stringProvider = "k0s"
}
if k == "kots.io/embedded-cluster-role" {
foundProviders.embeddedCluster = true
stringProvider = "embedded-cluster"
}
}
for k := range node.ObjectMeta.Annotations {
@@ -162,6 +177,10 @@ func ParseNodesForProviders(nodes []corev1.Node) (providers, string) {
foundProviders.ibm = true
stringProvider = "ibm"
}
if strings.HasPrefix(node.Spec.ProviderID, "kind:") {
foundProviders.kind = true
stringProvider = "kind"
}
}
if foundMaster {
@@ -172,6 +191,11 @@ func ParseNodesForProviders(nodes []corev1.Node) (providers, string) {
}
}
// If k0s and embedded-cluster are both found, prefer embedded-cluster
if foundProviders.k0s && foundProviders.embeddedCluster {
stringProvider = "embedded-cluster"
}
return foundProviders, stringProvider
}
@@ -335,6 +359,12 @@ func compareDistributionConditionalToActual(conditional string, actual providers
isMatch = actual.k3s
case oke:
isMatch = actual.oke
case kind:
isMatch = actual.kind
case k0s:
isMatch = actual.k0s
case embeddedCluster:
isMatch = actual.embeddedCluster
}
switch parts[0] {
@@ -377,6 +407,12 @@ func mustNormalizeDistributionName(raw string) Provider {
return k3s
case "oke":
return oke
case "kind":
return kind
case "k0s":
return k0s
case "embeddedcluster":
return embeddedCluster
}
return unknown
+131
View File
@@ -5,6 +5,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func Test_compareDistributionConditionalToActual(t *testing.T) {
@@ -39,6 +41,30 @@ func Test_compareDistributionConditionalToActual(t *testing.T) {
},
expected: true,
},
{
name: "== kind when kind is found",
conditional: "== kind",
input: providers{
kind: true,
},
expected: true,
},
{
name: "== k0s when k0s is found",
conditional: "== k0s",
input: providers{
k0s: true,
},
expected: true,
},
{
name: "== embedded-cluster when embedded-cluster is found",
conditional: "== embedded-cluster",
input: providers{
embeddedCluster: true,
},
expected: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
@@ -73,6 +99,66 @@ func Test_mustNormalizeDistributionName(t *testing.T) {
raw: "Docker-Desktop",
expected: dockerDesktop,
},
{
raw: "embedded-cluster",
expected: embeddedCluster,
},
{
raw: "k0s",
expected: k0s,
},
{
raw: "kind",
expected: kind,
},
{
raw: "k3s",
expected: k3s,
},
{
raw: "ibm",
expected: ibm,
},
{
raw: "ibmcloud",
expected: ibm,
},
{
raw: "ibm cloud",
expected: ibm,
},
{
raw: "gke",
expected: gke,
},
{
raw: "aks",
expected: aks,
},
{
raw: "eks",
expected: eks,
},
{
raw: "oke",
expected: oke,
},
{
raw: "rke2",
expected: rke2,
},
{
raw: "dockerdesktop",
expected: dockerDesktop,
},
{
raw: "docker desktop",
expected: dockerDesktop,
},
{
raw: "docker-desktop",
expected: dockerDesktop,
},
}
for _, test := range tests {
@@ -83,3 +169,48 @@ func Test_mustNormalizeDistributionName(t *testing.T) {
})
}
}
func TestParseNodesForProviders(t *testing.T) {
tests := []struct {
name string
nodes []corev1.Node
wantProviders providers
wantProviderString string
}{
{
name: "embedded-cluster",
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "embedded-cluster",
Labels: map[string]string{
"beta.kubernetes.io/arch": "amd64",
"beta.kubernetes.io/os": "linux",
"kots.io/embedded-cluster-role": "total-1",
"kots.io/embedded-cluster-role-0": "management",
"kubernetes.io/arch": "amd64",
"kubernetes.io/hostname": "evans-vm1",
"kubernetes.io/os": "linux",
"management": "true",
"node-role.kubernetes.io/control-plane": "true",
"node.k0sproject.io/role": "control-plane",
},
},
},
},
wantProviders: providers{embeddedCluster: true, k0s: true},
wantProviderString: "embedded-cluster",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
providers, stringProvider := ParseNodesForProviders(tt.nodes)
assert.Equalf(t, tt.wantProviders, providers,
"ParseNodesForProviders() gotProviders = %v, providers %v", providers, tt.wantProviders,
)
assert.Equalf(t, tt.wantProviderString, stringProvider,
"ParseNodesForProviders() gotStringProvider = %v, stringProvider %v", stringProvider, tt.wantProviderString,
)
})
}
}
+218
View File
@@ -0,0 +1,218 @@
package analyzer
import (
"bytes"
"encoding/json"
"fmt"
"path"
"regexp"
"strconv"
"strings"
"text/template"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/constants"
corev1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
)
type AnalyzeEvent struct {
analyzer *troubleshootv1beta2.EventAnalyze
}
type eventFilter struct {
kind string
reason string
msgRegex string
}
func (a *AnalyzeEvent) Title() string {
if a.analyzer.CheckName != "" {
return a.analyzer.CheckName
}
if a.analyzer.CollectorName != "" {
return a.analyzer.CollectorName
}
return "Event"
}
func (a *AnalyzeEvent) IsExcluded() (bool, error) {
return isExcluded(a.analyzer.Exclude)
}
func (a *AnalyzeEvent) Analyze(getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
// required check
if a.analyzer.Reason == "" {
return nil, errors.New("reason is required")
}
// read collected events based on namespace
namespace := getNamespace(a.analyzer.Namespace)
fullPath := path.Join(constants.CLUSTER_RESOURCES_DIR, constants.CLUSTER_RESOURCES_EVENTS, namespace)
fullPath = fmt.Sprintf("%s.json", fullPath)
fileContent, err := getFile(fullPath)
if err != nil {
return nil, errors.Wrapf(err, "failed to read collected events for namespace: %s", namespace)
}
events, err := convertToEventList(fileContent)
if err != nil {
return nil, errors.Wrap(err, "failed to read collected events")
}
// filter if there's single event matched with the given criteria
// match: Reason && Kind (optional) && MessageRegex (optional)
// e.g. Reason: Unhealthy. Kind: Pod. Message: Readiness probe failed:...
event := getEvent(events, eventFilter{
kind: a.analyzer.Kind,
reason: a.analyzer.Reason,
msgRegex: a.analyzer.RegexPattern,
})
return analyzeEventResult(event, a.analyzer.Outcomes, a.Title())
}
func getNamespace(namespace string) string {
if namespace == "" {
return corev1.NamespaceDefault
}
return namespace
}
func convertToEventList(data []byte) (*corev1.EventList, error) {
var eventList corev1.EventList
err := json.Unmarshal(data, &eventList)
if err != nil {
return nil, fmt.Errorf("failed to convert []byte to corev1.EventList: %w", err)
}
return &eventList, nil
}
func getEvent(events *corev1.EventList, filter eventFilter) *corev1.Event {
var (
re *regexp.Regexp
errParseRegex error
)
if filter.msgRegex != "" {
re, errParseRegex = regexp.Compile(filter.msgRegex)
if errParseRegex != nil {
klog.V(2).Infof("failed to read message regex: %v", errParseRegex)
return nil
}
}
for _, event := range events.Items {
if !matchReason(event.Reason, filter.reason) {
continue
}
if !matchKind(event.InvolvedObject.Kind, filter.kind) {
continue
}
if re == nil || re.MatchString(event.Message) {
klog.V(2).Infof("event matched: %v for reason: %s kind: %s messageRegex: %s ", event, filter.reason, filter.kind, filter.msgRegex)
return &event
}
}
return nil
}
func matchReason(actual, expected string) bool {
// not possible to have empty reason
if expected == "" {
return false
}
return strings.EqualFold(actual, expected)
}
func matchKind(actual, expected string) bool {
// kind is optional
if expected == "" {
return true
}
return strings.EqualFold(actual, expected)
}
func analyzeEventResult(event *corev1.Event, outcomes []*troubleshootv1beta2.Outcome, checkName string) ([]*AnalyzeResult, error) {
results := []*AnalyzeResult{}
// for now, only support single outcome
// we will return when there's a matched event
willReturn := event != nil
result := &AnalyzeResult{
Title: checkName,
IconKey: "kubernetes_event",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/kubernetes.svg?w=16&h=16",
}
for _, o := range outcomes {
if o.Fail != nil {
toReturn, err := strconv.ParseBool(o.Fail.When)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse when condition: %s", o.Fail.When)
}
if toReturn == willReturn {
result.IsFail = true
result.Message = decorateMessage(o.Fail.Message, event)
result.URI = o.Fail.URI
break
}
}
if o.Warn != nil {
toReturn, err := strconv.ParseBool(o.Warn.When)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse when condition: %s", o.Warn.When)
}
if toReturn == willReturn {
result.IsWarn = true
result.Message = decorateMessage(o.Warn.Message, event)
result.URI = o.Warn.URI
break
}
}
if o.Pass != nil {
toReturn, err := strconv.ParseBool(o.Pass.When)
if err != nil {
return nil, errors.Wrapf(err, "failed to parse when condition: %s", o.Pass.When)
}
if toReturn == willReturn {
result.IsPass = true
result.Message = decorateMessage(o.Pass.Message, event)
result.URI = o.Pass.URI
break
}
}
}
results = append(results, result)
return results, nil
}
func decorateMessage(message string, event *corev1.Event) string {
if event == nil {
return message
}
out := fmt.Sprintf("Event matched. Reason: %s Name: %s Message: %s", event.Reason, event.InvolvedObject.Name, event.Message)
tmpl := template.New("event")
msgTmpl, err := tmpl.Parse(message)
if err != nil {
klog.V(2).Infof("failed to parse message template: %v", err)
return out
}
var m bytes.Buffer
err = msgTmpl.Execute(&m, event)
if err != nil {
klog.V(2).Infof("failed to render message template: %v", err)
return out
}
return strings.TrimSpace(m.String())
}
+310
View File
@@ -0,0 +1,310 @@
package analyzer
import (
"testing"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
)
func TestAnalyzeEvent(t *testing.T) {
tests := []struct {
name string
analyzer troubleshootv1beta2.EventAnalyze
expectResult []AnalyzeResult
files map[string][]byte
err error
}{
{
name: "reason is required",
analyzer: troubleshootv1beta2.EventAnalyze{
CollectorName: "event-collector-0",
Kind: "Pod",
Namespace: "default",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "true",
Message: "test",
},
},
},
},
err: errors.New("reason is required"),
files: map[string][]byte{
"cluster-resources/events/default.json": []byte(`
{
"kind": "EventList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "722"
},
"items": [
{
"kind": "Event",
"apiVersion": "v1",
"metadata": {
"name": "nginx-rc",
"namespace": "default",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"involvedObject": {
"kind": "Pod",
"name": "nginx-rc-12345",
"namespace": "default"
},
"reason": "OOMKilled",
"message": "The container was killed due to an out-of-memory condition.",
"type": "Warning"
}
]
}
`),
},
},
{
name: "fail when OOMKilled event is present",
analyzer: troubleshootv1beta2.EventAnalyze{
CollectorName: "event-collector-1",
Kind: "Pod",
Namespace: "default",
Reason: "OOMKilled",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "true",
Message: "Detect OOMKilled event with {{ .InvolvedObject.Kind }}-{{ .InvolvedObject.Name }} with message {{ .Message }}",
},
Pass: &troubleshootv1beta2.SingleOutcome{
When: "false",
Message: "No OOMKilled event detected",
},
},
},
},
expectResult: []AnalyzeResult{
{
Title: "event-collector-1",
IconKey: "kubernetes_event",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/kubernetes.svg?w=16&h=16",
IsFail: true,
IsWarn: false,
IsPass: false,
Message: "Detect OOMKilled event with Pod-nginx-rc-12345 with message The container was killed due to an out-of-memory condition.",
},
},
files: map[string][]byte{
"cluster-resources/events/default.json": []byte(`
{
"kind": "EventList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "722"
},
"items": [
{
"kind": "Event",
"apiVersion": "v1",
"metadata": {
"name": "nginx-rc",
"namespace": "default",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"involvedObject": {
"kind": "Pod",
"name": "nginx-rc-12345",
"namespace": "default"
},
"reason": "OOMKilled",
"message": "The container was killed due to an out-of-memory condition.",
"type": "Warning"
}
]
}
`),
},
},
{
name: "pass when no FailedMount event is present",
analyzer: troubleshootv1beta2.EventAnalyze{
CollectorName: "event-collector-2",
Kind: "Pod",
Namespace: "default",
Reason: "FailedMount",
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
When: "false",
Message: "No FailedMount event detected",
},
},
},
},
expectResult: []AnalyzeResult{
{
Title: "event-collector-2",
IconKey: "kubernetes_event",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/kubernetes.svg?w=16&h=16",
IsFail: false,
IsWarn: false,
IsPass: true,
Message: "No FailedMount event detected",
},
},
files: map[string][]byte{
"cluster-resources/events/default.json": []byte(`
{
"kind": "EventList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "722"
},
"items": [
{
"kind": "Event",
"apiVersion": "v1",
"metadata": {
"name": "nginx-rc-1",
"namespace": "default",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"involvedObject": {
"kind": "Pod",
"name": "nginx-rc-12345",
"namespace": "default"
},
"reason": "Created",
"message": "Created container",
"type": "Normal"
},
{
"kind": "Event",
"apiVersion": "v1",
"metadata": {
"name": "nginx-rc-2",
"namespace": "default",
"creationTimestamp": "2022-01-01T00:00:00Z"
},
"involvedObject": {
"kind": "Pod",
"name": "nginx-rc-67890",
"namespace": "default"
},
"reason": "Started",
"message": "Started container",
"type": "Normal"
}
]
}
`),
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
req := require.New(t)
getFile := func(n string) ([]byte, error) {
if b, ok := test.files[n]; ok {
return b, nil
}
return nil, errors.New("file not found")
}
findFiles := func(n string, _ []string) (map[string][]byte, error) {
return nil, errors.New("method not implemented")
}
a := &AnalyzeEvent{
analyzer: &test.analyzer,
}
actual, err := a.Analyze(getFile, findFiles)
if test.err != nil {
req.EqualError(err, test.err.Error())
return
}
req.NoError(err)
unPointered := []AnalyzeResult{}
for _, v := range actual {
unPointered = append(unPointered, *v)
}
req.ElementsMatch(test.expectResult, unPointered)
})
}
}
func TestAnalyzeEventResult(t *testing.T) {
event := &corev1.Event{
InvolvedObject: corev1.ObjectReference{
Kind: "Pod",
Name: "foo-pod",
},
Reason: "Unhealthy",
Message: "foo-message",
Type: "Warning",
}
outcomes := []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "true",
Message: "No unhealthy pods allowed",
},
Pass: &troubleshootv1beta2.SingleOutcome{
When: "false",
Message: "No unhealthy pod detected",
},
},
}
checkName := "Test Event"
expectedResults := []*AnalyzeResult{
{
Title: "Test Event",
IconKey: "kubernetes_event",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/kubernetes.svg?w=16&h=16",
IsFail: true,
IsWarn: false,
IsPass: false,
Message: "No unhealthy pods allowed",
},
}
results, err := analyzeEventResult(event, outcomes, checkName)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if len(results) != len(expectedResults) {
t.Fatalf("unexpected number of results, got %d, want %d", len(results), len(expectedResults))
}
for i, result := range results {
expectedResult := expectedResults[i]
if result.Title != expectedResult.Title {
t.Errorf("unexpected title, got %s, want %s", result.Title, expectedResult.Title)
}
if result.IsFail != expectedResult.IsFail {
t.Errorf("unexpected IsFail value, got %v, want %v", result.IsFail, expectedResult.IsFail)
}
if result.IsWarn != expectedResult.IsWarn {
t.Errorf("unexpected IsWarn value, got %v, want %v", result.IsWarn, expectedResult.IsWarn)
}
if result.IsPass != expectedResult.IsPass {
t.Errorf("unexpected IsPass value, got %v, want %v", result.IsPass, expectedResult.IsPass)
}
if result.Message != expectedResult.Message {
t.Errorf("unexpected message, got %s, want %s", result.Message, expectedResult.Message)
}
}
}
@@ -0,0 +1,47 @@
{
"kind": "ConfigMapList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "4825753"
},
"items": [
{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"name": "kube-root-ca.crt",
"namespace": "kube-public",
"uid": "37a912b2-a666-480f-a1a8-05ab012432e4",
"resourceVersion": "332",
"creationTimestamp": "2023-05-29T23:33:07Z",
"annotations": {
"kubernetes.io/description": "Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters."
},
"managedFields": [
{
"manager": "kube-controller-manager",
"operation": "Update",
"apiVersion": "v1",
"time": "2023-05-29T23:33:07Z",
"fieldsType": "FieldsV1",
"fieldsV1": {
"f:data": {
".": {},
"f:ca.crt": {}
},
"f:metadata": {
"f:annotations": {
".": {},
"f:kubernetes.io/description": {}
}
}
}
}
]
},
"data": {
"ca.crt": "-----BEGIN CERTIFICATE-----\nMIIDBjCCAe6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p\na3ViZUNBMB4XDTIzMDUyODIzMzIzOVoXDTMzMDUyNjIzMzIzOVowFTETMBEGA1UE\nAxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOpU\nswd15tD+QCelgYlu5MRB260+Ke63gEDTkXIyAr+mR+TjW/v9TPPIP9iidvTUg+jq\nryrf1PwURVx3EUSZWtd9NpAEDT1ov/ggx16xxj2El7KLen0SXQutSF28zjCFXxYG\nMkPxXu+qYsn2mLJX5i1kaCZNffyToCJ0n2bxxx83rOS+fgz11JntAwcgC8V3Mtq6\nIv+2Xb9PSxPs38ef7r15j5KSTOrmWCR5texPFz/WU/YbZ3W42pj9T/EiuGwamfmI\ngevuwv7AxlfjKutp5UQEth5GhY6V4kJyVIUExN3ddEsTPLQD9zvdsP4DlkGpZmiR\n/Ip3rXY/ldxeeGZ0HUUCAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW\nMBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW\nBBS0XUXhCu/DOH8/0W5L0n4BOw9b6zANBgkqhkiG9w0BAQsFAAOCAQEAHrXOxKdy\n+DvPtvgfzzV3qqmIvTuuFyW0BdZdXV8yo1tZajkEO0B0HvLUyn8ljKgoK5YtCQcr\nzSj6QEewgP+JCBTsWCKzbOhMcDKw1pa6bSeLcQWwMxox+1Zcj7edMPlPcQ3SVLxZ\n6y7fD7BArTKRBKCr8Uwudwox5Vm0URWLRAvb+8jPv9BDuC/uMPJ4UrexL/Q2QQs8\nQkyWYeSk4mBCM3qAahQhYc0WSHbk+a/5iua/y+VUaa208CUbm5glBoAroHDk5eTN\nYstOSLUQAlzTdr4kCEVi+a3+NgmuvzYXWubAdy/PT860aFBJlmVNuDhy8V/bGpnS\nKxmG7B3yJmbmzg==\n-----END CERTIFICATE-----\n"
}
}
]
}
+18
View File
@@ -10,6 +10,7 @@ import (
"strconv"
"github.com/pkg/errors"
util "github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
iutils "github.com/replicatedhq/troubleshoot/pkg/interfaceutils"
"k8s.io/client-go/util/jsonpath"
@@ -54,6 +55,8 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
return nil, errors.Wrap(err, "failed to parse collected data as json")
}
originalActual := actual
if analyzer.Path != "" {
actual, err = iutils.GetAtPath(actual, analyzer.Path)
if err != nil {
@@ -112,6 +115,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
}
}
outcome.Fail.Message, err = util.RenderTemplate(outcome.Fail.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsFail = true
result.Message = outcome.Fail.Message
@@ -128,6 +136,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
}
}
outcome.Warn.Message, err = util.RenderTemplate(outcome.Warn.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsWarn = true
result.Message = outcome.Warn.Message
@@ -144,6 +157,11 @@ func (a *AnalyzeJsonCompare) analyzeJsonCompare(analyzer *troubleshootv1beta2.Js
}
}
outcome.Pass.Message, err = util.RenderTemplate(outcome.Pass.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsPass = true
result.Message = outcome.Pass.Message
+42
View File
@@ -756,6 +756,48 @@ func Test_jsonCompare(t *testing.T) {
]
}`),
},
{
name: "basic comparison with outcome message templated",
analyzer: troubleshootv1beta2.JsonCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
When: "true",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .morestuff.status }}, Info: {{ .morestuff.info }}",
When: "false",
},
},
},
CollectorName: "json-compare",
FileName: "json-compare.json",
Path: "morestuff.status",
Value: `"ready"`,
},
expectResult: AnalyzeResult{
IsPass: false,
IsWarn: false,
IsFail: true,
Title: "json-compare",
Message: "Status: notready, Info: morestuff is not ready",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`{
"stuff": {
"status": "ready",
"info": "this stuff is ready"
},
"morestuff": {
"status": "notready",
"info": "morestuff is not ready"
}
}`),
},
}
for _, test := range tests {
+316
View File
@@ -0,0 +1,316 @@
package analyzer
import (
"bytes"
"encoding/json"
"fmt"
"path/filepath"
"regexp"
"strconv"
"strings"
"text/template"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"k8s.io/klog/v2"
kubeletv1alpha1 "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
)
type AnalyzeNodeMetrics struct {
analyzer *troubleshootv1beta2.NodeMetricsAnalyze
}
type nodeMetricsComparisonResults struct {
PVC pvcTemplateData
}
type pvcTemplateData struct {
UsedPercentage float64
ConcatenatedNames string
Names []string
}
type pvcUsageStats struct {
PvcName string
Used float64
}
func (a *AnalyzeNodeMetrics) Title() string {
title := a.analyzer.CheckName
if title == "" {
title = a.analyzer.CollectorName
}
if title == "" {
title = "Node Metrics"
}
return title
}
func (a *AnalyzeNodeMetrics) IsExcluded() (bool, error) {
return isExcluded(a.analyzer.Exclude)
}
func (a *AnalyzeNodeMetrics) Analyze(getFile getCollectedFileContents, findFiles getChildCollectedFileContents) ([]*AnalyzeResult, error) {
// Gather all collected node-metrics files
collected, err := findFiles(filepath.Join("node-metrics", "*.json"), nil)
if err != nil {
return nil, errors.Wrap(err, "failed to read collected pods")
}
// Unmarshal all collected node-metrics files
summaries := []kubeletv1alpha1.Summary{}
for _, fileContent := range collected {
summary := kubeletv1alpha1.Summary{}
if err := json.Unmarshal(fileContent, &summary); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal node metrics")
}
summaries = append(summaries, summary)
}
// Run through all outcomes to generate results
result, err := a.compareCollectedMetricsWithOutcomes(summaries)
if err != nil {
return nil, errors.Wrap(err, "failed to compare node metrics with outcomes")
}
if result == nil {
return []*AnalyzeResult{}, nil
}
result.Strict = a.analyzer.Strict.BoolOrDefaultFalse()
return []*AnalyzeResult{result}, nil
}
func (a *AnalyzeNodeMetrics) compareCollectedMetricsWithOutcomes(summaries []kubeletv1alpha1.Summary) (*AnalyzeResult, error) {
for _, outcome := range a.analyzer.Outcomes {
result := &AnalyzeResult{
Title: a.Title(),
}
if outcome.Fail != nil {
if outcome.Fail.When == "" {
result.IsFail = true
result.Message = outcome.Fail.Message
result.URI = outcome.Fail.URI
return result, nil
} else {
isMatch, out, err := a.compareNodeMetricConditionalsToStats(outcome.Fail.When, summaries)
if err != nil {
return nil, errors.Wrap(err, "failed to compare node metrics conditional with summary stats")
}
if isMatch {
result.IsFail = true
result.Message = renderTemplate(outcome.Fail.Message, out)
result.URI = outcome.Fail.URI
return result, nil
}
}
} else if outcome.Warn != nil {
if outcome.Warn.When == "" {
result.IsWarn = true
result.Message = outcome.Warn.Message
result.URI = outcome.Warn.URI
return result, nil
} else {
isMatch, out, err := a.compareNodeMetricConditionalsToStats(outcome.Warn.When, summaries)
if err != nil {
return nil, errors.Wrap(err, "failed to compare node metrics conditional with summary stats")
}
if isMatch {
result.IsWarn = true
result.Message = renderTemplate(outcome.Warn.Message, out)
result.URI = outcome.Warn.URI
return result, nil
}
}
} else if outcome.Pass != nil {
if outcome.Pass.When == "" {
result.IsPass = true
result.Message = outcome.Pass.Message
result.URI = outcome.Pass.URI
return result, nil
} else {
isMatch, out, err := a.compareNodeMetricConditionalsToStats(outcome.Pass.When, summaries)
if err != nil {
return nil, errors.Wrap(err, "failed to compare node metrics conditional with summary stats")
}
if isMatch {
result.IsPass = true
result.Message = renderTemplate(outcome.Pass.Message, out)
result.URI = outcome.Pass.URI
return result, nil
}
}
}
}
return nil, nil
}
func (a *AnalyzeNodeMetrics) findPVCUsageStats(summaries []kubeletv1alpha1.Summary) ([]pvcUsageStats, error) {
// We just collect usage percentages for now. If other stats are needed, we can add them.
stats := []pvcUsageStats{}
var nameRegex *regexp.Regexp
var ns string
var err error
pvcFilter := a.analyzer.Filters.PVC
if pvcFilter != nil {
if pvcFilter.NameRegex != "" {
nameRegex, err = regexp.Compile(pvcFilter.NameRegex)
if err != nil {
return nil, errors.Wrap(err, "failed to compile PVC name regex")
}
}
ns = pvcFilter.Namespace
}
// Analyze PVCs
for _, summary := range summaries {
for i := range summary.Pods {
pod := summary.Pods[i]
if ns != "" && ns != pod.PodRef.Namespace {
klog.V(2).Infof("Skipping pvcs in %s/%s pod due to namespace filter", pod.PodRef.Namespace, pod.PodRef.Name)
continue
}
for j := range pod.VolumeStats {
volume := pod.VolumeStats[j]
// This is a persistent volume
if volume.PVCRef != nil {
if nameRegex != nil && !nameRegex.MatchString(volume.PVCRef.Name) {
klog.V(2).Infof("Skipping pvc %s/%s due to name regex filter", volume.PVCRef.Namespace, volume.PVCRef.Name)
continue
}
// Calculate the usage
pvcName := fmt.Sprintf("%s/%s", volume.PVCRef.Namespace, volume.PVCRef.Name)
used := volume.UsedBytes
capacity := volume.CapacityBytes
if used != nil && capacity != nil {
pvcUsedPercentage := float64(*used) / float64(*capacity) * 100
stats = append(stats, pvcUsageStats{
PvcName: pvcName,
Used: pvcUsedPercentage,
})
klog.V(2).Infof("PVC usage for %s: %0.2f%%", pvcName, pvcUsedPercentage)
} else {
klog.V(2).Infof("Missing capacity or used bytes for PVC %s", pvcName)
}
}
}
}
}
return stats, nil
}
// compareNodeMetricConditionalsToStats compares the conditional with the collected node metrics
// and returns true if the conditional is met. At the moment we only support comparing PVC usage
func (a *AnalyzeNodeMetrics) compareNodeMetricConditionalsToStats(conditional string, summaries []kubeletv1alpha1.Summary) (bool, nodeMetricsComparisonResults, error) {
klog.V(2).Infof("Comparing node metrics with conditional: %s", conditional)
parts := strings.Split(strings.TrimSpace(conditional), " ")
out := nodeMetricsComparisonResults{}
if len(parts) != 3 {
return false, out, errors.New("unable to parse conditional")
}
switch parts[0] {
case "pvcUsedPercentage":
// e.g pvcUsedPercentage >= 50.4
klog.V(2).Infof("Analyzing volume usage stats for PVCs")
op, err := ParseComparisonOperator(parts[1])
if err != nil {
return false, out, errors.Wrap(err, "failed to parse comparison operator")
}
expected, err := strconv.ParseFloat(parts[2], 64)
if err != nil {
return false, out, errors.Wrap(err, "failed to parse bool")
}
// Pick all PVCs from all summaries. Filters will be applied here
pvcUsageStats, err := a.findPVCUsageStats(summaries)
if err != nil {
return false, out, errors.Wrap(err, "failed to find PVC usage stats")
}
matchedPVCs := []string{}
for _, pvcUsage := range pvcUsageStats {
value := pvcUsage.Used
switch op {
case Equal:
if value == expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
case NotEqual:
if value != expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
case LessThan:
if value < expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
case GreaterThan:
if value > expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
case LessThanOrEqual:
if value <= expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
case GreaterThanOrEqual:
if value >= expected {
matchedPVCs = append(matchedPVCs, pvcUsage.PvcName)
}
}
}
// Concatenate all matched PVC names
out.PVC = pvcTemplateData{
Names: matchedPVCs,
ConcatenatedNames: strings.Join(matchedPVCs, ", "),
}
return len(matchedPVCs) > 0, out, nil
}
return false, out, errors.New("unknown node metric conditional")
}
func renderTemplate(tmpMsg string, data any) string {
if data == nil {
return tmpMsg
}
t, err := template.New("msg").Parse(tmpMsg)
if err != nil {
klog.V(2).Infof("Failed to parse template: %s", err)
return tmpMsg
}
var m bytes.Buffer
err = t.Execute(&m, data)
if err != nil {
klog.V(2).Infof("Failed to execute template: %s", err)
return tmpMsg
}
return m.String()
}
+288
View File
@@ -0,0 +1,288 @@
package analyzer
import (
"testing"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
kubeletv1alpha1 "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
utilptr "k8s.io/utils/ptr"
)
func TestAnalyzeNodeMetrics_findPVCUsageStats(t *testing.T) {
tests := []struct {
name string
analyzer troubleshootv1beta2.NodeMetricsAnalyze
summaries []kubeletv1alpha1.Summary
want []pvcUsageStats
wantErr bool
}{
{
name: "no summaries",
summaries: []kubeletv1alpha1.Summary{},
want: []pvcUsageStats{},
},
{
name: "one summary",
summaries: []kubeletv1alpha1.Summary{
{
Pods: []kubeletv1alpha1.PodStats{
{
PodRef: kubeletv1alpha1.PodReference{
Namespace: "default",
Name: "my-pod",
},
VolumeStats: []kubeletv1alpha1.VolumeStats{
{
Name: "volume-1",
PVCRef: &kubeletv1alpha1.PVCReference{
Namespace: "default",
Name: "my-pvc",
},
FsStats: kubeletv1alpha1.FsStats{
AvailableBytes: utilptr.To(uint64(20)),
UsedBytes: utilptr.To(uint64(80)),
CapacityBytes: utilptr.To(uint64(100)),
},
},
},
},
},
},
},
want: []pvcUsageStats{
{
Used: 80,
PvcName: "default/my-pvc",
},
},
},
{
name: "one summary with namespace filter",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{
PVC: &troubleshootv1beta2.PVCRef{
Namespace: "another-namespace",
},
},
},
summaries: []kubeletv1alpha1.Summary{
{
Pods: []kubeletv1alpha1.PodStats{
{
PodRef: kubeletv1alpha1.PodReference{
Namespace: "default",
Name: "my-pod",
},
VolumeStats: []kubeletv1alpha1.VolumeStats{
{
Name: "volume-1",
PVCRef: &kubeletv1alpha1.PVCReference{
Namespace: "default",
Name: "my-pvc",
},
FsStats: kubeletv1alpha1.FsStats{
AvailableBytes: utilptr.To(uint64(20)),
UsedBytes: utilptr.To(uint64(80)),
CapacityBytes: utilptr.To(uint64(100)),
},
},
},
},
},
},
},
want: []pvcUsageStats{},
},
{
name: "one summary with name regex filter",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{
PVC: &troubleshootv1beta2.PVCRef{
NameRegex: ".*other.*",
},
},
},
summaries: []kubeletv1alpha1.Summary{
{
Pods: []kubeletv1alpha1.PodStats{
{
PodRef: kubeletv1alpha1.PodReference{
Namespace: "default",
Name: "my-pod",
},
VolumeStats: []kubeletv1alpha1.VolumeStats{
{
Name: "volume-1",
PVCRef: &kubeletv1alpha1.PVCReference{
Namespace: "default",
Name: "my-pvc",
},
FsStats: kubeletv1alpha1.FsStats{
AvailableBytes: utilptr.To(uint64(20)),
UsedBytes: utilptr.To(uint64(80)),
CapacityBytes: utilptr.To(uint64(100)),
},
},
{
Name: "volume-1",
PVCRef: &kubeletv1alpha1.PVCReference{
Namespace: "default",
Name: "my-other-pvc",
},
FsStats: kubeletv1alpha1.FsStats{
AvailableBytes: utilptr.To(uint64(25)),
UsedBytes: utilptr.To(uint64(75)),
CapacityBytes: utilptr.To(uint64(100)),
},
},
},
},
},
},
},
want: []pvcUsageStats{
{
Used: 75,
PvcName: "default/my-other-pvc",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AnalyzeNodeMetrics{
analyzer: &tt.analyzer,
}
got, err := a.findPVCUsageStats(tt.summaries)
assert.Equalf(t, tt.wantErr, err != nil, "AnalyzeNodeMetrics.findPVCUsageStats() error = %v, wantErr %v", err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
}
}
func TestAnalyzeNodeMetrics_Analyze(t *testing.T) {
tests := []struct {
name string
analyzer troubleshootv1beta2.NodeMetricsAnalyze
nodeMetrics string
want []*AnalyzeResult
wantErr bool
}{
{
name: "no node metrics",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{},
},
nodeMetrics: "",
wantErr: true,
},
{
name: "invalid node metrics",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{},
},
nodeMetrics: "invalid",
wantErr: true,
},
{
name: "no summaries",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{},
},
nodeMetrics: "{}",
want: []*AnalyzeResult{},
},
{
name: "one summary with name regex filter",
analyzer: troubleshootv1beta2.NodeMetricsAnalyze{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Fail: &troubleshootv1beta2.SingleOutcome{
When: "pvcUsedPercentage >= 75",
Message: "PVC space usage is too high for pvcs [{{ .PVC.ConcatenatedNames }}]",
},
},
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "No PVCs are using more than 80% of storage",
},
},
},
Filters: troubleshootv1beta2.NodeMetricsAnalyzeFilters{
PVC: &troubleshootv1beta2.PVCRef{
NameRegex: ".*other.*",
},
},
},
nodeMetrics: `{
"pods": [
{
"podRef": {
"name": "my-pod",
"namespace": "my-namespace"
},
"volume": [
{
"capacityBytes": 100,
"usedBytes": 80,
"pvcRef": {
"name": "backup-pvc",
"namespace": "my-namespace"
}
},
{
"capacityBytes": 100,
"usedBytes": 75,
"pvcRef": {
"name": "another-pvc",
"namespace": "my-namespace"
}
},
{
"capacityBytes": 100,
"usedBytes": 80,
"pvcRef": {
"name": "the-other-pvc",
"namespace": "my-namespace"
}
},
{
"capacityBytes": 100,
"usedBytes": 65,
"pvcRef": {
"name": "to-other-pvc",
"namespace": "my-namespace"
}
}
]
}
]
}`,
want: []*AnalyzeResult{
{
Title: "Node Metrics",
IsFail: true,
Message: "PVC space usage is too high for pvcs [my-namespace/another-pvc, my-namespace/the-other-pvc]",
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AnalyzeNodeMetrics{
analyzer: &tt.analyzer,
}
filesFn := func(string, []string) (map[string][]byte, error) {
return map[string][]byte{
"node-metrics.json": []byte(tt.nodeMetrics),
}, nil
}
got, err := a.Analyze(nil, filesFn)
assert.Equalf(t, tt.wantErr, err != nil, "AnalyzeNodeMetrics.Analyze() error = %v, wantErr %v", err, tt.wantErr)
assert.Equal(t, tt.want, got)
})
}
}
+18 -14
View File
@@ -17,22 +17,23 @@ import (
)
var Filemap = map[string]string{
"Deployment": constants.CLUSTER_RESOURCES_DEPLOYMENTS,
"StatefulSet": constants.CLUSTER_RESOURCES_STATEFULSETS,
"NetworkPolicy": constants.CLUSTER_RESOURCES_NETWORK_POLICY,
"Pod": constants.CLUSTER_RESOURCES_PODS,
"Ingress": constants.CLUSTER_RESOURCES_INGRESS,
"Service": constants.CLUSTER_RESOURCES_SERVICES,
"ResourceQuota": constants.CLUSTER_RESOURCES_RESOURCE_QUOTA,
"Job": constants.CLUSTER_RESOURCES_JOBS,
"PersistentVolumeClaim": constants.CLUSTER_RESOURCES_PVCS,
"deployment": constants.CLUSTER_RESOURCES_DEPLOYMENTS,
"statefulset": constants.CLUSTER_RESOURCES_STATEFULSETS,
"networkpolicy": constants.CLUSTER_RESOURCES_NETWORK_POLICY,
"pod": constants.CLUSTER_RESOURCES_PODS,
"ingress": constants.CLUSTER_RESOURCES_INGRESS,
"service": constants.CLUSTER_RESOURCES_SERVICES,
"resourcequota": constants.CLUSTER_RESOURCES_RESOURCE_QUOTA,
"job": constants.CLUSTER_RESOURCES_JOBS,
"persistentvolumeclaim": constants.CLUSTER_RESOURCES_PVCS,
"pvc": constants.CLUSTER_RESOURCES_PVCS,
"ReplicaSet": constants.CLUSTER_RESOURCES_REPLICASETS,
"Namespace": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_NAMESPACES),
"PersistentVolume": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_PVS),
"replicaset": constants.CLUSTER_RESOURCES_REPLICASETS,
"configmap": constants.CLUSTER_RESOURCES_CONFIGMAPS,
"namespace": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_NAMESPACES),
"persistentvolume": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_PVS),
"pv": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_PVS),
"Node": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_NODES),
"StorageClass": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_STORAGE_CLASS),
"node": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_NODES),
"storageclass": fmt.Sprintf("%s.json", constants.CLUSTER_RESOURCES_STORAGE_CLASS),
}
type AnalyzeClusterResource struct {
@@ -66,6 +67,9 @@ func FindResource(kind string, clusterScoped bool, namespace string, name string
var datapath string
// lowercase the kind to avoid case sensitivity
kind = strings.ToLower(kind)
resourceLocation, ok := Filemap[kind]
if !ok {
+14 -4
View File
@@ -21,13 +21,13 @@ func Test_findResource(t *testing.T) {
resourceExists: true,
analyzer: troubleshootv1beta2.ClusterResource{
CollectorName: "Check namespaced resource",
Kind: "Deployment",
Kind: "deployment",
Namespace: "kube-system",
Name: "coredns",
},
},
{
name: "check default fallthrough",
name: "check default fallthrough with case insensitivity",
resourceExists: true,
analyzer: troubleshootv1beta2.ClusterResource{
CollectorName: "Check namespaced resource",
@@ -40,7 +40,7 @@ func Test_findResource(t *testing.T) {
resourceExists: true,
analyzer: troubleshootv1beta2.ClusterResource{
CollectorName: "Check namespaced resource",
Kind: "Node",
Kind: "node",
ClusterScoped: true,
Name: "repldev-marc",
},
@@ -50,11 +50,21 @@ func Test_findResource(t *testing.T) {
resourceExists: false,
analyzer: troubleshootv1beta2.ClusterResource{
CollectorName: "Check namespaced resource",
Kind: "Node",
Kind: "node",
ClusterScoped: true,
Name: "resource-does-not-exist",
},
},
{
name: "configmap does exist",
resourceExists: true,
analyzer: troubleshootv1beta2.ClusterResource{
CollectorName: "Check namespaced resource",
Kind: "configmap",
Namespace: "kube-public",
Name: "kube-root-ca.crt",
},
},
}
for _, test := range tests {
+4
View File
@@ -101,6 +101,10 @@ func analyzeOneReplicaSetStatus(analyzer *troubleshootv1beta2.ReplicaSetStatus,
}
}
if result == nil {
return nil, nil
}
return []*AnalyzeResult{result}, nil
}
+15 -12
View File
@@ -361,11 +361,9 @@ func analyzeBackups(backups []*velerov1.Backup) []*AnalyzeResult {
results := []*AnalyzeResult{}
failedPhases := map[velerov1.BackupPhase]bool{
velerov1.BackupPhaseFailed: true,
velerov1.BackupPhasePartiallyFailed: true,
velerov1.BackupPhaseFailedValidation: true,
velerov1.BackupPhaseFinalizingPartiallyFailed: true,
velerov1.BackupPhaseWaitingForPluginOperationsPartiallyFailed: true,
velerov1.BackupPhaseFailed: true,
velerov1.BackupPhasePartiallyFailed: true,
velerov1.BackupPhaseFailedValidation: true,
}
for _, backup := range backups {
@@ -510,10 +508,9 @@ func analyzeRestores(restores []*velerov1.Restore) []*AnalyzeResult {
if len(restores) > 0 {
failedPhases := map[velerov1.RestorePhase]bool{
velerov1.RestorePhaseFailed: true,
velerov1.RestorePhasePartiallyFailed: true,
velerov1.RestorePhaseFailedValidation: true,
velerov1.RestorePhaseWaitingForPluginOperationsPartiallyFailed: true,
velerov1.RestorePhaseFailed: true,
velerov1.RestorePhasePartiallyFailed: true,
velerov1.RestorePhaseFailedValidation: true,
}
for _, restore := range restores {
@@ -658,17 +655,23 @@ func getVeleroVersion(excludedFiles []string, findFiles getChildCollectedFileCon
veleroDeploymentGlob := filepath.Join(veleroDeploymentDir, "velero.json")
veleroDeploymentJson, err := findFiles(veleroDeploymentGlob, excludedFiles)
if err != nil {
return "", errors.Wrapf(err, "failed to find velero deployment file under %s", veleroDeploymentDir)
return "", errors.Wrapf(err, "failed to find Velero deployment")
}
if len(veleroDeploymentJson) == 0 {
return "", errors.Errorf("could not find Velero deployment in %s", veleroDeploymentDir)
}
var deploymentList *appsV1.DeploymentList
// should run only once
for key, veleroDeploymentJsonBytes := range veleroDeploymentJson {
err := json.Unmarshal(veleroDeploymentJsonBytes, &deploymentList)
if err != nil {
return "", errors.Wrapf(err, "failed to unmarshal velero deployment json from %s", key)
return "", errors.Wrapf(err, "failed to unmarshal Velero deployment json from %s", key)
}
break
}
if deploymentList == nil {
return "", errors.Errorf("could not find Velero deployment")
}
for _, deployment := range deploymentList.Items {
for _, container := range deployment.Spec.Template.Spec.Containers {
if container.Name == "velero" {
@@ -679,7 +682,7 @@ func getVeleroVersion(excludedFiles []string, findFiles getChildCollectedFileCon
}
}
return "", errors.Errorf("Unable to get velero version. Could not find velero container in deployment!")
return "", errors.Errorf("could not find Velero container in deployment")
}
func GetVeleroBackupsDirectory() string {
-26
View File
@@ -626,32 +626,6 @@ func TestAnalyzeVelero_Restores(t *testing.T) {
},
},
},
{
name: "restores - failures",
args: args{
restores: []*velerov1.Restore{
{
ObjectMeta: metav1.ObjectMeta{
Name: "observability-backup-20210308150016",
Namespace: "velero",
},
Spec: velerov1.RestoreSpec{
BackupName: "observability-backup",
},
Status: velerov1.RestoreStatus{
Phase: velerov1.RestorePhaseWaitingForPluginOperationsPartiallyFailed,
},
},
},
},
want: []*AnalyzeResult{
{
Title: "Restore observability-backup-20210308150016",
Message: "Restore observability-backup-20210308150016 phase is WaitingForPluginOperationsPartiallyFailed",
IsFail: true,
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
+18
View File
@@ -6,6 +6,7 @@ import (
"strconv"
"github.com/pkg/errors"
util "github.com/replicatedhq/troubleshoot/internal/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
iutils "github.com/replicatedhq/troubleshoot/pkg/interfaceutils"
"gopkg.in/yaml.v2"
@@ -50,6 +51,8 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
return nil, errors.Wrap(err, "failed to parse collected data as yaml doc")
}
originalActual := actual
if analyzer.Path != "" {
actual, err = iutils.GetAtPath(actual, analyzer.Path)
if err != nil {
@@ -81,6 +84,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
}
}
outcome.Fail.Message, err = util.RenderTemplate(outcome.Fail.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsFail = true
result.Message = outcome.Fail.Message
@@ -96,6 +104,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
}
}
outcome.Warn.Message, err = util.RenderTemplate(outcome.Warn.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsWarn = true
result.Message = outcome.Warn.Message
@@ -111,6 +124,11 @@ func (a *AnalyzeYamlCompare) analyzeYamlCompare(analyzer *troubleshootv1beta2.Ya
}
}
outcome.Pass.Message, err = util.RenderTemplate(outcome.Pass.Message, originalActual)
if err != nil {
return nil, errors.Wrap(err, "failed to render template on outcome message")
}
if when == equal {
result.IsPass = true
result.Message = outcome.Pass.Message
+39
View File
@@ -430,6 +430,45 @@ otherstuff:
},
fileContents: []byte(``),
},
{
name: "basic comparison with outcome message templated",
analyzer: troubleshootv1beta2.YamlCompare{
Outcomes: []*troubleshootv1beta2.Outcome{
{
Pass: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .stuff.status }}, Info: {{ .stuff.info }}",
When: "true",
},
},
{
Fail: &troubleshootv1beta2.SingleOutcome{
Message: "Status: {{ .stuff.status }}, Info: {{ .stuff.info }}",
When: "false",
},
},
},
CollectorName: "yaml-compare",
FileName: "yaml-compare.yaml",
Value: `ready`,
Path: "stuff.status",
},
expectResult: AnalyzeResult{
IsPass: true,
IsWarn: false,
IsFail: false,
Title: "yaml-compare",
Message: "Status: ready, Info: stuff is ready",
IconKey: "kubernetes_text_analyze",
IconURI: "https://troubleshoot.sh/images/analyzer-icons/text-analyze.svg",
},
fileContents: []byte(`
stuff:
status: ready
info: stuff is ready
morestuff:
status: notready
info: morestuff is not ready`),
},
}
for _, test := range tests {
@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2019 Replicated, Inc..
@@ -232,6 +232,32 @@ type GoldpingerAnalyze struct {
FilePath string `json:"filePath,omitempty" yaml:"filePath,omitempty"`
}
type EventAnalyze struct {
AnalyzeMeta `json:",inline" yaml:",inline"`
CollectorName string `json:"collectorName" yaml:"collectorName"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`
Reason string `json:"reason" yaml:"reason"`
RegexPattern string `json:"regex,omitempty" yaml:"regex,omitempty"`
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
}
type NodeMetricsAnalyze struct {
AnalyzeMeta `json:",inline" yaml:",inline"`
CollectorName string `json:"collectorName" yaml:"collectorName"`
Filters NodeMetricsAnalyzeFilters `json:"filters,omitempty" yaml:"filters,omitempty"`
Outcomes []*Outcome `json:"outcomes" yaml:"outcomes"`
}
type NodeMetricsAnalyzeFilters struct {
PVC *PVCRef `json:"pvc,omitempty" yaml:"pvc,omitempty"`
}
type PVCRef struct {
NameRegex string `json:"nameRegex,omitempty" yaml:"nameRegex,omitempty"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
}
type Analyze struct {
ClusterVersion *ClusterVersion `json:"clusterVersion,omitempty" yaml:"clusterVersion,omitempty"`
StorageClass *StorageClass `json:"storageClass,omitempty" yaml:"storageClass,omitempty"`
@@ -264,4 +290,6 @@ type Analyze struct {
ClusterResource *ClusterResource `json:"clusterResource,omitempty" yaml:"clusterResource,omitempty"`
Certificates *CertificatesAnalyze `json:"certificates,omitempty" yaml:"certificates,omitempty"`
Goldpinger *GoldpingerAnalyze `json:"goldpinger,omitempty" yaml:"goldpinger,omitempty"`
Event *EventAnalyze `json:"event,omitempty" yaml:"event,omitempty"`
NodeMetrics *NodeMetricsAnalyze `json:"nodeMetrics,omitempty" yaml:"nodeMetrics,omitempty"`
}
@@ -44,6 +44,12 @@ type CustomMetrics struct {
MetricRequests []MetricRequest `json:"metricRequests,omitempty" yaml:"metricRequests,omitempty"`
}
type NodeMetrics struct {
CollectorMeta `json:",inline" yaml:",inline"`
NodeNames []string `json:"nodeNames,omitempty" yaml:"nodeNames,omitempty"`
Selector []string `json:"selector,omitempty" yaml:"selector,omitempty"`
}
type Secret struct {
CollectorMeta `json:",inline" yaml:",inline"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
@@ -107,6 +113,15 @@ type RunPod struct {
PodSpec corev1.PodSpec `json:"podSpec,omitempty" yaml:"podSpec,omitempty"`
}
type RunDaemonSet struct {
CollectorMeta `json:",inline" yaml:",inline"`
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Namespace string `json:"namespace" yaml:"namespace"`
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
ImagePullSecret *ImagePullSecrets `json:"imagePullSecret,omitempty" yaml:"imagePullSecret,omitempty"`
PodSpec corev1.PodSpec `json:"podSpec,omitempty" yaml:"podSpec,omitempty"`
}
type ImagePullSecrets struct {
Name string `json:"name,omitempty" yaml:"name,omitempty"`
Data map[string]string `json:"data,omitempty" yaml:"data,omitempty"`
@@ -257,6 +272,7 @@ type Helm struct {
CollectorMeta `json:",inline" yaml:",inline"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
ReleaseName string `json:"releaseName,omitempty" yaml:"releaseName,omitempty"`
CollectValues bool `json:"collectValues,omitempty" yaml:"collectValues,omitempty"`
}
type Goldpinger struct {
@@ -272,6 +288,16 @@ type PodLaunchOptions struct {
ServiceAccountName string `json:"serviceAccountName,omitempty" yaml:"serviceAccountName,omitempty"`
}
type Sonobuoy struct {
CollectorMeta `json:",inline" yaml:",inline"`
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
}
type DNS struct {
CollectorMeta `json:",inline" yaml:",inline"`
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
}
type Collect struct {
ClusterInfo *ClusterInfo `json:"clusterInfo,omitempty" yaml:"clusterInfo,omitempty"`
ClusterResources *ClusterResources `json:"clusterResources,omitempty" yaml:"clusterResources,omitempty"`
@@ -281,6 +307,7 @@ type Collect struct {
Logs *Logs `json:"logs,omitempty" yaml:"logs,omitempty"`
Run *Run `json:"run,omitempty" yaml:"run,omitempty"`
RunPod *RunPod `json:"runPod,omitempty" yaml:"runPod,omitempty"`
RunDaemonSet *RunDaemonSet `json:"runDaemonSet,omitempty" yaml:"runDaemonSet,omitempty"`
Exec *Exec `json:"exec,omitempty" yaml:"exec,omitempty"`
Data *Data `json:"data,omitempty" yaml:"data,omitempty"`
Copy *Copy `json:"copy,omitempty" yaml:"copy,omitempty"`
@@ -298,6 +325,9 @@ type Collect struct {
Certificates *Certificates `json:"certificates,omitempty" yaml:"certificates,omitempty"`
Helm *Helm `json:"helm,omitempty" yaml:"helm,omitempty"`
Goldpinger *Goldpinger `json:"goldpinger,omitempty" yaml:"goldpinger,omitempty"`
Sonobuoy *Sonobuoy `json:"sonobuoy,omitempty" yaml:"sonobuoy,omitempty"`
NodeMetrics *NodeMetrics `json:"nodeMetrics,omitempty" yaml:"nodeMetrics,omitempty"`
DNS *DNS `json:"dns,omitempty" yaml:"dns,omitempty"`
}
func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSubjectAccessReviewSpec {
@@ -431,6 +461,19 @@ func (c *Collect) AccessReviewSpecs(overrideNS string) []authorizationv1.SelfSub
},
NonResourceAttributes: nil,
})
} else if c.RunDaemonSet != nil {
result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &authorizationv1.ResourceAttributes{
Namespace: pickNamespaceOrDefault(c.RunDaemonSet.Namespace, overrideNS),
Verb: "create",
Group: "",
Version: "",
Resource: "pods",
Subresource: "",
Name: "",
},
NonResourceAttributes: nil,
})
} else if c.Exec != nil {
result = append(result, authorizationv1.SelfSubjectAccessReviewSpec{
ResourceAttributes: &authorizationv1.ResourceAttributes{
@@ -541,6 +584,10 @@ func (c *Collect) GetName() string {
collector = "run-pod"
name = c.RunPod.CollectorName
}
if c.RunDaemonSet != nil {
collector = "run-daemonset"
name = c.RunDaemonSet.CollectorName
}
if c.Exec != nil {
collector = "exec"
name = c.Exec.CollectorName
@@ -187,6 +187,7 @@ type HostRun struct {
Env []string `json:"env,omitempty" yaml:"env,omitempty"`
InheritEnvs []string `json:"inheritEnvs,omitempty" yaml:"inheritEnvs,omitempty"`
IgnoreParentEnvs bool `json:"ignoreParentEnvs,omitempty" yaml:"ignoreParentEnvs,omitempty"`
Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty"`
}
type HostCollect struct {
@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 2019 Replicated, Inc..
@@ -209,6 +208,16 @@ func (in *Analyze) DeepCopyInto(out *Analyze) {
*out = new(GoldpingerAnalyze)
(*in).DeepCopyInto(*out)
}
if in.Event != nil {
in, out := &in.Event, &out.Event
*out = new(EventAnalyze)
(*in).DeepCopyInto(*out)
}
if in.NodeMetrics != nil {
in, out := &in.NodeMetrics, &out.NodeMetrics
*out = new(NodeMetricsAnalyze)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Analyze.
@@ -817,6 +826,11 @@ func (in *Collect) DeepCopyInto(out *Collect) {
*out = new(RunPod)
(*in).DeepCopyInto(*out)
}
if in.RunDaemonSet != nil {
in, out := &in.RunDaemonSet, &out.RunDaemonSet
*out = new(RunDaemonSet)
(*in).DeepCopyInto(*out)
}
if in.Exec != nil {
in, out := &in.Exec, &out.Exec
*out = new(Exec)
@@ -902,6 +916,21 @@ func (in *Collect) DeepCopyInto(out *Collect) {
*out = new(Goldpinger)
(*in).DeepCopyInto(*out)
}
if in.Sonobuoy != nil {
in, out := &in.Sonobuoy, &out.Sonobuoy
*out = new(Sonobuoy)
(*in).DeepCopyInto(*out)
}
if in.NodeMetrics != nil {
in, out := &in.NodeMetrics, &out.NodeMetrics
*out = new(NodeMetrics)
(*in).DeepCopyInto(*out)
}
if in.DNS != nil {
in, out := &in.DNS, &out.DNS
*out = new(DNS)
(*in).DeepCopyInto(*out)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Collect.
@@ -1231,6 +1260,22 @@ func (in *CustomResourceDefinition) DeepCopy() *CustomResourceDefinition {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DNS) DeepCopyInto(out *DNS) {
*out = *in
in.CollectorMeta.DeepCopyInto(&out.CollectorMeta)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNS.
func (in *DNS) DeepCopy() *DNS {
if in == nil {
return nil
}
out := new(DNS)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Data) DeepCopyInto(out *Data) {
*out = *in
@@ -1402,6 +1447,33 @@ func (in *Distribution) DeepCopy() *Distribution {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *EventAnalyze) DeepCopyInto(out *EventAnalyze) {
*out = *in
in.AnalyzeMeta.DeepCopyInto(&out.AnalyzeMeta)
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Outcome)
(*in).DeepCopyInto(*out)
}
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventAnalyze.
func (in *EventAnalyze) DeepCopy() *EventAnalyze {
if in == nil {
return nil
}
out := new(EventAnalyze)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Exec) DeepCopyInto(out *Exec) {
*out = *in
@@ -2943,6 +3015,80 @@ func (in *MetricRequest) DeepCopy() *MetricRequest {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeMetrics) DeepCopyInto(out *NodeMetrics) {
*out = *in
in.CollectorMeta.DeepCopyInto(&out.CollectorMeta)
if in.NodeNames != nil {
in, out := &in.NodeNames, &out.NodeNames
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Selector != nil {
in, out := &in.Selector, &out.Selector
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeMetrics.
func (in *NodeMetrics) DeepCopy() *NodeMetrics {
if in == nil {
return nil
}
out := new(NodeMetrics)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeMetricsAnalyze) DeepCopyInto(out *NodeMetricsAnalyze) {
*out = *in
in.AnalyzeMeta.DeepCopyInto(&out.AnalyzeMeta)
in.Filters.DeepCopyInto(&out.Filters)
if in.Outcomes != nil {
in, out := &in.Outcomes, &out.Outcomes
*out = make([]*Outcome, len(*in))
for i := range *in {
if (*in)[i] != nil {
in, out := &(*in)[i], &(*out)[i]
*out = new(Outcome)
(*in).DeepCopyInto(*out)
}
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeMetricsAnalyze.
func (in *NodeMetricsAnalyze) DeepCopy() *NodeMetricsAnalyze {
if in == nil {
return nil
}
out := new(NodeMetricsAnalyze)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeMetricsAnalyzeFilters) DeepCopyInto(out *NodeMetricsAnalyzeFilters) {
*out = *in
if in.PVC != nil {
in, out := &in.PVC, &out.PVC
*out = new(PVCRef)
**out = **in
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeMetricsAnalyzeFilters.
func (in *NodeMetricsAnalyzeFilters) DeepCopy() *NodeMetricsAnalyzeFilters {
if in == nil {
return nil
}
out := new(NodeMetricsAnalyzeFilters)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NodeResourceFilters) DeepCopyInto(out *NodeResourceFilters) {
*out = *in
@@ -3047,6 +3193,21 @@ func (in *Outcome) DeepCopy() *Outcome {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PVCRef) DeepCopyInto(out *PVCRef) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PVCRef.
func (in *PVCRef) DeepCopy() *PVCRef {
if in == nil {
return nil
}
out := new(PVCRef)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PodLaunchOptions) DeepCopyInto(out *PodLaunchOptions) {
*out = *in
@@ -4078,6 +4239,28 @@ func (in *Run) DeepCopy() *Run {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RunDaemonSet) DeepCopyInto(out *RunDaemonSet) {
*out = *in
in.CollectorMeta.DeepCopyInto(&out.CollectorMeta)
if in.ImagePullSecret != nil {
in, out := &in.ImagePullSecret, &out.ImagePullSecret
*out = new(ImagePullSecrets)
(*in).DeepCopyInto(*out)
}
in.PodSpec.DeepCopyInto(&out.PodSpec)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RunDaemonSet.
func (in *RunDaemonSet) DeepCopy() *RunDaemonSet {
if in == nil {
return nil
}
out := new(RunDaemonSet)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *RunPod) DeepCopyInto(out *RunPod) {
*out = *in
@@ -4136,6 +4319,22 @@ func (in *SingleOutcome) DeepCopy() *SingleOutcome {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Sonobuoy) DeepCopyInto(out *Sonobuoy) {
*out = *in
in.CollectorMeta.DeepCopyInto(&out.CollectorMeta)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Sonobuoy.
func (in *Sonobuoy) DeepCopy() *Sonobuoy {
if in == nil {
return nil
}
out := new(Sonobuoy)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StatefulsetStatus) DeepCopyInto(out *StatefulsetStatus) {
*out = *in
+33 -11
View File
@@ -19,6 +19,7 @@ package troubleshootclientset
import (
"fmt"
"net/http"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta2"
@@ -33,8 +34,7 @@ type Interface interface {
TroubleshootV1beta2() troubleshootv1beta2.TroubleshootV1beta2Interface
}
// Clientset contains the clients for groups. Each group has exactly one
// version included in a Clientset.
// Clientset contains the clients for groups.
type Clientset struct {
*discovery.DiscoveryClient
troubleshootV1beta1 *troubleshootv1beta1.TroubleshootV1beta1Client
@@ -62,26 +62,49 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
// NewForConfig creates a new Clientset for the given config.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfig will generate a rate-limiter in configShallowCopy.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.UserAgent == "" {
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
}
// share the transport between all clients
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&configShallowCopy, httpClient)
}
// NewForConfigAndClient creates a new Clientset for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
if configShallowCopy.Burst <= 0 {
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var cs Clientset
var err error
cs.troubleshootV1beta1, err = troubleshootv1beta1.NewForConfig(&configShallowCopy)
cs.troubleshootV1beta1, err = troubleshootv1beta1.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
cs.troubleshootV1beta2, err = troubleshootv1beta2.NewForConfig(&configShallowCopy)
cs.troubleshootV1beta2, err = troubleshootv1beta2.NewForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
if err != nil {
return nil, err
}
@@ -91,12 +114,11 @@ func NewForConfig(c *rest.Config) (*Clientset, error) {
// NewForConfigOrDie creates a new Clientset for the given config and
// panics if there is an error in the config.
func NewForConfigOrDie(c *rest.Config) *Clientset {
var cs Clientset
cs.troubleshootV1beta1 = troubleshootv1beta1.NewForConfigOrDie(c)
cs.troubleshootV1beta2 = troubleshootv1beta2.NewForConfigOrDie(c)
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
return &cs
cs, err := NewForConfig(c)
if err != nil {
panic(err)
}
return cs
}
// New creates a new Clientset for the given RESTClient.
@@ -23,7 +23,6 @@ import (
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeAnalyzers struct {
ns string
}
var analyzersResource = schema.GroupVersionResource{Group: "troubleshoot.replicated.com", Version: "v1beta1", Resource: "analyzers"}
var analyzersResource = v1beta1.SchemeGroupVersion.WithResource("analyzers")
var analyzersKind = schema.GroupVersionKind{Group: "troubleshoot.replicated.com", Version: "v1beta1", Kind: "Analyzer"}
var analyzersKind = v1beta1.SchemeGroupVersion.WithKind("Analyzer")
// Get takes name of the analyzer, and returns the corresponding analyzer object, and an error if there is any.
func (c *FakeAnalyzers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Analyzer, err error) {
@@ -116,7 +115,7 @@ func (c *FakeAnalyzers) UpdateStatus(ctx context.Context, analyzer *v1beta1.Anal
// Delete takes name of the analyzer and deletes it. Returns an error if one occurs.
func (c *FakeAnalyzers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(analyzersResource, c.ns, name), &v1beta1.Analyzer{})
Invokes(testing.NewDeleteActionWithOptions(analyzersResource, c.ns, name, opts), &v1beta1.Analyzer{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeCollectors struct {
ns string
}
var collectorsResource = schema.GroupVersionResource{Group: "troubleshoot.replicated.com", Version: "v1beta1", Resource: "collectors"}
var collectorsResource = v1beta1.SchemeGroupVersion.WithResource("collectors")
var collectorsKind = schema.GroupVersionKind{Group: "troubleshoot.replicated.com", Version: "v1beta1", Kind: "Collector"}
var collectorsKind = v1beta1.SchemeGroupVersion.WithKind("Collector")
// Get takes name of the collector, and returns the corresponding collector object, and an error if there is any.
func (c *FakeCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Collector, err error) {
@@ -116,7 +115,7 @@ func (c *FakeCollectors) UpdateStatus(ctx context.Context, collector *v1beta1.Co
// Delete takes name of the collector and deletes it. Returns an error if one occurs.
func (c *FakeCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(collectorsResource, c.ns, name), &v1beta1.Collector{})
Invokes(testing.NewDeleteActionWithOptions(collectorsResource, c.ns, name, opts), &v1beta1.Collector{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakePreflights struct {
ns string
}
var preflightsResource = schema.GroupVersionResource{Group: "troubleshoot.replicated.com", Version: "v1beta1", Resource: "preflights"}
var preflightsResource = v1beta1.SchemeGroupVersion.WithResource("preflights")
var preflightsKind = schema.GroupVersionKind{Group: "troubleshoot.replicated.com", Version: "v1beta1", Kind: "Preflight"}
var preflightsKind = v1beta1.SchemeGroupVersion.WithKind("Preflight")
// Get takes name of the preflight, and returns the corresponding preflight object, and an error if there is any.
func (c *FakePreflights) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Preflight, err error) {
@@ -116,7 +115,7 @@ func (c *FakePreflights) UpdateStatus(ctx context.Context, preflight *v1beta1.Pr
// Delete takes name of the preflight and deletes it. Returns an error if one occurs.
func (c *FakePreflights) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(preflightsResource, c.ns, name), &v1beta1.Preflight{})
Invokes(testing.NewDeleteActionWithOptions(preflightsResource, c.ns, name, opts), &v1beta1.Preflight{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeRedactors struct {
ns string
}
var redactorsResource = schema.GroupVersionResource{Group: "troubleshoot.replicated.com", Version: "v1beta1", Resource: "redactors"}
var redactorsResource = v1beta1.SchemeGroupVersion.WithResource("redactors")
var redactorsKind = schema.GroupVersionKind{Group: "troubleshoot.replicated.com", Version: "v1beta1", Kind: "Redactor"}
var redactorsKind = v1beta1.SchemeGroupVersion.WithKind("Redactor")
// Get takes name of the redactor, and returns the corresponding redactor object, and an error if there is any.
func (c *FakeRedactors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.Redactor, err error) {
@@ -116,7 +115,7 @@ func (c *FakeRedactors) UpdateStatus(ctx context.Context, redactor *v1beta1.Reda
// Delete takes name of the redactor and deletes it. Returns an error if one occurs.
func (c *FakeRedactors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(redactorsResource, c.ns, name), &v1beta1.Redactor{})
Invokes(testing.NewDeleteActionWithOptions(redactorsResource, c.ns, name, opts), &v1beta1.Redactor{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeSupportBundles struct {
ns string
}
var supportbundlesResource = schema.GroupVersionResource{Group: "troubleshoot.replicated.com", Version: "v1beta1", Resource: "supportbundles"}
var supportbundlesResource = v1beta1.SchemeGroupVersion.WithResource("supportbundles")
var supportbundlesKind = schema.GroupVersionKind{Group: "troubleshoot.replicated.com", Version: "v1beta1", Kind: "SupportBundle"}
var supportbundlesKind = v1beta1.SchemeGroupVersion.WithKind("SupportBundle")
// Get takes name of the supportBundle, and returns the corresponding supportBundle object, and an error if there is any.
func (c *FakeSupportBundles) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.SupportBundle, err error) {
@@ -116,7 +115,7 @@ func (c *FakeSupportBundles) UpdateStatus(ctx context.Context, supportBundle *v1
// Delete takes name of the supportBundle and deletes it. Returns an error if one occurs.
func (c *FakeSupportBundles) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(supportbundlesResource, c.ns, name), &v1beta1.SupportBundle{})
Invokes(testing.NewDeleteActionWithOptions(supportbundlesResource, c.ns, name, opts), &v1beta1.SupportBundle{})
return err
}
@@ -18,6 +18,8 @@ limitations under the License.
package v1beta1
import (
"net/http"
v1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
rest "k8s.io/client-go/rest"
@@ -58,12 +60,28 @@ func (c *TroubleshootV1beta1Client) SupportBundles(namespace string) SupportBund
}
// NewForConfig creates a new TroubleshootV1beta1Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*TroubleshootV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new TroubleshootV1beta1Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*TroubleshootV1beta1Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeAnalyzers struct {
ns string
}
var analyzersResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "analyzers"}
var analyzersResource = v1beta2.SchemeGroupVersion.WithResource("analyzers")
var analyzersKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "Analyzer"}
var analyzersKind = v1beta2.SchemeGroupVersion.WithKind("Analyzer")
// Get takes name of the analyzer, and returns the corresponding analyzer object, and an error if there is any.
func (c *FakeAnalyzers) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.Analyzer, err error) {
@@ -116,7 +115,7 @@ func (c *FakeAnalyzers) UpdateStatus(ctx context.Context, analyzer *v1beta2.Anal
// Delete takes name of the analyzer and deletes it. Returns an error if one occurs.
func (c *FakeAnalyzers) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(analyzersResource, c.ns, name), &v1beta2.Analyzer{})
Invokes(testing.NewDeleteActionWithOptions(analyzersResource, c.ns, name, opts), &v1beta2.Analyzer{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeCollectors struct {
ns string
}
var collectorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "collectors"}
var collectorsResource = v1beta2.SchemeGroupVersion.WithResource("collectors")
var collectorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "Collector"}
var collectorsKind = v1beta2.SchemeGroupVersion.WithKind("Collector")
// Get takes name of the collector, and returns the corresponding collector object, and an error if there is any.
func (c *FakeCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.Collector, err error) {
@@ -116,7 +115,7 @@ func (c *FakeCollectors) UpdateStatus(ctx context.Context, collector *v1beta2.Co
// Delete takes name of the collector and deletes it. Returns an error if one occurs.
func (c *FakeCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(collectorsResource, c.ns, name), &v1beta2.Collector{})
Invokes(testing.NewDeleteActionWithOptions(collectorsResource, c.ns, name, opts), &v1beta2.Collector{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeHostCollectors struct {
ns string
}
var hostcollectorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "hostcollectors"}
var hostcollectorsResource = v1beta2.SchemeGroupVersion.WithResource("hostcollectors")
var hostcollectorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "HostCollector"}
var hostcollectorsKind = v1beta2.SchemeGroupVersion.WithKind("HostCollector")
// Get takes name of the hostCollector, and returns the corresponding hostCollector object, and an error if there is any.
func (c *FakeHostCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.HostCollector, err error) {
@@ -116,7 +115,7 @@ func (c *FakeHostCollectors) UpdateStatus(ctx context.Context, hostCollector *v1
// Delete takes name of the hostCollector and deletes it. Returns an error if one occurs.
func (c *FakeHostCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(hostcollectorsResource, c.ns, name), &v1beta2.HostCollector{})
Invokes(testing.NewDeleteActionWithOptions(hostcollectorsResource, c.ns, name, opts), &v1beta2.HostCollector{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeHostPreflights struct {
ns string
}
var hostpreflightsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "hostpreflights"}
var hostpreflightsResource = v1beta2.SchemeGroupVersion.WithResource("hostpreflights")
var hostpreflightsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "HostPreflight"}
var hostpreflightsKind = v1beta2.SchemeGroupVersion.WithKind("HostPreflight")
// Get takes name of the hostPreflight, and returns the corresponding hostPreflight object, and an error if there is any.
func (c *FakeHostPreflights) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.HostPreflight, err error) {
@@ -116,7 +115,7 @@ func (c *FakeHostPreflights) UpdateStatus(ctx context.Context, hostPreflight *v1
// Delete takes name of the hostPreflight and deletes it. Returns an error if one occurs.
func (c *FakeHostPreflights) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(hostpreflightsResource, c.ns, name), &v1beta2.HostPreflight{})
Invokes(testing.NewDeleteActionWithOptions(hostpreflightsResource, c.ns, name, opts), &v1beta2.HostPreflight{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakePreflights struct {
ns string
}
var preflightsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "preflights"}
var preflightsResource = v1beta2.SchemeGroupVersion.WithResource("preflights")
var preflightsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "Preflight"}
var preflightsKind = v1beta2.SchemeGroupVersion.WithKind("Preflight")
// Get takes name of the preflight, and returns the corresponding preflight object, and an error if there is any.
func (c *FakePreflights) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.Preflight, err error) {
@@ -116,7 +115,7 @@ func (c *FakePreflights) UpdateStatus(ctx context.Context, preflight *v1beta2.Pr
// Delete takes name of the preflight and deletes it. Returns an error if one occurs.
func (c *FakePreflights) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(preflightsResource, c.ns, name), &v1beta2.Preflight{})
Invokes(testing.NewDeleteActionWithOptions(preflightsResource, c.ns, name, opts), &v1beta2.Preflight{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeRedactors struct {
ns string
}
var redactorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "redactors"}
var redactorsResource = v1beta2.SchemeGroupVersion.WithResource("redactors")
var redactorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "Redactor"}
var redactorsKind = v1beta2.SchemeGroupVersion.WithKind("Redactor")
// Get takes name of the redactor, and returns the corresponding redactor object, and an error if there is any.
func (c *FakeRedactors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.Redactor, err error) {
@@ -116,7 +115,7 @@ func (c *FakeRedactors) UpdateStatus(ctx context.Context, redactor *v1beta2.Reda
// Delete takes name of the redactor and deletes it. Returns an error if one occurs.
func (c *FakeRedactors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(redactorsResource, c.ns, name), &v1beta2.Redactor{})
Invokes(testing.NewDeleteActionWithOptions(redactorsResource, c.ns, name, opts), &v1beta2.Redactor{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeRemoteCollectors struct {
ns string
}
var remotecollectorsResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "remotecollectors"}
var remotecollectorsResource = v1beta2.SchemeGroupVersion.WithResource("remotecollectors")
var remotecollectorsKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "RemoteCollector"}
var remotecollectorsKind = v1beta2.SchemeGroupVersion.WithKind("RemoteCollector")
// Get takes name of the remoteCollector, and returns the corresponding remoteCollector object, and an error if there is any.
func (c *FakeRemoteCollectors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.RemoteCollector, err error) {
@@ -116,7 +115,7 @@ func (c *FakeRemoteCollectors) UpdateStatus(ctx context.Context, remoteCollector
// Delete takes name of the remoteCollector and deletes it. Returns an error if one occurs.
func (c *FakeRemoteCollectors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(remotecollectorsResource, c.ns, name), &v1beta2.RemoteCollector{})
Invokes(testing.NewDeleteActionWithOptions(remotecollectorsResource, c.ns, name, opts), &v1beta2.RemoteCollector{})
return err
}
@@ -23,7 +23,6 @@ import (
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
@@ -35,9 +34,9 @@ type FakeSupportBundles struct {
ns string
}
var supportbundlesResource = schema.GroupVersionResource{Group: "troubleshoot.sh", Version: "v1beta2", Resource: "supportbundles"}
var supportbundlesResource = v1beta2.SchemeGroupVersion.WithResource("supportbundles")
var supportbundlesKind = schema.GroupVersionKind{Group: "troubleshoot.sh", Version: "v1beta2", Kind: "SupportBundle"}
var supportbundlesKind = v1beta2.SchemeGroupVersion.WithKind("SupportBundle")
// Get takes name of the supportBundle, and returns the corresponding supportBundle object, and an error if there is any.
func (c *FakeSupportBundles) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta2.SupportBundle, err error) {
@@ -116,7 +115,7 @@ func (c *FakeSupportBundles) UpdateStatus(ctx context.Context, supportBundle *v1
// Delete takes name of the supportBundle and deletes it. Returns an error if one occurs.
func (c *FakeSupportBundles) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(supportbundlesResource, c.ns, name), &v1beta2.SupportBundle{})
Invokes(testing.NewDeleteActionWithOptions(supportbundlesResource, c.ns, name, opts), &v1beta2.SupportBundle{})
return err
}
@@ -18,6 +18,8 @@ limitations under the License.
package v1beta2
import (
"net/http"
v1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
rest "k8s.io/client-go/rest"
@@ -73,12 +75,28 @@ func (c *TroubleshootV1beta2Client) SupportBundles(namespace string) SupportBund
}
// NewForConfig creates a new TroubleshootV1beta2Client for the given config.
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
// where httpClient was generated with rest.HTTPClientFor(c).
func NewForConfig(c *rest.Config) (*TroubleshootV1beta2Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientFor(&config)
httpClient, err := rest.HTTPClientFor(&config)
if err != nil {
return nil, err
}
return NewForConfigAndClient(&config, httpClient)
}
// NewForConfigAndClient creates a new TroubleshootV1beta2Client for the given config and http client.
// Note the http client provided takes precedence over the configured transport values.
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*TroubleshootV1beta2Client, error) {
config := *c
if err := setConfigDefaults(&config); err != nil {
return nil, err
}
client, err := rest.RESTClientForConfigAndClient(&config, h)
if err != nil {
return nil, err
}
+33 -7
View File
@@ -35,6 +35,12 @@ var CephCommands = []CephCommand{
Format: "json",
DefaultTimeout: "30s",
},
{
ID: "status-txt",
Command: []string{"ceph", "status"},
Format: "txt",
DefaultTimeout: "30s",
},
{
ID: "fs",
Command: []string{"ceph", "fs", "status"},
@@ -42,6 +48,12 @@ var CephCommands = []CephCommand{
Format: "json",
DefaultTimeout: "30s",
},
{
ID: "fs-txt",
Command: []string{"ceph", "fs", "status"},
Format: "txt",
DefaultTimeout: "30s",
},
{
ID: "fs-ls",
Command: []string{"ceph", "fs", "ls"},
@@ -53,7 +65,7 @@ var CephCommands = []CephCommand{
ID: "osd-status",
Command: []string{"ceph", "osd", "status"},
Args: []string{"-f", "json-pretty"},
Format: "txt",
Format: "json",
DefaultTimeout: "30s",
},
{
@@ -88,15 +100,17 @@ var CephCommands = []CephCommand{
ID: "rgw-stats", // the disk usage (and other stats) of each object store bucket
Command: []string{"radosgw-admin", "bucket", "stats"},
Args: []string{"--rgw-cache-enabled=false"},
Format: "txt",
Format: "json",
DefaultTimeout: "30s", // include a default timeout because this command will hang if the RGW daemon isn't running/is unhealthy
},
{
ID: "rbd-du", // the disk usage of each PVC
Command: []string{"rbd", "du"},
Args: []string{"--pool=replicapool"},
Format: "txt",
DefaultTimeout: "30s",
ID: "rbd-du-txt", // the disk usage of each PVC
Command: []string{"rbd", "du"},
Args: []string{"--pool=replicapool"},
Format: "txt",
// On ceph clusters with a lot of data, this command can take a long time to run
// especially if fast-diff rbd_default_features is disabled
DefaultTimeout: "60s",
},
{
ID: "df", // the disk usage of each pool
@@ -105,6 +119,12 @@ var CephCommands = []CephCommand{
Format: "json",
DefaultTimeout: "30s",
},
{
ID: "df-txt", // the disk usage of each pool
Command: []string{"ceph", "df"},
Format: "txt",
DefaultTimeout: "30s",
},
{
ID: "osd-df",
Command: []string{"ceph", "osd", "df"},
@@ -112,6 +132,12 @@ var CephCommands = []CephCommand{
Format: "json",
DefaultTimeout: "30s",
},
{
ID: "osd-df-txt",
Command: []string{"ceph", "osd", "df"},
Format: "txt",
DefaultTimeout: "30s",
},
}
type CollectCeph struct {
+25 -27
View File
@@ -91,25 +91,23 @@ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----`,
"validCert": `-----BEGIN CERTIFICATE-----
MIIDejCCAmKgAwIBAgIEAZaq0DANBgkqhkiG9w0BAQsFADAuMRgwFgYDVQQDEw9Q
cm9qZWN0IENvbnRvdXIxEjAQBgNVBAUTCTYxNTkyOTg5MTAeFw0yMzAyMjQwNDI3
MThaFw0yNDAyMjUwNDI3MTZaMBAxDjAMBgNVBAMTBWVudm95MIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqsNmmxb1ICso6Ay25lapcRyvLxAX/5u422uV
eiNn5jseCVXfg1jJr2Symrgou2dgMtIpZoVKT7w0el8sNpD+az5oMOWUNfTGEpYI
5zNAhtiedxCWcX15gfezOZ/DECL7HP8U37JFVdazm0CjvlQWI+8rFGvFQJJFDLYJ
h0fHGfbX6L/ST6cANtkXZyIU6CYFSgniuuDjHmQnQr6CC8lkisJxY5QVS7MZ02RR
nU/dK14ABY+mo/0ZeBKR5si04hr4i18nJJnk4DnHN+jQ/WWWSO1yLqr9kAOj37dA
nRAeKuzkx/VbU8DC/3sh0otcazoWO470D+irOy1is0whDArLNwIDAQABo4G9MIG6
MA4GA1UdDwEB/wQEAwIE8DAdBgNVHQ4EFgQUbAavOY+vIXgc44k8GvLHH6mdzzYw
HwYDVR0jBBgwFoAUb+S3Mu7cbwZiqZaEHTEMyUhLyH4waAYDVR0RBGEwX4IFZW52
b3mCFGVudm95LnByb2plY3Rjb250b3VyghhlbnZveS5wcm9qZWN0Y29udG91ci5z
dmOCJmVudm95LnByb2plY3Rjb250b3VyLnN2Yy5jbHVzdGVyLmxvY2FsMA0GCSqG
SIb3DQEBCwUAA4IBAQBIKpBD1T9tugzJF7lajbdulXTb9qGibwQALqauskX9Sq57
po/R2TjyxywLn4DgM7BAzzu9qfHWf+S4eQjRUHQshPbUEX9CEsSd5tCu8ZHVbBds
6qFagl2+YQ9ng0Xwta9ezvctM3T6Dy9Kkf5OOe9ysMEsBX7s8NFxe68Qku+cExr3
78oERlIoNOlT0cNbFLAlH2svNv1uB4qOThRDha52L+mlUdZfTMYZAwNDJWm52t/M
NCIm5NJ5jAJpcJmoEb+JMP3j0x6wydHDXFtGm3WRggZRcrjasyodSKK6szbf96+9
6syzAwvg9xxNtFxwbhRqqplMEz2sDWaggTrxCQzd
MIIDEjCCAfqgAwIBAgIUWG+wobb7huLDKQ4bUn80QKsbVSQwDQYJKoZIhvcNAQEL
BQAwGDEWMBQGA1UEAwwNRXhhbXBsZVNlcnZlcjAeFw0yNDAyMjYyMjA5MjdaFw0y
OTAyMjQyMjA5MjdaMBgxFjAUBgNVBAMMDUV4YW1wbGVTZXJ2ZXIwggEiMA0GCSqG
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsb9MSNERE7l4b/vxzkRnL6qvkjodbY3yQ
DDCbG29jJ71wSwYoz0v4n/Q/tDaJDBUcSjSPIa+L6Gn1BGLNUD2LFec5H5XlwcDq
A0D8qzvPLMYaIw4p04M/2Wvkqme79yQta8jXaCnPxTkgysno/FuQR+nDMqXoyW01
wMmj8JAYFs9MVPbmP97RqbVHnn7cydzvQvi4+dfBuII9L+TvTQY2o42bbCqCcmov
16m0uXp98j4CFfv/8KhCmQcqS0uyvp+J/iJZzEow+1NP72pozPEPv9JhXsYDb+vH
KxX5k44fYXVYVQHxYQllLjDDRcbz2DJh2DQXMZTiTLE63tC0m2RjAgMBAAGjVDBS
MDEGA1UdEQQqMCiCCGV4YW1wbGUxgghleGFtcGxlMoIIZXhhbXBsZTOCCGV4YW1w
bGU0MB0GA1UdDgQWBBTEkowqyNS1ez5XJ0shro/18UQlqTANBgkqhkiG9w0BAQsF
AAOCAQEANhnxV81NZmt8FcgrcRt73WdKDCE0hQbci65ZkAbcTVOCAs6Rw+aEC04L
0gKJT4Zmx3kR3fUwcDQRhjoXIrhmvP59k/8SN0N+Ua50oEYikaetsxEDr8oikwP2
eHDKU451jZZfcyII2Jx8XjgtiExcNZL3N9ZtSstp3I9n9BSmMdQHDIvPxNeGdJri
l4YGTm+sJLs+c5efSNaEPw1Dr6bhAPamNQwvIspuASJlCTcMCLw2+F3dEolAFUuM
E5wI9498c+P3pvl85UfiQISTu95jOl7YmZOYl8xBpu9yhQ7kjWhVRdVAnhl9Ts9F
3TD68rCMXegJYyg5VbiwVdSPkcw3eQ==
-----END CERTIFICATE-----`,
"nonCert": `-----BEGIN CERTIFICATE-----
Oy1is0whDArLNwIDAQABo4G9MIG6
@@ -248,16 +246,16 @@ func TestCertParser(t *testing.T) {
CertificateChain: []ParsedCertificate{
{
CertName: "tls.crt",
Subject: "CN=envoy",
Subject: "CN=ExampleServer",
SubjectAlternativeNames: []string{
"envoy",
"envoy.projectcontour",
"envoy.projectcontour.svc",
"envoy.projectcontour.svc.cluster.local",
"example1",
"example2",
"example3",
"example4",
},
Issuer: "SERIALNUMBER=615929891,CN=Project Contour",
NotAfter: time.Date(2024, time.February, 25, 4, 27, 16, 0, time.UTC),
NotBefore: time.Date(2023, time.February, 24, 4, 27, 18, 0, time.UTC),
Issuer: "CN=ExampleServer",
NotAfter: time.Date(2029, time.February, 24, 22, 9, 27, 0, time.UTC),
NotBefore: time.Date(2024, time.February, 26, 22, 9, 27, 0, time.UTC),
IsValid: true,
IsCA: false,
},
+2 -2
View File
@@ -506,7 +506,7 @@ func pods(ctx context.Context, client *kubernetes.Clientset, namespaces []string
}
func getPodDisruptionBudgets(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
ok, err := discovery.HasResource(client, "policy.k8s.io/v1", "PodDisruptionBudgets")
ok, err := discovery.HasResource(client, "policy/v1", "PodDisruptionBudgets")
if err != nil {
return nil, map[string]string{"": err.Error()}
}
@@ -801,7 +801,7 @@ func jobs(ctx context.Context, client *kubernetes.Clientset, namespaces []string
}
func cronJobs(ctx context.Context, client *kubernetes.Clientset, namespaces []string) (map[string][]byte, map[string]string) {
ok, err := discovery.HasResource(client, "batch.k8s.io/v1", "CronJobs")
ok, err := discovery.HasResource(client, "batch/v1", "CronJobs")
if err != nil {
return nil, map[string]string{"": err.Error()}
}
+17
View File
@@ -75,6 +75,8 @@ func GetCollector(collector *troubleshootv1beta2.Collect, bundlePath string, nam
return &CollectRun{collector.Run, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.RunPod != nil:
return &CollectRunPod{collector.RunPod, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.RunDaemonSet != nil:
return &CollectRunDaemonSet{collector.RunDaemonSet, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.Exec != nil:
return &CollectExec{collector.Exec, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.Data != nil:
@@ -118,6 +120,12 @@ func GetCollector(collector *troubleshootv1beta2.Collect, bundlePath string, nam
return &CollectHelm{collector.Helm, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.Goldpinger != nil:
return &CollectGoldpinger{collector.Goldpinger, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.Sonobuoy != nil:
return &CollectSonobuoyResults{collector.Sonobuoy, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
case collector.NodeMetrics != nil:
return &CollectNodeMetrics{collector.NodeMetrics, bundlePath, clientConfig, client, ctx, RBACErrors}, true
case collector.DNS != nil:
return &CollectDNS{collector.DNS, bundlePath, namespace, clientConfig, client, ctx, RBACErrors}, true
default:
return nil, false
}
@@ -152,6 +160,9 @@ func getCollectorName(c interface{}) string {
case *CollectRunPod:
collector = "run-pod"
name = v.Collector.CollectorName
case *CollectRunDaemonSet:
collector = "run-daemonset"
name = v.Collector.CollectorName
case *CollectExec:
collector = "exec"
name = v.Collector.CollectorName
@@ -202,6 +213,12 @@ func getCollectorName(c interface{}) string {
collector = "helm"
case *CollectGoldpinger:
collector = "goldpinger"
case *CollectSonobuoyResults:
collector = "sonobuoy"
case *CollectNodeMetrics:
collector = "node-metrics"
case *CollectDNS:
collector = "dns"
default:
collector = "<none>"
}
+273
View File
@@ -0,0 +1,273 @@
package collect
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"path/filepath"
"strings"
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
const (
dnsUtilsImage = "registry.k8s.io/e2e-test-images/jessie-dnsutils:1.3"
)
type CollectDNS struct {
Collector *troubleshootv1beta2.DNS
BundlePath string
Namespace string
ClientConfig *rest.Config
Client kubernetes.Interface
Context context.Context
RBACErrors
}
func (c *CollectDNS) Title() string {
return getCollectorName(c)
}
func (c *CollectDNS) IsExcluded() (bool, error) {
return isExcluded(c.Collector.Exclude)
}
func (c *CollectDNS) Collect(progressChan chan<- interface{}) (CollectorResult, error) {
ctx, cancel := context.WithTimeout(c.Context, time.Duration(60*time.Second))
defer cancel()
sb := strings.Builder{}
// get kubernetes Cluster IP
clusterIP, err := getKubernetesClusterIP(c.Client, ctx)
if err == nil {
sb.WriteString(fmt.Sprintf("=== Kubernetes Cluster IP from API Server: %s\n", clusterIP))
} else {
sb.WriteString(fmt.Sprintf("=== Failed to detect Kubernetes Cluster IP: %v\n", err))
}
// run a pod and perform DNS lookup
podLog, err := troubleshootDNSFromPod(c.Client, ctx)
if err == nil {
sb.WriteString(fmt.Sprintf("=== Test DNS resolution in pod %s: \n", dnsUtilsImage))
sb.WriteString(podLog)
} else {
sb.WriteString(fmt.Sprintf("=== Failed to run commands from pod: %v\n", err))
}
// is DNS pods running?
sb.WriteString(fmt.Sprintf("=== Running kube-dns pods: %s\n", getRunningKubeDNSPodNames(c.Client, ctx)))
// is DNS service up?
sb.WriteString(fmt.Sprintf("=== Running kube-dns service: %s\n", getKubeDNSServiceClusterIP(c.Client, ctx)))
// are DNS endpoints exposed?
sb.WriteString(fmt.Sprintf("=== kube-dns endpoints: %s\n", getKubeDNSEndpoints(c.Client, ctx)))
// get DNS server config
coreDNSConfig, err := getCoreDNSConfig(c.Client, ctx)
if err == nil {
sb.WriteString("=== CoreDNS config: \n")
sb.WriteString(coreDNSConfig)
}
kubeDNSConfig, err := getKubeDNSConfig(c.Client, ctx)
if err == nil {
sb.WriteString("=== KubeDNS config: \n")
sb.WriteString(kubeDNSConfig)
}
data := sb.String()
output := NewResult()
output.SaveResult(c.BundlePath, filepath.Join("dns", c.Collector.CollectorName), bytes.NewBuffer([]byte(data)))
return output, nil
}
func getKubernetesClusterIP(client kubernetes.Interface, ctx context.Context) (string, error) {
service, err := client.CoreV1().Services("default").Get(ctx, "kubernetes", metav1.GetOptions{})
if err != nil {
klog.V(2).Infof("Failed to detect Kubernetes Cluster IP: %v", err)
return "", err
}
return service.Spec.ClusterIP, nil
}
func troubleshootDNSFromPod(client kubernetes.Interface, ctx context.Context) (string, error) {
namespace := "default"
command := []string{"/bin/sh", "-c", `
set -x
cat /etc/resolv.conf
nslookup -debug kubernetes
exit 0
`}
// TODO: image pull secret?
podLabels := map[string]string{
"troubleshoot-role": "dns-collector",
}
pod := &corev1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "troubleshoot-dns-",
Namespace: namespace,
Labels: podLabels,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "troubleshoot-dns",
Image: dnsUtilsImage,
Command: command,
},
},
RestartPolicy: corev1.RestartPolicyNever,
},
}
created, err := client.CoreV1().Pods(namespace).Create(ctx, pod, metav1.CreateOptions{})
if err != nil {
return "", errors.Wrap(err, "failed to run troubleshoot DNS pod")
}
klog.V(2).Infof("Pod with prefix %s has been created", created.GenerateName)
defer func() {
if created == nil {
return
}
err := client.CoreV1().Pods(namespace).Delete(ctx, created.Name, metav1.DeleteOptions{})
if err != nil {
klog.Errorf("Failed to delete troubleshoot DNS pod %s: %v", created.Name, err)
}
klog.V(2).Infof("Deleted pod %s", created.Name)
}()
// wait for pod to be completed
watcher, err := client.CoreV1().Pods(namespace).Watch(ctx, metav1.ListOptions{
LabelSelector: "troubleshoot-role=dns-collector",
})
if err != nil {
return "", errors.Wrap(err, "failed to watch pod")
}
defer func() {
if watcher != nil {
watcher.Stop()
}
}()
for event := range watcher.ResultChan() {
pod, ok := event.Object.(*corev1.Pod)
if !ok {
continue
}
if pod.Status.Phase == corev1.PodSucceeded {
break
}
if pod.Status.Phase == corev1.PodFailed {
return "", errors.New("troubleshoot DNS pod failed")
}
}
// get pod logs
podLogOpts := corev1.PodLogOptions{}
req := client.CoreV1().Pods(namespace).GetLogs(created.Name, &podLogOpts)
podLogs, err := req.Stream(ctx)
if err != nil {
return "", errors.Wrap(err, "failed to get pod logs")
}
defer podLogs.Close()
bytes, err := io.ReadAll(podLogs)
if err != nil {
return "", errors.Wrap(err, "failed to read troubleshoot DNS pod logs")
}
return string(bytes), nil
}
func getCoreDNSConfig(client kubernetes.Interface, ctx context.Context) (string, error) {
configMap, err := client.CoreV1().ConfigMaps("kube-system").Get(ctx, "coredns", metav1.GetOptions{})
if err != nil {
klog.V(2).Infof("Failed to detect CoreDNS config: %v", err)
return "", err
}
return configMap.Data["Corefile"], nil
}
func getKubeDNSConfig(client kubernetes.Interface, ctx context.Context) (string, error) {
configMap, err := client.CoreV1().ConfigMaps("kube-system").Get(ctx, "kube-dns", metav1.GetOptions{})
if err != nil {
klog.V(2).Infof("Failed to detect KubeDNS config: %v", err)
return "", err
}
if configMap.Data == nil {
return "", nil
}
dataBytes, err := json.Marshal(configMap.Data)
if err != nil {
return "", err
}
return string(dataBytes), nil
}
func getRunningKubeDNSPodNames(client kubernetes.Interface, ctx context.Context) string {
pods, err := client.CoreV1().Pods("kube-system").List(ctx, metav1.ListOptions{
LabelSelector: "k8s-app=kube-dns",
})
if err != nil {
klog.V(2).Infof("failed to list kube-dns pods: %v", err)
return ""
}
var podNames []string
for _, pod := range pods.Items {
if pod.Status.Phase == corev1.PodRunning {
podNames = append(podNames, pod.Name)
}
}
return strings.Join(podNames, ", ")
}
func getKubeDNSServiceClusterIP(client kubernetes.Interface, ctx context.Context) string {
service, err := client.CoreV1().Services("kube-system").Get(ctx, "kube-dns", metav1.GetOptions{})
if err != nil {
klog.V(2).Infof("failed to get kube-dns service: %v", err)
return ""
}
return service.Spec.ClusterIP
}
func getKubeDNSEndpoints(client kubernetes.Interface, ctx context.Context) string {
endpoints, err := client.CoreV1().Endpoints("kube-system").Get(ctx, "kube-dns", metav1.GetOptions{})
if err != nil {
klog.V(2).Infof("failed to get kube-dns endpoints: %v", err)
return ""
}
var endpointStrings []string
for _, subset := range endpoints.Subsets {
for _, address := range subset.Addresses {
if len(subset.Ports) > 0 {
endpointStrings = append(endpointStrings, fmt.Sprintf("%s:%d", address.IP, subset.Ports[0].Port))
}
}
}
return strings.Join(endpointStrings, ", ")
}
+41
View File
@@ -0,0 +1,41 @@
package collect
import (
"context"
"testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
func TestGetKubernetesClusterIP(t *testing.T) {
k8sSvcIp := "10.0.0.1"
client := fake.NewSimpleClientset()
service := &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: "kubernetes",
Namespace: "default",
},
Spec: corev1.ServiceSpec{
ClusterIP: k8sSvcIp,
},
}
// Add the service to the fake clientset
_, err := client.CoreV1().Services("default").Create(context.TODO(), service, metav1.CreateOptions{})
if err != nil {
t.Fatalf("error injecting service into fake clientset: %v", err)
}
// Call the function
clusterIP, err := getKubernetesClusterIP(client, context.TODO())
if err != nil {
t.Fatalf("error getting cluster IP: %v", err)
}
// Check the result
if clusterIP != k8sSvcIp {
t.Errorf("expected %s, got %s", k8sSvcIp, clusterIP)
}
}
+70 -22
View File
@@ -5,12 +5,11 @@ import (
"context"
"encoding/json"
"fmt"
"log"
"strconv"
"strings"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"helm.sh/helm/v3/pkg/action"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
@@ -39,10 +38,11 @@ type ReleaseInfo struct {
// Helm release version information struct
type VersionInfo struct {
Revision string `json:"revision"`
Date string `json:"date"`
Status string `json:"status"`
IsPending bool `json:"isPending,omitempty"`
Revision string `json:"revision"`
Date string `json:"date"`
Status string `json:"status"`
IsPending bool `json:"isPending,omitempty"`
Values map[string]interface{} `json:"values,omitempty"`
}
func (c *CollectHelm) Title() string {
@@ -57,9 +57,15 @@ func (c *CollectHelm) Collect(progressChan chan<- interface{}) (CollectorResult,
output := NewResult()
releaseInfos, err := helmReleaseHistoryCollector(c.Collector.ReleaseName, c.Collector.Namespace)
releaseInfos, err := helmReleaseHistoryCollector(c.Collector.ReleaseName, c.Collector.Namespace, c.Collector.CollectValues)
if err != nil {
return nil, errors.Wrap(err, "failed to get Helm release history")
errsToMarhsal := []string{}
for _, e := range err {
errsToMarhsal = append(errsToMarhsal, e.Error())
}
output.SaveResult(c.BundlePath, "helm/errors.json", marshalErrors(errsToMarhsal))
klog.Errorf("error collecting helm release info: %v", err)
return output, nil
}
releaseInfoByNamespace := helmReleaseInfoByNamespaces(releaseInfos)
@@ -72,22 +78,23 @@ func (c *CollectHelm) Collect(progressChan chan<- interface{}) (CollectorResult,
}
filePath := fmt.Sprintf("helm/%s.json", namespace)
err := output.SaveResult(c.BundlePath, filePath, bytes.NewBuffer(helmHistoryJson))
if err != nil {
return nil, err
if c.Collector.ReleaseName != "" {
filePath = fmt.Sprintf("helm/%s/%s.json", namespace, c.Collector.ReleaseName)
}
output.SaveResult(c.BundlePath, filePath, bytes.NewBuffer(helmHistoryJson))
}
return output, nil
}
func helmReleaseHistoryCollector(releaseName string, namespace string) ([]ReleaseInfo, error) {
func helmReleaseHistoryCollector(releaseName string, namespace string, collectValues bool) ([]ReleaseInfo, []error) {
var results []ReleaseInfo
error_list := []error{}
actionConfig := new(action.Configuration)
if err := actionConfig.Init(nil, namespace, "", klog.V(2).Infof); err != nil {
return nil, errors.Wrap(err, "failed to initialize Helm action config")
return nil, []error{err}
}
// If releaseName is specified, get the history of that release
@@ -95,7 +102,11 @@ func helmReleaseHistoryCollector(releaseName string, namespace string) ([]Releas
getAction := action.NewGet(actionConfig)
r, err := getAction.Run(releaseName)
if err != nil {
return nil, errors.Wrapf(err, "failed to get Helm release %s", releaseName)
return nil, []error{err}
}
versionInfo, err := getVersionInfo(actionConfig, r.Name, r.Namespace, collectValues)
if err != nil {
return nil, []error{err}
}
results = append(results, ReleaseInfo{
ReleaseName: r.Name,
@@ -103,7 +114,7 @@ func helmReleaseHistoryCollector(releaseName string, namespace string) ([]Releas
ChartVersion: r.Chart.Metadata.Version,
AppVersion: r.Chart.Metadata.AppVersion,
Namespace: r.Namespace,
VersionInfo: getVersionInfo(actionConfig, releaseName),
VersionInfo: versionInfo,
})
return results, nil
}
@@ -114,39 +125,64 @@ func helmReleaseHistoryCollector(releaseName string, namespace string) ([]Releas
listAction := action.NewList(actionConfig)
releases, err := listAction.Run()
if err != nil {
log.Fatalf("Failed to list Helm releases: %v", err)
return nil, []error{err}
}
for _, r := range releases {
versionInfo, err := getVersionInfo(actionConfig, r.Name, r.Namespace, collectValues)
if err != nil {
error_list = append(error_list, err)
}
results = append(results, ReleaseInfo{
ReleaseName: r.Name,
Chart: r.Chart.Metadata.Name,
ChartVersion: r.Chart.Metadata.Version,
AppVersion: r.Chart.Metadata.AppVersion,
Namespace: r.Namespace,
VersionInfo: getVersionInfo(actionConfig, r.Name),
VersionInfo: versionInfo,
})
}
if len(error_list) > 0 {
return nil, error_list
}
return results, nil
}
func getVersionInfo(actionConfig *action.Configuration, releaseName string) []VersionInfo {
func getVersionInfo(actionConfig *action.Configuration, releaseName, namespace string, collectValues bool) ([]VersionInfo, error) {
versionCollect := []VersionInfo{}
error_list := []error{}
history, _ := action.NewHistory(actionConfig).Run(releaseName)
history, err := action.NewHistory(actionConfig).Run(releaseName)
if err != nil {
return nil, err
}
for _, release := range history {
values := map[string]interface{}{}
if collectValues {
values, err = getHelmValues(releaseName, namespace, release.Version)
if err != nil {
error_list = append(error_list, err)
}
}
versionCollect = append(versionCollect, VersionInfo{
Revision: strconv.Itoa(release.Version),
Date: release.Info.LastDeployed.String(),
Status: release.Info.Status.String(),
IsPending: release.Info.Status.IsPending(),
Values: values,
})
}
return versionCollect
if len(error_list) > 0 {
errs := []string{}
for _, e := range error_list {
errs = append(errs, e.Error())
}
return nil, errors.New(strings.Join(errs, "\n"))
}
return versionCollect, nil
}
func helmReleaseInfoByNamespaces(releaseInfo []ReleaseInfo) map[string][]ReleaseInfo {
@@ -158,3 +194,15 @@ func helmReleaseInfoByNamespaces(releaseInfo []ReleaseInfo) map[string][]Release
return releaseInfoByNamespace
}
func getHelmValues(releaseName, namespace string, revision int) (map[string]interface{}, error) {
actionConfig := new(action.Configuration)
if err := actionConfig.Init(nil, namespace, "", klog.V(2).Infof); err != nil {
return nil, err
}
getAction := action.NewGetValues(actionConfig)
getAction.AllValues = true
getAction.Version = revision
helmValues, err := getAction.Run(releaseName)
return helmValues, err
}
@@ -24,16 +24,16 @@ func Test_HostCertParser(t *testing.T) {
CertificatePath: path,
CertificateChain: []ParsedCertificate{
{
Subject: "CN=envoy",
Subject: "CN=ExampleServer",
SubjectAlternativeNames: []string{
"envoy",
"envoy.projectcontour",
"envoy.projectcontour.svc",
"envoy.projectcontour.svc.cluster.local",
"example1",
"example2",
"example3",
"example4",
},
Issuer: "SERIALNUMBER=615929891,CN=Project Contour",
NotAfter: time.Date(2024, time.February, 25, 4, 27, 16, 0, time.UTC),
NotBefore: time.Date(2023, time.February, 24, 4, 27, 18, 0, time.UTC),
Issuer: "CN=ExampleServer",
NotAfter: time.Date(2029, time.February, 24, 22, 9, 27, 0, time.UTC),
NotBefore: time.Date(2024, time.February, 26, 22, 9, 27, 0, time.UTC),
IsValid: true,
IsCA: false,
},
+1 -1
View File
@@ -60,7 +60,7 @@ func isValidLoadBalancerAddress(address string) bool {
// Check for isValidIP
test := validation.IsValidIP(hostAddress)
test := validation.IsValidIP(nil, hostAddress)
return len(test) == 0
}
+28 -1
View File
@@ -2,12 +2,14 @@ package collect
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
@@ -49,7 +51,29 @@ func (c *CollectHostRun) Collect(progressChan chan<- interface{}) (map[string][]
collectorName = "run-host"
}
cmd := exec.Command(c.attemptToConvertCmdToAbsPath(), runHostCollector.Args...)
var (
timeout time.Duration
cmd *exec.Cmd
errInvalidDuration error
)
ctx := context.Background()
cmdPath := c.attemptToConvertCmdToAbsPath()
if runHostCollector.Timeout != "" {
timeout, errInvalidDuration = time.ParseDuration(runHostCollector.Timeout)
if errInvalidDuration != nil {
return nil, errors.Wrapf(errInvalidDuration, "failed to parse timeout %q", runHostCollector.Timeout)
}
}
if timeout <= time.Duration(0) {
cmd = exec.Command(cmdPath, runHostCollector.Args...)
} else {
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
cmd = exec.CommandContext(timeoutCtx, cmdPath, runHostCollector.Args...)
}
klog.V(2).Infof("Run host collector command: %q", cmd.String())
runInfo := &HostRunInfo{
@@ -118,6 +142,9 @@ func (c *CollectHostRun) Collect(progressChan chan<- interface{}) (map[string][]
if werr, ok := err.(*exec.ExitError); ok {
runInfo.ExitCode = strings.TrimPrefix(werr.Error(), "exit status ")
runInfo.Error = stderr.String()
} else if err == context.DeadlineExceeded {
runInfo.ExitCode = "-1"
runInfo.Error = fmt.Sprintf("command timed out after %s", timeout.String())
} else {
return nil, errors.Wrap(err, "failed to run")
}
+74
View File
@@ -158,3 +158,77 @@ func TestCollectHostRun_Collect(t *testing.T) {
}
}
}
func TestCollectHostRunCollectWithTimeout(t *testing.T) {
tests := []struct {
name string
collector *CollectHostRun
wantError bool
}{
{
name: "no timeout",
collector: &CollectHostRun{
hostCollector: &troubleshootv1beta2.HostRun{
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
CollectorName: "no timeout",
},
Command: "echo",
Args: []string{"1"},
},
},
wantError: false,
},
{
name: "invalid timeout",
collector: &CollectHostRun{
hostCollector: &troubleshootv1beta2.HostRun{
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
CollectorName: "negative timeout",
},
Command: "echo",
Args: []string{"1"},
Timeout: "thisistheway",
},
},
wantError: true,
},
{
name: "negative timeout",
collector: &CollectHostRun{
hostCollector: &troubleshootv1beta2.HostRun{
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
CollectorName: "negative timeout",
},
Command: "echo",
Args: []string{"1"},
Timeout: "-10s",
},
},
wantError: false,
},
{
name: "endless command with timeout",
collector: &CollectHostRun{
hostCollector: &troubleshootv1beta2.HostRun{
HostCollectorMeta: troubleshootv1beta2.HostCollectorMeta{
CollectorName: "endless command",
},
Command: "ping",
Args: []string{"google.com"},
Timeout: "200ms",
},
},
wantError: false,
},
}
for _, test := range tests {
got, err := test.collector.Collect(nil)
if test.wantError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.NotNil(t, got)
}
}
}
+9
View File
@@ -14,12 +14,14 @@ import (
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
type HTTPResponse struct {
Status int `json:"status"`
Body string `json:"body"`
Headers map[string]string `json:"headers"`
RawJSON json.RawMessage `json:"raw_json,omitempty"`
}
type HTTPError struct {
@@ -127,10 +129,17 @@ func responseToOutput(response *http.Response, err error) ([]byte, error) {
headers[k] = strings.Join(v, ",")
}
var rawJSON json.RawMessage
if err := json.Unmarshal(body, &rawJSON); err != nil {
klog.Infof("failed to unmarshal response body as JSON: %v", err)
rawJSON = json.RawMessage{}
}
output["response"] = HTTPResponse{
Status: response.StatusCode,
Body: string(body),
Headers: headers,
RawJSON: rawJSON,
}
}
+63
View File
@@ -1,8 +1,10 @@
package collect
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
@@ -376,3 +378,64 @@ func Test_parseTimeout(t *testing.T) {
})
}
}
func Test_responseToOutput(t *testing.T) {
tests := []struct {
name string
response *http.Response
err error
want []byte
wantErr bool
}{
{
name: "valid JSON response",
response: &http.Response{
Body: io.NopCloser(bytes.NewBufferString(`{"ok": false, "error": "invalid_auth"}`)),
Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}},
StatusCode: http.StatusOK,
},
err: nil,
want: []byte(`
{
"response":
{
"status":200,
"body":"{\"ok\": false, \"error\": \"invalid_auth\"}",
"headers":{"Content-Type":"application/json; charset=utf-8"},
"raw_json":{"ok":false,"error":"invalid_auth"}
}
}`),
wantErr: false,
},
{
name: "invalid JSON response",
response: &http.Response{
Body: io.NopCloser(bytes.NewBufferString(`foobar`)),
Header: http.Header{"Content-Type": []string{"text/html; charset=utf-8"}},
StatusCode: http.StatusOK,
},
err: nil,
want: []byte(`
{
"response":
{
"status":200,
"body":"foobar",
"headers":{"Content-Type":"text/html; charset=utf-8"}
}
}`),
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := responseToOutput(tt.response, tt.err)
if tt.wantErr {
assert.Error(t, err)
return
}
assert.NoError(t, err)
assert.JSONEq(t, string(got), string(tt.want))
})
}
}
+102
View File
@@ -0,0 +1,102 @@
package collect
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
const (
summaryUrlTemplate = "/api/v1/nodes/%s/proxy/stats/summary"
)
type CollectNodeMetrics struct {
Collector *troubleshootv1beta2.NodeMetrics
BundlePath string
ClientConfig *rest.Config
Client kubernetes.Interface
Context context.Context
RBACErrors
}
func (c *CollectNodeMetrics) Title() string {
return getCollectorName(c)
}
func (c *CollectNodeMetrics) IsExcluded() (bool, error) {
return isExcluded(c.Collector.Exclude)
}
func (c *CollectNodeMetrics) Collect(progressChan chan<- interface{}) (CollectorResult, error) {
output := NewResult()
nodesMap := c.constructNodesMap()
if len(nodesMap) == 0 {
klog.V(2).Info("no nodes found to collect metrics for")
return output, nil
}
nodeNames := make([]string, 0, len(nodesMap))
for nodeName := range nodesMap {
nodeNames = append(nodeNames, nodeName)
}
klog.V(2).Infof("collecting node metrics for [%s] nodes", strings.Join(nodeNames, ", "))
for nodeName, endpoint := range nodesMap {
// Equivalent to `kubectl get --raw "/api/v1/nodes/<nodeName>/proxy/stats/summary"`
klog.V(2).Infof("querying: %+v\n", endpoint)
response, err := c.Client.CoreV1().RESTClient().Get().AbsPath(endpoint).DoRaw(c.Context)
if err != nil {
return output, errors.Wrapf(err, "could not query endpoint %s", endpoint)
}
err = output.SaveResult(c.BundlePath, fmt.Sprintf("node-metrics/%s.json", nodeName), bytes.NewBuffer(response))
if err != nil {
klog.Errorf("failed to save node metrics for %s: %v", nodeName, err)
}
}
return output, nil
}
func (c *CollectNodeMetrics) constructNodesMap() map[string]string {
nodesMap := map[string]string{}
if c.Collector.NodeNames == nil && c.Collector.Selector == nil {
// If no node names or selectors are provided, collect all nodes
nodes, err := c.Client.CoreV1().Nodes().List(c.Context, metav1.ListOptions{})
if err != nil {
klog.Errorf("failed to list nodes: %v", err)
}
for _, node := range nodes.Items {
nodesMap[node.Name] = fmt.Sprintf(summaryUrlTemplate, node.Name)
}
return nodesMap
}
for _, nodeName := range c.Collector.NodeNames {
nodesMap[nodeName] = fmt.Sprintf(summaryUrlTemplate, nodeName)
}
// Find nodes by label selector
if c.Collector.Selector != nil {
nodes, err := c.Client.CoreV1().Nodes().List(c.Context, metav1.ListOptions{
LabelSelector: strings.Join(c.Collector.Selector, ","),
})
if err != nil {
klog.Errorf("failed to list nodes by label selector: %v", err)
}
for _, node := range nodes.Items {
nodesMap[node.Name] = fmt.Sprintf(summaryUrlTemplate, node.Name)
}
}
return nodesMap
}
+97
View File
@@ -0,0 +1,97 @@
package collect
import (
"context"
"testing"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
testclient "k8s.io/client-go/kubernetes/fake"
)
func TestCollectNodeMetrics_constructNodesMap(t *testing.T) {
tests := []struct {
name string
objectMetas []metav1.ObjectMeta
collector troubleshootv1beta2.NodeMetrics
want map[string]string
}{
{
name: "default collector no nodes",
want: map[string]string{},
},
{
name: "default collector one node",
objectMetas: []metav1.ObjectMeta{
{
Name: "node1",
},
},
want: map[string]string{
"node1": "/api/v1/nodes/node1/proxy/stats/summary",
},
},
{
name: "collector with node list picking one node",
objectMetas: []metav1.ObjectMeta{
{
Name: "node1",
},
{
Name: "node2",
},
},
collector: troubleshootv1beta2.NodeMetrics{
NodeNames: []string{"node2"},
},
want: map[string]string{
"node2": "/api/v1/nodes/node2/proxy/stats/summary",
},
},
{
name: "collector with selector picking one node",
objectMetas: []metav1.ObjectMeta{
{
Name: "node1",
Labels: map[string]string{
"hostname": "node1.example.com",
},
},
{
Name: "node2",
},
},
collector: troubleshootv1beta2.NodeMetrics{
Selector: []string{"hostname=node1.example.com"},
},
want: map[string]string{
"node1": "/api/v1/nodes/node1/proxy/stats/summary",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
client := testclient.NewSimpleClientset()
ctx := context.Background()
collector := tt.collector
c := &CollectNodeMetrics{
Collector: &collector,
Client: client,
Context: ctx,
}
for _, objectMeta := range tt.objectMetas {
_, err := client.CoreV1().Nodes().Create(ctx, &v1.Node{
ObjectMeta: objectMeta,
}, metav1.CreateOptions{})
require.NoError(t, err)
}
got := c.constructNodesMap()
assert.Equalf(t, tt.want, got, "constructNodesMap() = %v, want %v", got, tt.want)
})
}
}
+1 -1
View File
@@ -49,7 +49,7 @@ func (c *CollectMssql) Collect(progressChan chan<- interface{}) (CollectorResult
db, err := sql.Open("mssql", c.Collector.URI)
if err != nil {
klog.V(2).Infof("Failed to connect to %q MSSQL Database: %w", connUrl.Host, err)
klog.V(2).Infof("Failed to connect to %q MSSQL Database: %v", connUrl.Host, err)
databaseConnection.Error = err.Error()
} else {
defer db.Close()
+2 -2
View File
@@ -71,9 +71,9 @@ func RedactResult(bundlePath string, input CollectorResult, additionalRedactors
errorCh <- errors.Wrap(err, "failed to get relative path")
return
}
klog.V(2).Infof("Redacting %s (symlink => %s)\n", file, symlink)
klog.V(4).Infof("Redacting %s (symlink => %s)\n", file, symlink)
} else {
klog.V(2).Infof("Redacting %s\n", file)
klog.V(4).Infof("Redacting %s\n", file)
}
r, err := input.GetReader(bundlePath, file)
if err != nil {
+6 -6
View File
@@ -25,7 +25,7 @@ func NewResult() CollectorResult {
// is empty, no symlink is created. The relativeLinkPath is always saved in the result map.
func (r CollectorResult) SymLinkResult(bundlePath, relativeLinkPath, relativeFilePath string) error {
// We should have saved the result this symlink is pointing to prior to creating it
klog.V(2).Info("Creating symlink ", relativeLinkPath, " -> ", relativeFilePath)
klog.V(4).Info("Creating symlink ", relativeLinkPath, " -> ", relativeFilePath)
data, ok := r[relativeFilePath]
if !ok {
return errors.Errorf("cannot create symlink, result in %q not found", relativeFilePath)
@@ -75,7 +75,7 @@ func (r CollectorResult) SymLinkResult(bundlePath, relativeLinkPath, relativeFil
return errors.Wrap(err, "failed to create symlink")
}
klog.V(2).Infof("Added %q symlink of %q in bundle output", relativeLinkPath, relativeFilePath)
klog.V(4).Infof("Added %q symlink of %q in bundle output", relativeLinkPath, relativeFilePath)
// store the file name referencing the symlink to have archived
r[relativeLinkPath] = nil
@@ -105,7 +105,7 @@ func (r CollectorResult) SaveResult(bundlePath string, relativePath string, read
return errors.Wrap(err, "failed to read data")
}
// Memory only bundle
klog.V(2).Infof("Added %q to bundle output", relativePath)
klog.V(4).Infof("Added %q to bundle output", relativePath)
r[relativePath] = data
return nil
}
@@ -135,7 +135,7 @@ func (r CollectorResult) SaveResult(bundlePath string, relativePath string, read
return errors.Wrap(err, "failed to stat file")
}
klog.V(2).Infof("Added %q (%d KB) to bundle output", relativePath, fileInfo.Size()/(1024))
klog.V(4).Infof("Added %q (%d KB) to bundle output", relativePath, fileInfo.Size()/(1024))
return nil
}
@@ -340,7 +340,7 @@ func (r CollectorResult) ArchiveSupportBundle(bundlePath string, outputFilename
if fileMode.Type() == os.ModeSymlink {
// Don't copy the symlink, just write the header which
// will create a symlink in the tarball
klog.V(2).Infof("Added %q symlink to bundle archive", hdr.Linkname)
klog.V(4).Infof("Added %q symlink to bundle archive", hdr.Linkname)
return nil
}
@@ -354,7 +354,7 @@ func (r CollectorResult) ArchiveSupportBundle(bundlePath string, outputFilename
if err != nil {
return errors.Wrap(err, "failed to copy file into archive")
}
klog.V(2).Infof("Added %q file to bundle archive", hdr.Name)
klog.V(4).Infof("Added %q file to bundle archive", hdr.Name)
return nil
}()
+294
View File
@@ -0,0 +1,294 @@
package collect
import (
"bytes"
"context"
"fmt"
"io"
"path/filepath"
"strings"
"sync"
"time"
"github.com/pkg/errors"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/rest"
"k8s.io/klog/v2"
)
const (
defaultTimeout = time.Duration(60 * time.Second)
)
type CollectRunDaemonSet struct {
Collector *troubleshootv1beta2.RunDaemonSet
BundlePath string
Namespace string
ClientConfig *rest.Config
Client kubernetes.Interface
Context context.Context
RBACErrors
}
func (c *CollectRunDaemonSet) Title() string {
return getCollectorName(c)
}
func (c *CollectRunDaemonSet) IsExcluded() (bool, error) {
return isExcluded(c.Collector.Exclude)
}
func (c *CollectRunDaemonSet) Collect(progressChan chan<- interface{}) (CollectorResult, error) {
ctx := context.Background()
client, err := kubernetes.NewForConfig(c.ClientConfig)
if err != nil {
return nil, errors.Wrap(err, "failed to create client from config")
}
// create DaemonSet Spec
dsSpec, err := createDaemonSetSpec(c.Collector)
if err != nil {
return nil, errors.Wrap(err, "failed to create DaemonSet spec")
}
// create ImagePullSecret
var secretName string
if c.Collector.ImagePullSecret != nil && c.Collector.ImagePullSecret.Data != nil {
secretName, err = createSecret(ctx, client, dsSpec.ObjectMeta.Namespace, c.Collector.ImagePullSecret)
if err != nil {
return nil, errors.Wrap(err, "failed to create ImagePullSecret")
}
dsSpec.Spec.Template.Spec.ImagePullSecrets = append(dsSpec.Spec.Template.Spec.ImagePullSecrets, corev1.LocalObjectReference{Name: secretName})
}
// run DaemonSet
ds, err := client.AppsV1().DaemonSets(dsSpec.ObjectMeta.Namespace).Create(ctx, dsSpec, metav1.CreateOptions{})
klog.V(2).Infof("DaemonSet %s has been created", ds.Name)
if err != nil {
return nil, errors.Wrap(err, "failed to create DaemonSet")
}
defer func() {
// delete DaemonSet
err := client.AppsV1().DaemonSets(ds.ObjectMeta.Namespace).Delete(ctx, ds.ObjectMeta.Name, metav1.DeleteOptions{})
if err != nil {
klog.Errorf("Failed to delete DaemonSet %s: %v", ds.Name, err)
}
// delete ImagePullSecret
if secretName != "" {
err := client.CoreV1().Secrets(ds.ObjectMeta.Namespace).Delete(ctx, secretName, metav1.DeleteOptions{})
if err != nil {
klog.Errorf("Failed to delete Secret %s: %v", secretName, err)
}
}
}()
// set custom timeout if any
var (
timeout time.Duration
errInvalidDuration error
)
if c.Collector.Timeout != "" {
timeout, errInvalidDuration = time.ParseDuration(c.Collector.Timeout)
if errInvalidDuration != nil {
return nil, errors.Wrapf(errInvalidDuration, "failed to parse timeout %q", c.Collector.Timeout)
}
}
if timeout <= time.Duration(0) {
timeout = defaultTimeout
}
timeoutCtx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
// block till DaemonSet has right number of scheduled Pods
err = waitForDaemonSetPods(timeoutCtx, client, ds)
if err != nil {
return nil, errors.Wrap(err, "failed to wait for DaemonSet pods")
}
klog.V(2).Infof("DaemonSet %s has desired number of pods", ds.Name)
// get all Pods in DaemonSet
pods, err := client.CoreV1().Pods(ds.ObjectMeta.Namespace).List(ctx, metav1.ListOptions{
LabelSelector: getLabelSelector(ds),
})
if err != nil {
return nil, errors.Wrap(err, "failed to list pods")
}
results := NewResult()
// collect logs from all Pods
// or save error message if failed to get logs
wg := &sync.WaitGroup{}
mtx := &sync.Mutex{}
for _, pod := range pods.Items {
wg.Add(1)
go func(pod corev1.Pod) {
defer wg.Done()
select {
case <-timeoutCtx.Done():
klog.Errorf("Timeout reached while waiting for pod %s", pod.Name)
return
default:
}
var logs []byte
nodeName, err := getPodNodeAtCompletion(timeoutCtx, client.CoreV1(), pod)
if err != nil {
nodeName = fmt.Sprintf("unknown-node-%s", pod.Name)
errString := fmt.Sprintf("Failed to get node name/wait for pod %s to complete: %v", pod.Name, err)
klog.Error(errString)
logs = []byte(errString)
} else {
logs, err = getPodLog(timeoutCtx, client.CoreV1(), pod)
if err != nil {
errString := fmt.Sprintf("Failed to get log from pod %s: %v", pod.Name, err)
klog.Error(errString)
logs = []byte(errString)
}
}
mtx.Lock()
defer mtx.Unlock()
results[nodeName] = logs
klog.V(2).Infof("Collected logs for pod %s", pod.Name)
}(pod)
}
wg.Wait()
output := NewResult()
for k, v := range results {
filename := k + ".log"
err := output.SaveResult(c.BundlePath, filepath.Join(c.Collector.Name, filename), bytes.NewBuffer(v))
if err != nil {
return nil, err
}
}
return output, nil
}
func createDaemonSetSpec(c *troubleshootv1beta2.RunDaemonSet) (*appsv1.DaemonSet, error) {
ds := &appsv1.DaemonSet{}
labels := make(map[string]string)
labels["troubleshoot-role"] = "run-daemonset-collector"
namespace := "default"
if c.Namespace != "" {
namespace = c.Namespace
}
ds.ObjectMeta = metav1.ObjectMeta{
GenerateName: fmt.Sprintf("run-daemonset-%s-", c.Name),
Namespace: namespace,
Labels: labels,
}
ds.Spec = appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: labels,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Namespace: namespace,
Labels: labels,
},
Spec: c.PodSpec,
},
}
return ds, nil
}
func getLabelSelector(ds *appsv1.DaemonSet) string {
labelSelector := ""
for k, v := range ds.Spec.Template.ObjectMeta.Labels {
labelSelector += k + "=" + v + ","
}
return strings.TrimSuffix(labelSelector, ",")
}
func getPodLog(ctx context.Context, client v1.CoreV1Interface, pod corev1.Pod) ([]byte, error) {
podLogOpts := corev1.PodLogOptions{
Container: pod.Spec.Containers[0].Name,
}
req := client.Pods(pod.Namespace).GetLogs(pod.Name, &podLogOpts)
logs, err := req.Stream(ctx)
if err != nil {
return nil, errors.Wrap(err, "failed to get log stream")
}
defer logs.Close()
return io.ReadAll(logs)
}
// getPodNodeAtCompletion waits for the Pod to complete and returns the node name
func getPodNodeAtCompletion(ctx context.Context, client v1.CoreV1Interface, pod corev1.Pod) (string, error) {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return "", ctx.Err()
case <-ticker.C:
pod, err := client.Pods(pod.Namespace).Get(ctx, pod.Name, metav1.GetOptions{})
if err != nil {
return "", errors.Wrap(err, "failed to get pod")
}
if pod.Status.Phase == corev1.PodFailed || pod.Status.Phase == corev1.PodSucceeded {
return pod.Spec.NodeName, nil
}
// we assume a container restart means the Pod has completed before
if len(pod.Status.ContainerStatuses) > 0 && pod.Status.ContainerStatuses[0].RestartCount > 0 {
return pod.Spec.NodeName, nil
}
if pod.Status.Phase == corev1.PodPending {
for _, v := range pod.Status.ContainerStatuses {
if v.State.Waiting != nil && v.State.Waiting.Reason == "ImagePullBackOff" {
return "", errors.New("wait for pod aborted after getting pod status 'ImagePullBackOff'")
}
}
}
}
}
}
// waitForDaemonSetPods waits for the DaemonSet to have the desired number of pods scheduled
func waitForDaemonSetPods(ctx context.Context, client kubernetes.Interface, ds *appsv1.DaemonSet) error {
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return ctx.Err()
case <-ticker.C:
ds, err := client.AppsV1().DaemonSets(ds.ObjectMeta.Namespace).Get(ctx, ds.ObjectMeta.Name, metav1.GetOptions{})
if err != nil {
return errors.Wrap(err, "failed to get DaemonSet")
}
// we return as soon as the desired number of pods are scheduled
if ds.Status.DesiredNumberScheduled == ds.Status.CurrentNumberScheduled {
return nil
}
}
}
}

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