Compare commits

...
805 Commits
Author SHA1 Message Date
Ethan Mosbaugh e6e9df1773 Merge pull request #565 from replicatedhq/mysql-collector-example
Mysql collector example
2022-05-04 11:14:25 -07:00
Ethan Mosbaugh 755220cd4c Mysql collector example 2022-05-04 17:45:10 +00:00
Edgar OchoaandEthan Mosbaugh 7289134757 Add Mysql variables to collector (#562)
* Add Mysql variables to collector

* Cleanup row scanning and a few updates based on feedback

* Close db connection

* Move defer db.close

* Updates based on feedback

* Use vars in loop instead of struct

* Only pull parameters specified in collector config

Co-authored-by: Ethan Mosbaugh <ethan@replicated.com>
2022-05-04 10:42:37 -07:00
Jalaja Ganapathy 63362d32ee Include osd disk usage (#563)
* Include osd disk usage

* add timeouts to ceph commands

* removed df, collect from host
2022-05-02 09:51:49 -07:00
Ethan Mosbaugh aeb89e57a7 Merge pull request #556 from replicatedhq/emosbaugh/sc-45934/longhorn-logs-collector-all-files-are-empty
Fix missing longhorn logs
2022-04-01 15:21:56 -07:00
Ethan Mosbaugh 8d1a0f6d24 return ReadCloser 2022-04-01 14:22:44 -07:00
Ethan Mosbaugh 0cfd431274 Fix missing longhorn logs 2022-04-01 14:13:32 -07:00
Andrew Lavery fe5dd3ee8f Merge pull request #554 from replicatedhq/laverya/pods-with-notready-containers-are-unhealthy
pods with containers that are not 'ready' are unhealthy
2022-03-25 22:31:25 -04:00
Andrew Lavery 7eb1d5a5fb better parse namespaces, and parse legacy list-of-pods storage format 2022-03-25 22:13:52 -04:00
Andrew Lavery 40cdc6805e pods with containers that are not 'ready' are unhealthy 2022-03-25 21:36:22 -04:00
Pavan Sokke Nagaraj 3d7a255e32 update: add missing database collector code for func GetName() (#553) 2022-03-23 22:00:25 -04:00
Pavan Sokke Nagaraj 77a2475bd2 fix: return true when one of analyzers strict field is true (#552)
* fix: return true when one of analyzers is true

* fix: return true when one of analyzers is true

* update: add unit test

* update: log errors while processing analyzers

* fix: return parse error instead of logging

* fix: update err message

* fix: evaluate strict check err separately
2022-03-23 20:24:21 -04:00
Pavan Sokke Nagaraj 7bfb54360c map strict flag to analyze result (#551)
* add util functions

* rename func HasStrictAnalyzersFailed

* map strict flag to analyze err result
2022-03-22 20:47:50 -04:00
Diamon Wiggins ca0b3c31c1 Merge pull request #544 from replicatedhq/diamonwiggins/sc-44015/run-pod-service-account
Add ServiceAccountName parameter to Run collector
2022-03-03 10:46:31 -05:00
diamonwiggins 2b774e16d7 adding serviceaccountname parameter to run collector 2022-03-03 06:12:42 +00:00
Salah Al Saleh 9d41d4a7be Fix getting pod details for new support bundle formats (#543) 2022-03-01 15:55:47 -08:00
e248ab0f97 Fix strict flag mapping (#542)
* add func BoolOrDefaultFalse and Bool

* use strict.BoolOrDefaultFalse

* Update pkg/multitype/boolstring.go

Co-authored-by: Andrew Lavery <laverya@umich.edu>

* Update pkg/multitype/boolstring_test.go

Co-authored-by: Andrew Lavery <laverya@umich.edu>

* Update pkg/multitype/boolstring_test.go

Co-authored-by: Andrew Lavery <laverya@umich.edu>

* Update boolstring_test.go

* remove duplicate test

* Update pkg/multitype/boolstring_test.go

Co-authored-by: garcialuis <garcialuisdev@gmail.com>

Co-authored-by: Andrew Lavery <laverya@umich.edu>
Co-authored-by: garcialuis <garcialuisdev@gmail.com>
2022-02-24 13:31:51 -05:00
Pavan Sokke Nagaraj 942234da80 Add strict flag to Analyzers and ResultAnalyzers (#539)
* add strict flag to Analyzer/AnalyzerMeta

and regenerate schemas and controller-gen code

* map analyzer strict to result

* Update stdout for human and json format

* fix review comment

* update interactive result

* update interactive results

* Update types.go

* Update upload_results.go

* print strict when only true
2022-02-23 15:07:51 -05:00
Craig O'Donnell 0a2ed01a46 improvement: added --output flag for preflight and support bundle (#538)
* improvement: added --output flag for preflight and support bundle

* improvement: added datetime to preflight default file name
2022-02-17 17:28:28 -05:00
Jeff Golden a818417e8c include atomic collector statuses (#534) 2022-02-10 11:27:13 -06:00
divolgin f9039a0fb5 Merge pull request #533 from replicatedhq/divolgin/gvk
Add GVK to k8s objects in cluster-resources files
2022-02-04 09:28:29 -08:00
divolgin 3351c289ab Add GVK to k8s objects in cluster-resources files 2022-02-04 01:31:07 +00:00
Salah Aldeen Al Saleh 6f0cf6550d find total memory instead of available (#525) 2022-01-11 17:02:44 -08:00
Salah Aldeen Al Saleh 7425f583fc Don't include any default host collectors (#524) 2022-01-10 16:19:56 -08:00
Andrew Lavery c3af3b63d9 Merge pull request #521 from replicatedhq/laverya/improve-required-fields
mark a number of fields as not being required
2022-01-06 18:11:08 -05:00
Andrew Lavery 8fc7d12e19 mark a number of fields as not being required
namespace/namepsaces in resource status analyzers, and the OS list in host package collectors
2022-01-06 23:54:19 +01:00
divolgin 877e43dd47 Merge pull request #511 from replicatedhq/dependabot/go_modules/k8s.io/apimachinery-0.23.0
Bump k8s.io/apimachinery from 0.22.4 to 0.23.0
2021-12-17 15:49:46 -08:00
divolgin e18d273205 Fix build 2021-12-17 23:00:21 +00:00
dependabot[bot] 3d97d8e5a6 Bump k8s.io/apimachinery from 0.22.4 to 0.23.0
Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.22.4 to 0.23.0.
- [Release notes](https://github.com/kubernetes/apimachinery/releases)
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.22.4...v0.23.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-17 23:00:21 +00:00
divolgin 137b0cee14 Merge pull request #515 from replicatedhq/divolgin/namesapces
Allow specifying namespaces when analyzing cluster resources
2021-12-17 14:31:51 -08:00
divolgin 007edd1181 Allow specifying namespaces when analyzing cluster resources 2021-12-17 21:47:06 +00:00
divolgin 3cedbe16a7 Organize test files by type and namespace 2021-12-17 19:23:54 +00:00
Salah Aldeen Al Saleh 46cfa14598 no-op (#514) 2021-12-10 14:10:27 -08:00
Salah Aldeen Al Saleh 4c72573936 os minor should default to 0 (#513) 2021-12-10 13:17:36 -08:00
Salah Aldeen Al Saleh 347d462d7f goreleaser should wait for supportbundle binary (#512) 2021-12-10 12:27:16 -08:00
Salah Aldeen Al Saleh d1f341b8ed host system packages collector/analyzer (#506)
* host system packages collector/analyzer
2021-12-10 12:05:21 -08:00
Ethan Mosbaugh 186180612b Merge pull request #502 from replicatedhq/dependabot/go_modules/sigs.k8s.io/controller-runtime-0.10.3
Bump sigs.k8s.io/controller-runtime from 0.7.0 to 0.10.3
2021-12-01 12:27:30 -08:00
dependabot[bot] bed930fa7c Bump sigs.k8s.io/controller-runtime from 0.7.0 to 0.10.3
Bumps [sigs.k8s.io/controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) from 0.7.0 to 0.10.3.
- [Release notes](https://github.com/kubernetes-sigs/controller-runtime/releases)
- [Commits](https://github.com/kubernetes-sigs/controller-runtime/compare/v0.7.0...v0.10.3)

---
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>
2021-12-01 18:43:11 +00:00
Ethan Mosbaugh 08b746d021 Merge pull request #503 from replicatedhq/dependabot/go_modules/k8s.io/apiextensions-apiserver-0.22.4
Bump k8s.io/apiextensions-apiserver from 0.22.2 to 0.22.4
2021-12-01 10:26:50 -08:00
Ethan Mosbaugh f9b55e2bff Merge pull request #504 from replicatedhq/dependabot/go_modules/github.com/shirou/gopsutil-3.21.11incompatible
Bump github.com/shirou/gopsutil from 3.21.10+incompatible to 3.21.11+incompatible
2021-12-01 10:26:37 -08:00
Ethan Mosbaugh f4db86960b Merge pull request #505 from replicatedhq/dependabot/go_modules/github.com/google/gofuzz-1.2.0
Bump github.com/google/gofuzz from 1.1.0 to 1.2.0
2021-12-01 10:02:45 -08:00
dependabot[bot] 40eea877ad Bump github.com/google/gofuzz from 1.1.0 to 1.2.0
Bumps [github.com/google/gofuzz](https://github.com/google/gofuzz) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/google/gofuzz/releases)
- [Commits](https://github.com/google/gofuzz/compare/v1.1.0...v1.2.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 17:58:15 +00:00
dependabot[bot] 9e2dac4d55 Bump github.com/shirou/gopsutil
Bumps [github.com/shirou/gopsutil](https://github.com/shirou/gopsutil) from 3.21.10+incompatible to 3.21.11+incompatible.
- [Release notes](https://github.com/shirou/gopsutil/releases)
- [Commits](https://github.com/shirou/gopsutil/compare/v3.21.10...v3.21.11)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 17:58:10 +00:00
dependabot[bot] 5c4825f4d4 Bump k8s.io/apiextensions-apiserver from 0.22.2 to 0.22.4
Bumps [k8s.io/apiextensions-apiserver](https://github.com/kubernetes/apiextensions-apiserver) from 0.22.2 to 0.22.4.
- [Release notes](https://github.com/kubernetes/apiextensions-apiserver/releases)
- [Commits](https://github.com/kubernetes/apiextensions-apiserver/compare/v0.22.2...v0.22.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 17:58:01 +00:00
Ethan Mosbaugh 2252e61cbf Merge pull request #498 from replicatedhq/dependabot/go_modules/github.com/go-redis/redis/v7-7.4.1
Bump github.com/go-redis/redis/v7 from 7.2.0 to 7.4.1
2021-12-01 09:41:11 -08:00
dependabot[bot] 7582e58220 Bump github.com/go-redis/redis/v7 from 7.2.0 to 7.4.1
Bumps [github.com/go-redis/redis/v7](https://github.com/go-redis/redis) from 7.2.0 to 7.4.1.
- [Release notes](https://github.com/go-redis/redis/releases)
- [Changelog](https://github.com/go-redis/redis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/go-redis/redis/compare/v7.2.0...v7.4.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 15:23:26 +00:00
Ethan Mosbaugh c18453711e Merge pull request #497 from replicatedhq/dependabot/go_modules/k8s.io/cli-runtime-0.22.4
Bump k8s.io/cli-runtime from 0.21.5 to 0.22.4
2021-12-01 06:49:20 -08:00
Ethan Mosbaugh 9603ccdc56 Merge pull request #499 from replicatedhq/dependabot/go_modules/github.com/spf13/viper-1.9.0
Bump github.com/spf13/viper from 1.8.1 to 1.9.0
2021-12-01 06:49:01 -08:00
Ethan Mosbaugh 891ee93cb1 Merge pull request #500 from replicatedhq/dependabot/go_modules/github.com/lib/pq-1.10.4
Bump github.com/lib/pq from 1.3.0 to 1.10.4
2021-12-01 06:48:47 -08:00
Ethan Mosbaugh 2cfa690838 Merge pull request #501 from replicatedhq/dependabot/go_modules/github.com/go-sql-driver/mysql-1.6.0
Bump github.com/go-sql-driver/mysql from 1.5.0 to 1.6.0
2021-12-01 06:48:37 -08:00
dependabot[bot] 9b9824bef5 Bump github.com/go-sql-driver/mysql from 1.5.0 to 1.6.0
Bumps [github.com/go-sql-driver/mysql](https://github.com/go-sql-driver/mysql) from 1.5.0 to 1.6.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.5.0...v1.6.0)

---
updated-dependencies:
- dependency-name: github.com/go-sql-driver/mysql
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 01:01:27 +00:00
dependabot[bot] 60ef14a751 Bump github.com/lib/pq from 1.3.0 to 1.10.4
Bumps [github.com/lib/pq](https://github.com/lib/pq) from 1.3.0 to 1.10.4.
- [Release notes](https://github.com/lib/pq/releases)
- [Commits](https://github.com/lib/pq/compare/v1.3.0...v1.10.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 01:01:14 +00:00
dependabot[bot] 3980a7b903 Bump github.com/spf13/viper from 1.8.1 to 1.9.0
Bumps [github.com/spf13/viper](https://github.com/spf13/viper) from 1.8.1 to 1.9.0.
- [Release notes](https://github.com/spf13/viper/releases)
- [Commits](https://github.com/spf13/viper/compare/v1.8.1...v1.9.0)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 01:00:57 +00:00
dependabot[bot] 655fa9b4a0 Bump k8s.io/cli-runtime from 0.21.5 to 0.22.4
Bumps [k8s.io/cli-runtime](https://github.com/kubernetes/cli-runtime) from 0.21.5 to 0.22.4.
- [Release notes](https://github.com/kubernetes/cli-runtime/releases)
- [Commits](https://github.com/kubernetes/cli-runtime/compare/v0.21.5...v0.22.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-12-01 00:59:45 +00:00
Ethan Mosbaugh 27c5e51920 Merge pull request #496 from replicatedhq/emosbaugh/update-containers-image-v5
Update github.com/containers/image/v5
2021-11-30 16:28:58 -08:00
Ethan Mosbaugh 177f2da16d Update github.com/containers/image/v5 2021-11-30 23:37:25 +00:00
Ethan Mosbaugh d774ad1f5a Merge pull request #493 from replicatedhq/dependabot/go_modules/k8s.io/apiserver-0.22.4
Bump k8s.io/apiserver from 0.22.2 to 0.22.4
2021-11-30 15:10:50 -08:00
Ethan Mosbaugh 9c5ae1f64e Merge pull request #494 from replicatedhq/dependabot/go_modules/github.com/segmentio/ksuid-1.0.4
Bump github.com/segmentio/ksuid from 1.0.3 to 1.0.4
2021-11-30 15:10:24 -08:00
Ethan Mosbaugh a237dba463 Merge pull request #495 from replicatedhq/dependabot/go_modules/github.com/fatih/color-1.13.0
Bump github.com/fatih/color from 1.12.0 to 1.13.0
2021-11-30 15:10:03 -08:00
dependabot[bot] 60ec620ba9 Bump github.com/fatih/color from 1.12.0 to 1.13.0
Bumps [github.com/fatih/color](https://github.com/fatih/color) from 1.12.0 to 1.13.0.
- [Release notes](https://github.com/fatih/color/releases)
- [Commits](https://github.com/fatih/color/compare/v1.12.0...v1.13.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>
2021-11-30 22:10:22 +00:00
dependabot[bot] 0c422aefbd Bump github.com/segmentio/ksuid from 1.0.3 to 1.0.4
Bumps [github.com/segmentio/ksuid](https://github.com/segmentio/ksuid) from 1.0.3 to 1.0.4.
- [Release notes](https://github.com/segmentio/ksuid/releases)
- [Commits](https://github.com/segmentio/ksuid/compare/v1.0.3...v1.0.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 22:10:13 +00:00
dependabot[bot] c2ac654e08 Bump k8s.io/apiserver from 0.22.2 to 0.22.4
Bumps [k8s.io/apiserver](https://github.com/kubernetes/apiserver) from 0.22.2 to 0.22.4.
- [Release notes](https://github.com/kubernetes/apiserver/releases)
- [Commits](https://github.com/kubernetes/apiserver/compare/v0.22.2...v0.22.4)

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

Signed-off-by: dependabot[bot] <support@github.com>
2021-11-30 22:10:05 +00:00
Ethan Mosbaugh ffc8a347c6 Merge pull request #490 from replicatedhq/emosbaugh-create-dependabot-yaml
Create dependabot.yml
2021-11-30 13:59:27 -08:00
Ethan Mosbaugh 0a5e397d44 Create dependabot.yml 2021-11-30 13:56:43 -08:00
Ethan Mosbaugh e03cf6b37f Merge pull request #489 from replicatedhq/emosbaugh-delete-dependabot
Delete dependabot.yml
2021-11-30 13:56:08 -08:00
Ethan Mosbaugh 2ec15b69f6 Delete dependabot.yml 2021-11-30 13:53:04 -08:00
Ethan Mosbaugh 39bd7778f5 Merge pull request #488 from replicatedhq/emosbaugh/sc-38420/fix-go-mod
Fix go mod
2021-11-30 13:47:44 -08:00
Ethan Mosbaugh 59d50e7679 Fix go mod 2021-11-30 21:26:24 +00:00
Ethan Mosbaugh cb8dccbe7b Merge pull request #487 from replicatedhq/emosbaugh/20211130/fixes
Various fixes
2021-11-30 13:06:45 -08:00
Ethan Mosbaugh fba0f97225 found not ound 2021-11-30 20:12:29 +00:00
Ethan Mosbaugh 4d0eaf471f crd not storageClass 2021-11-30 20:12:09 +00:00
Ethan Mosbaugh 213d518136 Time parse doesnt support day notation 2021-11-30 20:11:51 +00:00
Ethan Mosbaugh c4ba3fe70e Merge pull request #486 from replicatedhq/enable-dependabot
Enable dependabot
2021-11-30 10:01:03 -08:00
Ethan Mosbaugh b524ac8ac4 Add labels and change interval to weekly 2021-11-30 10:00:49 -08:00
Ethan Mosbaugh 7403de58bd Enable dependabot 2021-11-30 09:52:03 -08:00
Marc Campbell 9eadae6771 Merge pull request #484 from replicatedhq/arm
Adding darwin/arm64
2021-11-12 11:57:14 -08:00
Marc Campbell 75a56d09b2 Windows/Arm64 2021-11-12 19:38:24 +00:00
Marc Campbell 4a72e7d2a5 Bump go version 2021-11-12 19:03:35 +00:00
Marc Campbell 2c53fb4da6 Bump go-ole 2021-11-12 18:02:08 +00:00
Marc Campbell 6a360b635f Merge branch 'arm' of https://github.com/replicatedhq/troubleshoot into arm 2021-11-12 18:01:36 +00:00
Marc Campbell 913963a809 Bump go-ole dep 2021-11-12 18:00:11 +00:00
Marc Campbell 49c56f6cd7 Adding darwin/arm64 2021-11-12 17:51:02 +00:00
Marc Campbell baa943474d Merge pull request #485 from replicatedhq/remove-precache
Remove precache until we have it enabled
2021-11-12 09:49:31 -08:00
Marc Campbell fa2c775abd Remove precache until we have it enabled 2021-11-11 22:31:11 +00:00
Marc Campbell ac65e4dc97 Adding darwin/arm64 2021-11-11 22:27:21 +00:00
Marc Campbell dfb0991fb2 Merge pull request #483 from replicatedhq/codespaces
Add codespace env
2021-11-11 14:05:03 -08:00
Marc Campbell 101ab5d2fa Add github action for codespace 2021-11-11 21:32:21 +00:00
Marc Campbell 5211cb0fe7 Add codespace env 2021-11-11 20:57:54 +00:00
Salah Aldeen Al Saleh c7c21e88fb fix custom resources redaction file path (#480)
* fix custom resources redaction file path
2021-11-02 12:36:15 -07:00
divolgin ea7756f8f2 Merge pull request #479 from replicatedhq/divolgin/no-files
Allow text analyzer to not generate an error if no files match
2021-10-29 11:23:34 -07:00
divolgin 739ee666af Allow text analyzer to not generate an error if no files match 2021-10-29 17:52:59 +00:00
divolgin 181df9c85b Merge pull request #478 from replicatedhq/divolgin/outcomes
Ensure outcomes are optional in every case
2021-10-28 17:41:02 -07:00
divolgin 742ddc8c06 Ensure outcomes are optional in every case 2021-10-29 00:23:32 +00:00
divolgin b4c97e377e Merge pull request #477 from replicatedhq/divolgin/selectors
replicaset analyzer supports label selectors
2021-10-28 17:21:11 -07:00
divolgin 7cb6d90a39 replicaset analyzer supports label selectors 2021-10-28 22:06:15 +00:00
Sean Rester 5d9f14fde5 Merge pull request #474 from replicatedhq/add-node-status-check
38798: Adding node status check
2021-10-28 17:52:18 -04:00
Salah Aldeen Al Saleh 14463642b0 a function to get a pod details from the support bundle (#476)
* a function to get a pod details from the support bundle
2021-10-28 14:06:02 -07:00
Salah Aldeen Al Saleh 45dd980012 update cluster pod analyzers comment (#475) 2021-10-28 10:31:59 -07:00
e100e7c478 get container logs for unhealthy pods (#469)
* get container logs for unhealthy pods

Co-authored-by: divolgin <dmitriy@replicated.com>
Co-authored-by: divolgin <divolgin@users.noreply.github.com>
2021-10-28 09:21:14 -07:00
Sean Rester 1345b200aa 38798: Adding node status check 2021-10-28 11:16:26 -04:00
divolgin 1cb0dab3c2 Merge pull request #471 from replicatedhq/divolgin/windows
Fix windows build
2021-10-27 15:39:15 -07:00
divolgin db3d27d38f Fix windows build 2021-10-27 21:29:11 +00:00
divolgin e7daba9d0c Merge pull request #470 from replicatedhq/divolgin/analyzers
Replicaset collector and analyzer
2021-10-27 13:51:42 -07:00
divolgin ada35eb31c Replicaset collector and analyzer 2021-10-27 20:24:14 +00:00
Salah Aldeen Al Saleh f2374cf113 add involved object to clusterPodStatuses analyzer result (#459)
* cluster pod statuses analyzer involved object
2021-10-27 12:18:49 -07:00
Salah Aldeen Al Saleh e7f7e75df1 change goreleaser version to v0.166.1 (#468) 2021-10-27 10:31:35 -07:00
Salah Aldeen Al Saleh 5a8561a31f include logs for init containers as well (#467) 2021-10-27 10:20:55 -07:00
divolgin 0df678929a Merge pull request #465 from replicatedhq/divolgin/analyzers
Jobs status analyzer
2021-10-26 17:13:36 -07:00
divolgin 1cdfd96768 Jobs status analyzer 2021-10-26 23:41:02 +00:00
divolgin 9666679ab4 Merge pull request #464 from replicatedhq/divolgin/analyzers
Analyze all deployments in all namespaces
2021-10-26 14:54:15 -07:00
divolgin f108c3ca57 Analyze all deployments in all namespaces 2021-10-26 21:36:27 +00:00
divolgin 491376b772 Merge pull request #462 from replicatedhq/divolgin/analyzers
Ability to analyze all statefulsets
2021-10-26 14:08:32 -07:00
divolgin 34724e7932 Ability to analyze all statefulsets 2021-10-26 20:51:45 +00:00
Marc Campbell 7e11498509 Merge pull request #461 from replicatedhq/deepsource-fix-97a5e72b
Fix check for empty string
2021-10-26 12:58:17 -07:00
deepsource-autofix[bot] 3e60fcda8e Fix check for empty string 2021-10-26 19:24:08 +00:00
Salah Aldeen Al Saleh b32afc1d17 pin goreleaser version to v0.182.1 (#460) 2021-10-26 11:37:37 -07:00
divolgin f048b426a5 Merge pull request #440 from replicatedhq/divolgin/tests
Better preflight validation
2021-10-26 08:45:40 -07:00
Salah Aldeen Al Saleh 26402a7b04 cluster pod statuses analyzer improvements (#458)
* add pod status reason to cluster pod statuses analyzer
2021-10-26 08:42:40 -07:00
Salah Aldeen Al Salehanddivolgin 3d1d53ee9d ClusterPodStatuses analyzer (#456)
* ClusterPodStatuses analyzer

Co-authored-by: divolgin <dmitriy@replicated.com>
2021-10-25 17:44:59 -07:00
divolgin 9cbdb70d16 Merge pull request #457 from replicatedhq/divolgin/pod-logs
Include pod logs for pods that are failing
2021-10-25 17:18:32 -07:00
divolgin 20f1b60f11 Include pod logs for pods that are failing 2021-10-26 00:01:26 +00:00
divolgin fafac18d29 Merge pull request #455 from replicatedhq/divolgin/ceph
Fix ceph collector
2021-10-22 16:38:55 -07:00
divolgin 072d2d7a36 Fix ceph collector 2021-10-22 23:01:13 +00:00
Andrew Reed 7b36e6a1f8 Copy in longhorn client (#454) 2021-10-22 15:24:07 -05:00
cf03503216 feat: Collect custom resources (#447)
* feat: Collect custom resources
Co-authored-by: Martin Hrabovcin<mhrabovcin@users.noreply.github.com>

Co-authored-by: Andrew Reed <andrew@replicated.com>
2021-10-21 16:49:59 -05:00
Dimitri KoshkinandSalah Aldeen Al Saleh 111396eb39 fix: pass redact flag when running support-bundle (#406)
Co-authored-by: Salah Aldeen Al Saleh <sg.alsaleh@gmail.com>
2021-10-20 10:47:27 -07:00
Jalaja Ganapathy 372454651e collector/analyzer for host operating system (#443)
* collector/analyzer for host operating system

* address cr comments

* cleanup

* fix invoking the analyzer
code cleanup

* fix cr comments

* add corner case unit-test

* fix kernel version parsing

* address review comments

* add default case

* parse using regex

* added more testcases and fixed the bug found in cr

* few small things
2021-10-12 14:42:23 -07:00
divolgin 5dece3eb75 Merge pull request #451 from replicatedhq/divolgin/panic
Check nil pointers
2021-10-12 10:12:11 -07:00
divolgin e095a7838f Check nil pointers 2021-10-12 16:10:02 +00:00
Vera Harless 08953d46d1 fix: add collect to goreleaser (#450) 2021-10-08 15:44:55 -04:00
Andrew Lavery bc197761ea Merge pull request #434 from croomes/handle-api-deprecations
Handle k8s api deprecations
2021-10-08 06:52:31 -07:00
Simon Croome dc8b38d249 Handle k8s api deprecations 2021-10-07 18:55:51 +01:00
Vera Harless 73609c4fef feat: add more detail to the ceph analyzer output (#445) 2021-10-06 11:22:56 -04:00
Simon Croome 977fc438ea Remote host collectors (#392)
* Add collect command and remote host collectors

Adds the ability to run a host collector on a set of remote k8s nodes.
Target nodes can be filtered using the --selector flag, with the same
syntax as kubectl.  Existing flags for --collector-image,
--collector-pullpolicy and --request-timeout are used.  To run on a
specified node, --selector="kubernetes.io/hostname=kind-worker2" could
be used.

The collect command is used by the remote collector to output the
results using a "raw" format, which uses the filename as the key, and
the value the output as a escaped json string.  When run manually it
defaults to fully decoded json. The existing block devices,
ipv4interfaces and services host collectors don't decode properly - the
fix is to convert their slice output to a map (fix not included as
unsure what depends on the existing format).

The collect command is also useful for troubleshooting preflight issues.

Examples are included to show remote collector usage.

```
bin/collect --collector-image=croomes/troubleshoot:latest  examples/collect/remote/memory.yaml --namespace test
{
  "kind-control-plane": {
    "system/memory.json": {
      "total": 1304207360
    }
  },
  "kind-worker": {
    "system/memory.json": {
      "total": 1695780864
    }
  },
  "kind-worker2": {
    "system/memory.json": {
      "total": 1726353408
    }
  }
}
```

The preflight command has been updated to run remote collectors.  To run
a host collector remotely it must be specified in the spec as a
`remoteCollector`:

```
apiVersion: troubleshoot.sh/v1beta2
kind: HostPreflight
metadata:
  name: memory
spec:
  remoteCollectors:
    - memory:
        collectorName: memory
  analyzers:
    - memory:
        outcomes:
          - fail:
              when: "< 8Gi"
              message: At least 8Gi of memory is required
          - warn:
              when: "< 32Gi"
              message: At least 32Gi of memory is recommended
          - pass:
              message: The system has as sufficient memory
```

Results for each node are analyzed separately, with the node name
appended to the title:

```
bin/preflight --interactive=false --collector-image=croomes/troubleshoot:latest examples/preflight/remote/memory.yaml --format=json
{memory running 0 1}
{memory completed 1 1}
{
  "fail": [
    {
      "title": "Amount of Memory (kind-worker2)",
      "message": "At least 8Gi of memory is required"
    },
    {
      "title": "Amount of Memory (kind-worker)",
      "message": "At least 8Gi of memory is required"
    },
    {
      "title": "Amount of Memory (kind-control-plane)",
      "message": "At least 8Gi of memory is required"
    }
  ]
}
```

Also added a host collector to allow preflight checks of required kernel
modules, which is the main driver for this change.
2021-10-06 09:03:53 -05:00
Andrew Reed 4d52760d35 Collector and analyzer for sysctl parameters (#441)
Collector and analyzer for sysctl parameters
2021-10-01 13:43:26 -05:00
divolgin 6e34aa615e Merge pull request #442 from replicatedhq/divolgin/closer
Allow memory writers
2021-09-30 11:42:14 -07:00
divolgin ca51e92878 Allow memory writers 2021-09-30 18:25:52 +00:00
divolgin c546577449 Better preflight validation 2021-09-29 22:28:25 +00:00
divolgin 06750d478e Merge pull request #439 from replicatedhq/divolgin/nil
Don't panic when no data is collected
2021-09-29 15:03:50 -07:00
divolgin 6d0a57b16e Don't panic when no data is collected 2021-09-29 21:25:28 +00:00
Jalaja Ganapathy 8a29442a2a Remove ID from host preflight spec (#438) 2021-09-29 09:49:54 -07:00
divolgin 299497c0c0 Merge pull request #429 from danbudris/copyFromHostForCpNodes
add toleration to copy-from-host daemonset to allow collection from CP nodes
2021-09-29 09:01:14 -07:00
divolgin 050f5939c6 Merge pull request #437 from replicatedhq/divolgin/memory
Save collector data to disk directly
2021-09-29 08:12:05 -07:00
divolgin 0e8bedc281 Save collector data to disk directly 2021-09-29 00:15:02 +00:00
Dan Stough bb0515830d Merge pull request #436 from replicatedhq/dans-fix-sbom-perms
chore(ci): fix sbom assets for krew
2021-09-28 15:09:47 -04:00
Dan Stough b903f1f1c4 chore(ci): fix sbom asset perms 2021-09-28 16:37:53 +00:00
Jalaja Ganapathy f26c9b4136 fix README syntax (#433) 2021-09-24 17:35:36 -07:00
Jalaja Ganapathy eb795c98b6 fix serializer for unique id (#432) 2021-09-24 14:20:37 -07:00
Jalaja Ganapathy a0b3b3f7dc add an unique id to each host preflights (#431)
* add an unique id to each host preflights

* auto generated files

* updated schemas for the new field id

* keeping it consistent with the rest of the spec
2021-09-24 13:29:14 -07:00
danbudris 67987a4432 add toleration to allow copy-from-host daemonset to run on CP nodes 2021-09-23 17:53:57 -04:00
Salah Aldeen Al Saleh 1bdd3db8c5 update schemas (#428)
* update schemas

* update controller-gen
2021-09-23 11:03:19 -07:00
John Murphy a2b5edb551 added missing cosign.key (#427)
SBOM generation was failing because it missed a step to generate the private key needed for SBOM signing from Github secret.
2021-09-23 10:46:30 -05:00
Salah Aldeen Al Saleh 880c7dc3ea ability to specify a list of namespaces for the cluster resources collector (#424)
* ability to specify a list of namespaces for the cluster resources collector
2021-09-23 08:02:05 -07:00
divolgin 922f7c8b23 Merge pull request #425 from replicatedhq/divolgin/results
Analyzers should not return multiple results
2021-09-22 16:13:54 -07:00
divolgin afa08e5362 Analyzers should not return multiple results 2021-09-22 22:50:38 +00:00
Dan Stough 614aed52c9 Merge pull request #422 from replicatedhq/dans/fix-clean-noninteractive-output
fix(support-bundle): no client-go warnings or control chars if noninteractive.
2021-09-22 13:38:43 -04:00
Dan Stough 72a50ee3f2 fix(support-bundle): no client-go warnings or control chars if noninteractive 2021-09-22 15:59:35 +00:00
Salah Aldeen Al Saleh 0c7fede7b6 check for nil analyzers (#421) 2021-09-21 12:12:10 -07:00
John Murphy 639bf7a832 Add signed SBOM to troubleshoot (#414)
This change will generate a signed software bill of materials and add it to the repository release archives when the project is released.
2021-09-21 13:55:41 -05:00
John Murphy 48287097d8 added email alias to code of conduct (#420) 2021-09-21 13:52:00 -05:00
divolgin cb5ddf752f Merge pull request #419 from danbudris/machineReadableNonInteractiveOutput
make non-interactive `support-bundle` output more machine readable
2021-09-21 09:21:06 -07:00
danbudris 52e1a04f57 Merge branch 'machineReadableNonInteractiveOutput' of https://github.com/danbudris/troubleshoot into machineReadableNonInteractiveOutput 2021-09-17 11:21:34 -04:00
danbudris 5b4b548aa0 if interactive, only return the print archivePath to stdout; if non-interactive, print whole analysis as json 2021-09-17 11:20:39 -04:00
Daniel Budris f2a232d174 use analyzerResults not analysis for key 2021-09-17 11:05:34 -04:00
danbudris f4e675dae0 add json tags to output struct for easier unmarshalling 2021-09-17 10:57:52 -04:00
danbudris 867df407ea convert output bytearray to string before printing 2021-09-17 10:50:22 -04:00
danbudris e0fb748498 move non-interactive output to discreet struct with marshalling methods; dont show output for non-interactive; format everything in JSON 2021-09-17 10:38:38 -04:00
danbudris 463783d2fa resolve merge conflicts 2021-09-15 21:25:15 -04:00
danbudris 2ce78ac33a Merge branch 'master' of https://github.com/replicatedhq/troubleshoot into machineReadableNonInteractiveOutput 2021-09-15 21:19:01 -04:00
danbudris 4cf0f5881d make non-interactive support-bundle output more machine readable
when using the `interactive=false` flag of `support-bundle`, the spinner would still spin and the archive path and analysis output were kind of smooshed together with the logs.

now, if `interactive=false`, only print each recieved collector callback message once, and don't spin

also, add a key to the archivePath and analyzerOutput that are returned, for easier programatic parsing
2021-09-15 20:58:09 -04:00
Salah Aldeen Al Saleh 465a533640 store analysis in the support bundle (#417)
* store analysis in the support bundle
2021-09-10 11:58:16 -07:00
Andrew Reed 10785987c5 Merge pull request #415 from areed/areed/weave-analyzer
Weave report analyzers
2021-09-09 12:47:51 -05:00
Andrew Reed 91eb94baaa Weave report analyzers
The IPAM pool analyzer checks that utilization of the pod IP subnet is
less than 85%. For example, if using 10.32.0.0/12, this analyzer will
warn if 3,482 IPs are currently allocated to pods.

The pending allocation analyzer checks that the IPAM status in the
report has no items for the PendingAllocates field. This indicates the
IPAM service is not ready according to the code in the weave status
template
https://github.com/weaveworks/weave/blob/e3712152d2a0fe3bc998964c948e45bdf8ff6144/prog/weaver/http.go#L186.

The weave connections analyzer checks that all connections to remote
peers are in the established state. The state will be "pending" if UDP
is blocked between nodes and will be "failed" if the weave pod on the
remote node is in a crash loop. To force a pending state for testing,
run the commands `iptables -A INPUT -p udp --dport 6784 -j REJECT` and
`iptables -A INPUT -p udp --dport 6783 -j REJECT` on a peer.

The weave connections analyzer also checks that all connections are
using the fastdp protocol. A commopn issue seen in the field on
CentOS/RHEL 7 is that some sides of a connection are using fastdp and
other sides have fallen back to sleeve. Set the WEAVE_NO_FASTDP env var
on the weave daemonset to "true" to test this analyzer.
2021-09-08 21:29:38 +00:00
Andrew Lavery 1b65d1a544 Merge pull request #413 from replicatedhq/laverya/collect-jobs-and-cronjobs
collect jobs and cronjobs as part of cluster-resources
2021-09-03 17:25:41 -04:00
Dan Stough 6e09aa641d Merge pull request #412 from replicatedhq/dans-chore-goreleaser-175-updates
chore(ci): update gorelease.yaml to use v175 syntax
2021-09-03 17:23:14 -04:00
Andrew Lavery 7fcc951c9a collect jobs and cronjobs as part of cluster-resources 2021-09-03 15:46:03 -05:00
Dan Stough 123e2e1049 chore(ci): update gorelease.yaml to use 175 syntax 2021-09-03 20:45:18 +00:00
Dan Stough 558f92caef Merge pull request #411 from replicatedhq/dans-fix-missing-cluster-res-namespaces
fix: cluster-res collector fixed to one namespace
2021-09-03 15:41:50 -04:00
Dan Stough 0478a7a60f fix: cluster-res collector fixed to one namespace 2021-09-03 19:23:44 +00:00
divolgin 5b157381fe Merge pull request #410 from replicatedhq/divolgin/codeowners
Create CODEOWNERS
2021-09-01 14:30:13 -07:00
divolgin 1181bc21d0 Create CODEOWNERS 2021-09-01 21:14:48 +00:00
Salah Aldeen Al Saleh c7af0dc593 fix openshift cluster detection (#408) 2021-08-24 09:51:12 -07:00
Kyle Sorensenandmurphybytes f30e925580 Community building (#402)
Create CODE_OF_CONDUCT.md , CONTRIBUTING.md and bug report / feature request templates for issues

Co-authored-by: murphybytes <murphybytes@gmail.com>
2021-08-19 20:57:46 -06:00
Jalaja Ganapathy e23fb2ce59 run support-bundle and preflight checks even with restricted access (#404) 2021-08-13 07:52:49 -07:00
John Murphy fd3b32293c default result only when no other result exists (#398) 2021-07-28 11:19:41 -05:00
Kyle Sorensen 2977f8f0d3 Stop longhorn false positives on no results. (#397)
Longhorn analyzer no longer report positive results on no results
2021-07-28 09:37:54 -06:00
Kyle Sorensen bf7d658313 troubleshoot enables collecting all data from a configmap (#395)
Enabled collecting all data from a ConfigMap instead of by key
2021-07-26 13:00:06 -06:00
emosbaugh e2dbb623e3 Merge pull request #396 from replicatedhq/emosbaugh/20210726/cleanup
remove debug log
2021-07-26 11:38:29 -06:00
Joris 'Josh' De Winne 6349ae8aee Adding support for inverted regex (#370) 2021-07-26 13:06:30 -04:00
Ethan Mosbaugh 851c91b582 remove debug log 2021-07-26 16:28:11 +00:00
emosbaugh cf4d510413 Merge pull request #393 from replicatedhq/collect-copy-extractArchive
Copy collectors extractArchive property
2021-07-23 08:55:10 -06:00
John Murphy e0f6cab5b3 Fix removes control characters from non interactive preflight runs (#394) 2021-07-23 09:46:36 -05:00
Ethan Mosbaugh cf7864cd97 Copy collectors extractArchive property 2021-07-23 13:37:57 +00:00
emosbaugh 8dcfa9886d Copy from host collector (#391)
* Copy from host collector

* namespace improvements

* better support for multiple nodes
2021-07-22 12:25:59 -07:00
John Murphy 6007f15253 fixed issue where warnings are disseminated along with passes (#390) 2021-07-22 08:27:39 -05:00
Andrew Lavery ba65f92ca2 Merge pull request #389 from replicatedhq/laverya/simplify-text-analyze-code
simplify the text analyze code by combining with compareRegex code
2021-07-20 16:32:38 -07:00
Andrew Lavery 6a0fb2e19c greatly improve coverage by adding regex group tests 2021-07-20 19:15:09 -04:00
Andrew Lavery 6861660460 simplify the text analyze code by combining with compareRegex code 2021-07-20 18:43:09 -04:00
kwsorensen 1ed6100ac8 Feature/validate tcp load balancer address (#387)
Load Balancer Validation part of troubleshoot pre-flight checks
2021-07-14 14:30:47 -06:00
emosbaugh 39350b5722 ConfigMap collector and secrets can be collected by selectors (#384)
* ConfigMap collector and secrets can be collected by selectors

* follow docs

* Pass context and kubernetes client to collectors

* collect tests

* analyze tests

* fix tests

* improvements
2021-07-08 16:30:26 -07:00
emosbaugh d7b6aa2758 Log progress when interactive=false (#382)
* Log progress when interactive=false

* safe print statement
2021-07-08 13:57:35 -07:00
Andrew Reed 0d56371242 Merge pull request #385 from replicatedhq/longhorn-accumulate-analyzers
Accumulate all longhorn pass results
2021-07-08 14:16:06 -05:00
Andrew Reed c95dc489a2 Accumulate all longhorn pass results
If there are any error or warning results then return those. Otherwise
return a single healthy pass result.
2021-07-08 18:25:10 +00:00
John Murphy c119a16235 Fixed bugs introduced by handling multiple results in host preflights (#383)
Fixed bug caused by host preflights not handling empty when clauses, this cropped up because we now handle multiple host preflight results. Also expanded test coverage and added integration test script.
2021-07-08 11:08:53 -05:00
John Murphy d730e6cad6 fixed tests 2021-07-06 08:42:12 -05:00
John Murphy 7e32de464a implemented code review suggestion 2021-07-06 08:42:12 -05:00
John Murphy ae4c07027b host preflights can produce multiple results 2021-07-06 08:42:12 -05:00
John Murphy eef54d0021 force timezone to upper case 2021-07-06 08:42:12 -05:00
divolgin 972fe2c210 Merge pull request #380 from replicatedhq/divolgin/cursor
Make cursors visible on CTRL+C
2021-07-01 16:26:46 -07:00
divolgin 4047977b35 Make cursors visible on CTRL+C 2021-07-01 23:08:05 +00:00
divolgin 3382d29e96 Merge pull request #379 from replicatedhq/divolgin/apis
Update troubleshoot api schema
2021-07-01 11:32:24 -07:00
Andrew Reed 4b4eedf477 Merge pull request #378 from replicatedhq/longhorn-ns
Always use longhorn namespace
2021-07-01 13:12:19 -05:00
divolgin 7381d5086c Update troubleshoot api schema 2021-07-01 17:24:00 +00:00
Andrew Reed 1ed8532663 Speed up replica checksum 2021-07-01 16:52:59 +00:00
Andrew Reed 3833955a58 Always include longhorn namespace 2021-07-01 15:03:28 +00:00
divolgin 6aa97a9a51 Merge pull request #376 from replicatedhq/divolgin/insecretls
Don't skip TLS validation on http package's default client
2021-06-30 11:47:25 -07:00
divolgin 52bbc0f2bf Don't skip TLS validation on http package's default client 2021-06-30 18:22:15 +00:00
divolgin 8fbae89465 Merge pull request #375 from replicatedhq/divolgin/redact
Add a default redactor for postgres db connection string
2021-06-29 15:48:39 -07:00
divolgin 53e8ee5495 Add a default redactor for postgres db connection string 2021-06-29 22:38:32 +00:00
Andrew Reed c018452b8a Merge pull request #374 from areed/longhorn-corrupted-replica
Longhorn replica corruption analyzer
2021-06-22 17:38:19 -05:00
Andrew Reed cb3925a0af Longhorn replica corruption analyzer
This automates the procedure from
https://longhorn.io/docs/1.1.1/advanced-resources/data-recovery/corrupted-replica/
2021-06-22 21:55:12 +00:00
Andrew Reed 900dd9e417 Merge pull request #373 from areed/no-import-goprocinfo
Use updated longhorn-manager fork
2021-06-22 15:37:49 -05:00
Andrew Reed 776934af2b Use updated longhorn-manager fork 2021-06-22 20:20:41 +00:00
Vera Harless f92d6f9cfe fix: always print support-bundle filename after generation (#372) 2021-06-16 14:05:47 -04:00
Andrew Reed 904afc0b2a Merge pull request #369 from areed/longhorn-engines-analyzer
Analyze longhorn engine
2021-05-27 16:54:34 -05:00
Andrew Reed e1bccd74b5 Analyze longhorn engine 2021-05-27 21:37:39 +00:00
Andrew Reed 2f34561a39 Merge pull request #368 from areed/longhorn-pod-logs
Collect all longhorn pod logs
2021-05-27 15:29:45 -05:00
Andrew Reed a86f5cae7d Collect all longhorn pod logs 2021-05-27 20:14:05 +00:00
Andrew Reed ed6b3369b3 Merge pull request #367 from areed/longhorn-replica-analyzer
Analyze longhorn replica
2021-05-27 15:07:54 -05:00
Andrew Reed 0d5f17de3c Analyze longhorn replica 2021-05-27 19:44:52 +00:00
Andrew Reed 12fb05e5f9 Merge pull request #366 from areed/longhorn
Longhorn collector for all CRDs
2021-05-26 18:52:06 -05:00
Andrew Reed 646f7a6991 Longhorn collector for all CRDs
Also implement a single analyzer as a proof of concept. More analyzers
can be added using the collected CRDs.
2021-05-26 23:37:15 +00:00
divolgin 160fffe9ed Merge pull request #364 from replicatedhq/divolgin/insecure
Do insecure upload if user allows it
2021-05-14 11:33:47 -07:00
divolgin c17be3fb73 Do insecure upload if user allows it 2021-05-14 18:21:56 +00:00
Dan Stough 35718432fe Merge pull request #363 from replicatedhq/chore-refactor-support-bundle
fix: use temp directory for storing bundles
2021-05-05 10:17:21 -04:00
Dan Stough 0dd24c702c fix: use temp directory for storing bundles 2021-05-04 20:29:21 +00:00
Dan Stough 2c3909f585 Merge pull request #360 from replicatedhq/chore-refactor-support-bundle
chore(support-bundle): refactor out support bundle pkg
2021-05-04 10:53:29 -04:00
Dan Stough b8622a65ad chore(support-bundle): refactor out support bundle pkg 2021-05-04 14:41:54 +00:00
emosbaugh f1ca1a5345 Merge pull request #362 from replicatedhq/preflight-error-and-result
Include result if not nil regardless of error
2021-04-28 20:41:26 -07:00
Ethan Mosbaugh 9357d5ac96 Include result if not nil regardless of error 2021-04-28 02:58:59 +00:00
Andrew Lavery eef9ebe0e5 Merge pull request #361 from replicatedhq/laverya/rook-block-device-disk-stats
collect rook block device disk stats
2021-04-20 16:10:15 -05:00
Andrew Lavery 25a92dec56 collect rook block device disk stats
this contains both max size and currently used size for each PV
2021-04-20 15:41:47 -05:00
divolgin 39cf553a03 Merge pull request #359 from replicatedhq/divolgin/maxage
Honor maxAge for log collector if set in the spec
2021-04-19 13:26:29 -07:00
divolgin e5233dfcf5 Honor maxAge for log collector if set in the spec 2021-04-19 20:15:41 +00:00
Dan Stough 1562a645de Merge pull request #358 from replicatedhq/DanStough-patch-1
Fix linkage to KOTS
2021-04-15 12:01:33 -04:00
Dan Stough 3f43697b57 Fix linkage to KOTS 2021-04-15 11:46:59 -04:00
jgruica 67ec6f54bc Merge pull request #357 from replicatedhq/jelena-analyzer-checks
More analyzer types checks
2021-04-15 07:59:08 -07:00
Jelena c43da65afe More analyzer types checks 2021-04-15 14:30:20 +00:00
jgruica dd2c2f84e6 Merge pull request #352 from replicatedhq/jelena-analyze-supportbundle
Analyze kind support bundle
2021-04-14 14:15:24 -07:00
Andrew Reed 45decfcb7d Merge pull request #356 from areed/fs-perf-text
Remove html escaping in fs performance analyzer
2021-04-13 12:47:14 -07:00
Andrew Reed 7d7e3c2664 Remove html escaping in fs performance analyzer 2021-04-13 19:35:11 +00:00
Andrew Reed 822ada99a2 Merge pull request #355 from areed/fs-perf-fix-timeout
Fix background IOPS blocking until timeout
2021-04-13 12:05:54 -07:00
Andrew Reed 30f21ac71b Fix background IOPS blocking until timeout 2021-04-13 18:55:53 +00:00
Andrew Reed ce815844cd Merge pull request #354 from areed/fs-perf-timeout
Add timeout to filesystem performance collector
2021-04-13 11:43:19 -07:00
Andrew Reed 0a6c9836e0 Add timeout to filesystem performance collector 2021-04-13 18:30:18 +00:00
Andrew Lavery e21813535c Merge pull request #353 from replicatedhq/laverya/collect-rgw-status
collect RGW status/stats as part of ceph collector
2021-04-13 11:24:08 -05:00
Andrew Lavery 44993a5d0d collect RGW status as part of ceph collector 2021-04-12 23:14:00 -05:00
Jelena a2f4041a1b Analyze kind support bundle 2021-04-12 23:50:15 +00:00
Andrew Reed 744523cc09 Merge pull request #351 from areed/concurrent-iops
Benchmark write latency with background IOPS
2021-04-12 16:06:13 -07:00
Andrew Reed 477cde7228 Benchmark write latency with background IOPS
Add a background IOPS feature to the filesystem performance collector
that specifies separate read and write background IOPS to perform while
measuring latency. This allows for better assessment of whether etcd
will be stable when running alongside other workloads on the same
cluster.

Also add templating to the outcome message of the filesystem performance
analyzers to allow printing individual latency percentiles or the entire
table.

Remove the random IOPS benchmark since it was attempting to perform
unaligned direct I/O.
2021-04-12 22:56:00 +00:00
divolgin ae63ccba8d Merge pull request #350 from replicatedhq/divolgin/so
remove troubleshoot.so from builds
2021-04-12 11:53:18 -07:00
divolgin 5c5e30a9a5 remove troubleshoot.so from builds 2021-04-12 18:50:58 +00:00
Salah Aldeen Al Saleh ac2a0484e2 add build flags to ffi (#349) 2021-04-12 11:23:46 -07:00
divolgin bc91151883 Merge pull request #348 from replicatedhq/divolgin/goreleaser
fix ffi build
2021-04-12 10:57:34 -07:00
divolgin de8feb167e fix ffi build 2021-04-12 17:22:21 +00:00
divolgin 0a6ef1c2c3 Merge pull request #347 from replicatedhq/divolgin/goreleaser
fix ffi build
2021-04-12 10:10:08 -07:00
divolgin 4a89067912 fix ffi build 2021-04-12 17:07:09 +00:00
divolgin 1e17c5c4c2 Merge pull request #346 from replicatedhq/divolgin/goreleaser
fix go-releaser build
2021-04-12 09:40:23 -07:00
divolgin 32cca1215a fix go-releaser build 2021-04-12 16:34:53 +00:00
divolgin 052d10fec7 Merge pull request #345 from replicatedhq/divolgin/images
use containers package instead of go-containerregistry
2021-04-12 08:42:46 -07:00
divolgin 7a0c6e5383 use containers package instead of go-containerregistry 2021-04-11 21:39:44 +00:00
divolgin 1dc03db254 Merge pull request #343 from replicatedhq/divolgin/images
Docker registry collector/analyzer
2021-04-09 09:25:29 -07:00
divolgin fe414af556 Docker registry collector/analyzer 2021-04-09 16:17:15 +00:00
Andrew Lavery f8dca39899 Merge pull request #342 from replicatedhq/laverya/improve-systemctl-service-analyzer
expand systemctl service analyzer to also match service sub/load
2021-04-02 15:33:02 -04:00
Andrew Lavery 19aef8a02f expand systemctl service analyzer to also match service sub/load 2021-04-02 14:48:24 -04:00
Andrew Lavery 4b6606e323 Merge pull request #341 from replicatedhq/laverya/systemctl-services-collector
systemctl services collector
2021-03-30 16:41:30 -04:00
Andrew Lavery 559e18d996 lowercase errors 2021-03-30 16:32:19 -04:00
Andrew Lavery bf4d26acd2 add host_services analyzer 2021-03-30 16:15:18 -04:00
Andrew Lavery f3b599c19a collect host systemctl services 2021-03-30 16:15:17 -04:00
Salah Aldeen Al Saleh 810b3cbf78 support non-interactive mode in support bundle (#340)
* support non-interactive mode in support bundle
2021-03-23 18:01:39 -07:00
Andrew Lavery 81789181ed Merge pull request #339 from replicatedhq/laverya/host-unmounted-partitions
added two parameters to the eligible block device check
2021-03-18 19:36:56 -04:00
Andrew Lavery 256c68feca added two parameters to the eligible block device check
whether to accept unmounted partitions (default false) and minimum acceptable device size (default 0)
2021-03-18 19:03:39 -04:00
divolgin b01e6ef578 Merge pull request #338 from replicatedhq/divolgin/preogress2
Add progress percentage
2021-03-18 16:02:11 -07:00
divolgin 62afc87af8 Add progress percentage 2021-03-18 22:29:27 +00:00
divolgin 17bff4b2bd Merge pull request #337 from replicatedhq/divolgin/progress
Report back some basic progress
2021-03-18 12:11:54 -07:00
divolgin 5f2525b663 Report back some basic progress 2021-03-18 18:56:27 +00:00
Salah Aldeen Al Saleh afa0bc56d4 fix custom redactors file selectors in support bundle subdirectory (#336)
* fix custom redactors file selectors in support bundle subdirectory
2021-03-11 08:45:20 -08:00
Salah Aldeen Al Saleh c1f9b3906d support reading redactors from configmaps (#335) 2021-03-10 15:25:55 -08:00
DexandSalah Aldeen Al Saleh 0a19d35073 hide spinner if interactive false (#328)
* hide preflight spinner if interactive is false

Co-authored-by: Salah Aldeen Al Saleh <salahalsaleh1993@gmail.com>
2021-03-09 09:42:38 -08:00
emosbaugh 7c4135d563 Merge pull request #334 from replicatedhq/host-preflgihts-ux
Host preflight ux improvements
2021-03-02 12:03:17 -08:00
Ethan Mosbaugh 4b78c430ca Host preflight ux improvements 2021-03-02 17:27:01 +00:00
Ethan Mosbaugh 09d16ff185 Host preflights exclude 2021-03-01 22:45:16 +00:00
Andrew Lavery bdf843f84d Merge pull request #332 from replicatedhq/laverya/add-regex-case-insensitive-test
add a test that uses a case-insensitive regex analyzer
2021-03-01 13:13:35 -05:00
Andrew Lavery 47f7d98907 add a test that uses a case-insensitive regex analyzer 2021-03-01 13:02:30 -05:00
emosbaugh a1e0813d55 Merge pull request #331 from replicatedhq/condition-analyzers 2021-02-26 07:22:38 -08:00
Ethan Mosbaugh d6acd6d906 Conditional Analyzers 2021-02-26 04:33:11 +00:00
Jalaja Ganapathy ce53dbcd29 Merge pull request #330 from replicatedhq/pv-pvc
add pv and pvcs to support bundle
2021-02-25 20:18:44 -08:00
Jalaja 3b10d9c9e1 add pv and pvcs to support bundle 2021-02-26 01:02:33 +00:00
emosbaugh 7589b4fed0 Merge pull request #329 from replicatedhq/host-diskUsage-traverse
diskUsage host collector traverse file tree for directory exists
2021-02-24 16:26:34 -08:00
Ethan Mosbaugh a459120516 diskUsage host collector traverse file tree for directory exists 2021-02-24 23:38:57 +00:00
Andrew Reed b02338762e Fix build for darwin and windows (#327)
* Fix build for darwin and windows

* Remove unexpected dependencies
2021-02-19 18:31:18 -05:00
Andrew Reed 76419237d4 Merge pull request #326 from areed/host-cert
Analyze TLS certificate
2021-02-19 16:30:27 -05:00
Andrew Reed 87b4c12274 Analyze TLS certificate 2021-02-19 20:55:16 +00:00
Dan Stough 7647c039e9 Merge pull request #325 from replicatedhq/feat/rke3-k3s-anaylzer
feat(analyzer): rke2 and k3s distro support
2021-02-19 14:52:22 -05:00
Dan Stough c26824a619 feat(analyzer): rke2 and k3s distro support 2021-02-19 19:06:02 +00:00
Andrew Reed 617e0d55de Merge pull request #324 from areed/fs-read-perf
Analyze random read IOPS for a directory
2021-02-19 13:34:28 -05:00
Andrew Reed b418334a46 Analyze random read IOPS for a directory
The random IOPS benchmark attempts to replicate the results of this
fio command:

fio --ioengine=psync --direct=1 --bs=4k --size=1Gi --readwrite=randread --serialize_overlap=1

Across three tests the fio command reported 1877 IOPS and the preflight
1822 IOPS with the same block and file size.
2021-02-18 23:56:51 +00:00
Andrew Reed b78d7d04d9 Merge pull request #323 from areed/host-fio
Analyze fs sequential write performance
2021-02-17 20:19:08 -05:00
Andrew Reed 989d5f7dbd Analyze fs write performance
The included example found P99 latency of 2.6ms.
Fio reported P99 latency of 2.5ms with this command:
fio --rw=write --ioengine=sync --fdatasync=1 --directory=/var/lib/etcd
--size=220m --bs=2300
2021-02-17 23:20:38 +00:00
Andrew Reed 8aca23199c Merge pull request #322 from areed/host-preflight-examples
Move host preflights examples into separate directory
2021-02-15 18:18:56 -05:00
Andrew Reed fe4db40b43 Move host preflights examples into separate directory
Add all supported analyzers to host preflight sample.
Don't log transient errors waiting for TCP connection.
Begin human stdout results on new line after spinner.
2021-02-15 22:46:12 +00:00
Andrew Reed 5eef177965 Merge pull request #321 from areed/host-interfaces
Analyze ipv4 interfaces
2021-02-15 16:05:11 -05:00
Andrew ReedandAndrew Lavery 6498c34da5 Analyze ipv4 interfaces
Co-authored-by: Andrew Lavery <laverya@umich.edu>
2021-02-15 20:54:53 +00:00
Andrew Reed b0a005796c Merge pull request #317 from areed/host-remote-port
Analyze TCP connection
2021-02-15 15:18:11 -05:00
Andrew Reed 1311064d21 Merge pull request #320 from areed/host-http-load-balancer
Analyze HTTP load balancer
2021-02-15 12:32:22 -05:00
Andrew Reed 450d7570eb Analyze HTTP load balancer 2021-02-15 17:22:42 +00:00
Andrew Reed 40af0f8a9c Analyze TCP connection 2021-02-12 21:45:57 +00:00
divolgin 529fe8cdbf Merge pull request #319 from replicatedhq/divolgin/cani
log not logs is the subresource
2021-02-12 11:40:36 -08:00
divolgin 105a718bbb log not logs is the subresource 2021-02-12 18:38:46 +00:00
divolgin c2b53036f9 Merge pull request #318 from replicatedhq/divolgin/cani
Fix can-i checks
2021-02-12 09:42:18 -08:00
divolgin ba22fe9f22 Fix can-i checks 2021-02-12 17:27:48 +00:00
Andrew Reed 8df8a5c792 Merge pull request #316 from areed/host-block-device
Analyze block devices
2021-02-11 14:50:22 -05:00
Andrew Reed 0bcd5183f5 Analyze block devices 2021-02-11 19:19:45 +00:00
Andrew Reed e2c0c722ae Merge pull request #315 from areed/host-time
Get time info from systemd
2021-02-10 15:30:49 -05:00
Andrew Reed 9984fe2caa Get time info from timedated 2021-02-10 20:01:15 +00:00
Andrew Reed f2e4127111 Merge pull request #314 from areed/host-preflight-urls
Host HTTP request analyzer
2021-02-10 10:56:54 -05:00
Andrew Reed f25149f45c Host HTTP request analyzer 2021-02-09 20:31:28 +00:00
Andrew Reed 2a06cb25e4 Merge pull request #313 from areed/fix-darwin-build
Fix build for darwin amd64
2021-02-08 18:00:49 -05:00
Andrew Reed 86bc366ec3 Fix build for darwin amd64 2021-02-08 22:47:06 +00:00
Andrew ReedandMarc Campbell 10a34c2e58 Host preflight (#311)
* Add HostPreflight v1beta2

* Work on TCP Load Balancer

* Host disk usage collector and analyzer

* Host memory analyzer

* TCP port status

* TCP load balancer

* Review changes

Co-authored-by: Marc Campbell <marc.e.campbell@gmail.com>
2021-02-08 16:09:01 -05:00
Marc Campbell df68f7445f Merge pull request #310 from replicatedhq/remove-scope
Removing Scopeagent
2021-01-28 10:31:24 -08:00
Marc Campbell c7fdec0291 Removing Scopeagent 2021-01-28 18:22:48 +00:00
divolgin e8dba3cad9 Merge pull request #309 from replicatedhq/divolgin/secrets
Create pull secrets if they don't have names
2021-01-08 12:21:04 -08:00
divolgin 3e2d90ee9b Create pull secrets if they don't have names 2021-01-08 20:01:47 +00:00
Salah Aldeen Al Saleh b05eb6bf75 fix subdirectory missing in support bundle issue (#308) 2020-12-08 12:52:29 -08:00
Andrew Lavery 2e16424b44 Merge pull request #307 from replicatedhq/laverya/fix-node-resources-label-filtering
fix node resources label filtering
2020-12-04 10:14:23 -05:00
Andrew Lavery f19ac98055 add tests for analyzeNodeResources, including label filtering 2020-12-03 19:19:57 -05:00
Andrew Lavery 55fbd92673 not finding a label is not an error 2020-12-03 19:17:47 -05:00
Andrew Lavery 2f2edb5356 Merge pull request #302 from replicatedhq/laverya/dont-rbac-check-excluded-collectors
check whether a collector is excluded before checking RBAC for it
2020-11-19 19:44:41 -05:00
Andrew Lavery 0ec1c43afd update setup-kind action 2020-11-19 18:57:52 -05:00
Andrew Lavery b43ef17b8f remve set-env and add-path from CI 2020-11-19 18:37:57 -05:00
Andrew Lavery 858d00ce41 check whether a collector is excluded before checking RBAC for it 2020-11-19 18:31:56 -05:00
emosbaugh c81576f25f Merge pull request #299 from replicatedhq/ceph-no-name
Ceph collector does not need a name property
2020-11-13 13:03:05 -08:00
Ethan Mosbaugh 1e8e20a295 Ceph collector does not need a name property 2020-11-13 21:01:02 +00:00
emosbaugh 4cdfa5b112 Merge pull request #298 from replicatedhq/ceph-format
Fix Ceph collector file extension
2020-11-13 12:17:48 -08:00
Ethan Mosbaugh 8ef720ba9e Fix Ceph collector file extension 2020-11-13 20:02:15 +00:00
divolgin 7d2e0d0aa3 Merge pull request #297 from replicatedhq/divolgin/fix
fixing build
2020-11-13 09:54:03 -08:00
divolgin 88685ae5f7 fixing build 2020-11-13 17:49:43 +00:00
divolgin 364a63533a Merge pull request #296 from replicatedhq/divolgin/releaser
Revert changes for static linking
2020-11-13 09:37:31 -08:00
divolgin 6749f339e8 Revert changes for static linking 2020-11-13 17:34:08 +00:00
emosbaugh 2bf19eaddf Ceph collectors and analyzers (#295)
* Ceph collectors and analyzers

* updating based on prior pr

* fixes

* fixes
2020-11-13 09:12:42 -08:00
divolgin fd6af65f7e Merge pull request #294 from replicatedhq/divolgin/no-rrd
Remove RRD dependency and switch to dynamic linking
2020-11-12 11:28:07 -08:00
divolgin 9e669b3f13 Remove RRD dependency and switch to dynamic linking 2020-11-12 19:13:25 +00:00
divolgin 4e74fd209e Merge pull request #293 from replicatedhq/divolgin/fix
fix build
2020-11-10 22:00:21 -08:00
divolgin a00a1892d9 include darwin builds in archives 2020-11-11 02:10:30 +00:00
divolgin 474a874f82 Merge pull request #292 from replicatedhq/divolgin/fix
fixing build
2020-11-10 16:38:49 -08:00
divolgin 463ba62ffa fixing build 2020-11-11 00:26:53 +00:00
divolgin 46194fccb7 Merge pull request #291 from replicatedhq/divolgin/fix
fixing build
2020-11-10 14:59:59 -08:00
divolgin badedf34ee fixing build 2020-11-10 22:55:21 +00:00
divolgin af2f49cb07 Merge pull request #271 from manavellamnimble/fixImagePullSecretAndTextAnalyzer
ImagePullSecret and TextAnalyzer with regex fixed
2020-11-10 09:40:10 -08:00
divolgin 88a6d3f715 Merge pull request #290 from replicatedhq/divolgin/rrd
Collector for RRD data
2020-11-10 09:19:46 -08:00
divolgin 5a1321da02 Collector and analyzer for RRD data 2020-11-10 17:19:17 +00:00
divolgin 014a716949 Merge pull request #287 from manavellamnimble/addLogFlags
added flag --since-time for Logs Collectors
2020-10-29 15:20:10 -07:00
Matias Manavella ad4893bec5 default message 2020-10-29 18:19:32 -03:00
Matias Manavella 989093394c test fixed 2020-10-29 17:47:37 -03:00
Matias Manavella f1868d0ba8 return messages modified 2020-10-22 14:42:05 -03:00
Matias Manavella 3cbdb41c8f return error when both flags are used 2020-10-22 14:35:08 -03:00
Matias Manavella d2f6594c0c return error when both flags are used 2020-10-22 14:31:34 -03:00
Matias Manavella 56408fab01 return error when both flags are used 2020-10-22 14:28:35 -03:00
Matias Manavella f0d9418e21 parseTimeFlag function and error handling added 2020-10-22 12:26:29 -03:00
Matias Manavella 1ba3840ad9 parseTimeFlag function and error handling added 2020-10-22 11:37:52 -03:00
Matias ManavellaandMark Pundsack a3d667298e Update cmd/preflight/cli/root.go
Co-authored-by: Mark Pundsack <markpundsack@users.noreply.github.com>
2020-10-22 10:13:45 -03:00
Matias ManavellaandMark Pundsack 5cf4ae2157 Update cmd/preflight/cli/root.go
Co-authored-by: Mark Pundsack <markpundsack@users.noreply.github.com>
2020-10-22 10:13:32 -03:00
Matias ManavellaandMark Pundsack dede187841 Update cmd/troubleshoot/cli/root.go
Co-authored-by: Mark Pundsack <markpundsack@users.noreply.github.com>
2020-10-22 09:26:29 -03:00
Matias ManavellaandMark Pundsack 7dc6e22d8d Update cmd/troubleshoot/cli/root.go
Co-authored-by: Mark Pundsack <markpundsack@users.noreply.github.com>
2020-10-22 09:26:11 -03:00
Matias Manavella f3af73b6e3 nil and error handling 2020-10-21 14:49:46 -03:00
Matias Manavella 4e047b2372 nil and error handling 2020-10-21 14:47:25 -03:00
Matias ManavellaandSalah Aldeen Al Saleh 7f190e3cce Update cmd/troubleshoot/cli/run.go
Co-authored-by: Salah Aldeen Al Saleh <salahalsaleh1993@gmail.com>
2020-10-21 13:59:51 -03:00
Matias ManavellaandSalah Aldeen Al Saleh 2436a0c163 Update cmd/preflight/cli/root.go
Co-authored-by: Salah Aldeen Al Saleh <salahalsaleh1993@gmail.com>
2020-10-21 13:59:24 -03:00
Matias Manavella 883abacaf8 --since flag added 2020-10-21 09:59:10 -03:00
Matias Manavella 7186b75f7e --since flag added 2020-10-21 09:51:52 -03:00
Matias Manavella e16eabd531 added flag --since-time 2020-10-19 16:53:13 -03:00
Salah Aldeen Al Saleh 3ff91a3b92 support bundle subdirectory (#285) 2020-10-19 11:11:56 -07:00
Marc Campbell 2020049cb7 Merge pull request #283 from manavellamnimble/fixFilePath
Filepath fixed
2020-10-14 19:02:41 -07:00
Salah Aldeen Al Saleh d94954e6dd use '_' instead of ':' in support bundle name format (#284) 2020-10-14 15:57:26 -07:00
Matias Manavella 06817c1682 Filepath fixed 2020-10-14 15:01:00 -03:00
divolgin 0554c2ac0f Merge pull request #278 from replicatedhq/divolgin/insecure
Retry http requests on x509 errors if allowed
2020-10-06 14:44:36 -07:00
divolgin 1087eb65d2 Retry http requests on x509 errors if allowed 2020-10-06 21:42:04 +00:00
divolgin 09dc6b5862 Merge pull request #276 from replicatedhq/divolgin/panic
Don't panic when pod is in a waiting state
2020-10-05 17:27:04 -07:00
divolgin 3d301f4307 Don't panic when pod is in a waiting state 2020-10-06 00:24:46 +00:00
divolgin 446b1d5552 Merge pull request #274 from manavellamnimble/removeImagePullSecretPathSupport
Remove image pull secret path support
2020-10-05 16:55:46 -07:00
divolgin 63c8422e63 Merge pull request #270 from manavellamnimble/secretAnalyzerFixed
Secret analyzer fixed
2020-10-05 16:51:28 -07:00
divolgin 616f6e73a5 Merge pull request #273 from replicatedhq/divolgin/preflight
Allow preflight spec to be loaded from a secret
2020-10-01 12:12:29 -07:00
Matias Manavella 213b52477f Run collectors docs modified 2020-10-01 13:53:54 -03:00
Matias Manavella e9ba73d87f Support for path to config.json file removed 2020-10-01 13:42:29 -03:00
divolgin 6e86cdc803 Allow preflight spec to be loaded from a secret 2020-10-01 01:37:37 +00:00
divolgin c023a81966 Merge pull request #272 from replicatedhq/divolgin/secrets
Support loading spec from a secret
2020-09-30 16:21:10 -07:00
divolgin 7d0bb1a5d7 Support loading spec from a secret 2020-09-30 23:06:42 +00:00
Matias Manavella 3cf679260e ImagePullSecret and TextAnalyzer with regex fixed 2020-09-30 18:06:52 -03:00
Matias Manavella 53bd30755d secret analyzer fixed 2020-09-29 11:42:21 -03:00
divolgin 7fe7216b29 Merge pull request #268 from manavellamnimble/postgressVersion
Error Parsing Postgres Version
2020-09-24 15:43:28 -07:00
Matias Manavella 2da1f518d3 parse tolerant 2020-09-23 15:10:54 -03:00
divolgin 8a30f2ddce Merge pull request #269 from manavellamnimble/distributionEnhacement
Distribution enhacement
2020-09-23 08:53:19 -07:00
Matias Manavella 0ea4e1d52f distribution_test fixed 2020-09-22 18:10:28 -03:00
Matias Manavella 74c9ff2432 add ibm and minikube to distribution analyzer 2020-09-22 17:36:27 -03:00
Matias Manavella bfa50c9643 add ibm and minikube to distribution analyzer 2020-09-22 17:32:41 -03:00
Matias Manavella 74a7e5f19c add ibm and minikube to distribution analyzer 2020-09-22 16:31:52 -03:00
Matias Manavella e3c954f460 add ibm and minikube to distribution analyzer 2020-09-22 16:17:47 -03:00
Matias Manavella 16d3ff372f add ibm and minikube to distribution analyzer 2020-09-22 16:08:03 -03:00
Matias Manavella 437357f099 Filename fixed 2020-09-21 11:06:15 -03:00
Matias Manavella 955e08c35a fixed varsion formats 2020-09-17 17:38:42 -03:00
divolgin 58261cdaf2 Merge pull request #267 from manavellamnimble/fixIngress
ingres analyzer fixed
2020-09-17 08:55:14 -07:00
divolgin 545313aa06 Merge pull request #260 from manavellamnimble/abortImagePullBackoff
Abort run collector on ImagePullBackoff
2020-09-17 08:54:39 -07:00
divolgin 1ceab64b6f Merge pull request #259 from manavellamnimble/emptyKeySecret
fixEmptyKeySecret
2020-09-17 08:50:39 -07:00
Matias Manavella eb0f692aa0 using filepath instead of path 2020-09-16 18:25:15 -03:00
Matias Manavella 2ae1b9b678 abort run collector on ImagePullBackOff 2020-09-16 18:16:32 -03:00
Matias Manavella 2f2501ac3b fix empty key in secret 2020-09-16 18:12:19 -03:00
Matias Manavella a57894962d ingres analyzer fixed 2020-09-16 18:04:46 -03:00
Bryant Hagadorn 3f48574071 Add all auth providers (#266)
* Update main.go

* Adding generic auth for OIDC
2020-09-15 15:34:10 -07:00
Matias Manavella 00bbfc0414 Abort run collector on ImagePullBackoff 2020-09-11 10:20:39 -03:00
Matias Manavella c4d4af6890 fixEmptyKeySecret 2020-09-10 13:01:31 -03:00
Salah Aldeen Al Saleh 4149e4d6ed this is an empty commit (#256) 2020-09-09 08:53:29 -07:00
Salah Aldeen Al Saleh b2cb3bf43b handle nil ImagePullSecret in collector (#255) 2020-09-09 07:41:34 -07:00
divolgin e232cc0f34 Merge pull request #253 from manavellamnimble/runImagePullSecret
Add or create ImagePullSecret  in a run collector
2020-09-08 13:59:25 -07:00
Andrew Lavery f68e0dbae0 Merge pull request #174 from replicatedhq/laverya/allow-analyzing-all-files-in-dir
allow textAnalyze to run on all files in a dir or matching a prefix
2020-09-08 14:43:58 -04:00
Andrew Lavery 0126fb7d7a Merge remote-tracking branch 'origin/master' into laverya/allow-analyzing-all-files-in-dir 2020-09-08 14:27:26 -04:00
Andrew Lavery d2bc571a18 Merge pull request #250 from manavellamnimble/defaultStorageClass
Check for Default Storage Class when storageClassName is empty
2020-09-08 14:25:36 -04:00
Matias Manavella 1f0842484c error-handling modified 2020-09-07 11:33:06 -03:00
Matias Manavella 8c31054331 error-handling modified 2020-09-07 11:21:23 -03:00
Matias Manavella 4b2e7e153e add or create ImagePullSecret 2020-09-04 12:41:47 -03:00
Marc Campbell 2289e00558 Merge pull request #252 from replicatedhq/fix-statefulset-status
Fix statefulset status
2020-09-03 14:00:16 -07:00
Marc Campbell 949f0f2213 Fix statefulset status 2020-09-03 13:48:25 -07:00
divolgin 703219119e Merge pull request #251 from replicatedhq/divolgin/v1beta2
Adding troubleshoot.sh/v1beta2
2020-09-01 15:19:19 -07:00
Matias Manavella 5522b0623c check Default SC 2020-09-01 19:07:13 -03:00
Matias Manavella 8b1ae0194e check Default SC 2020-09-01 18:36:55 -03:00
divolgin a0ce85ae1e Adding troubleshoot.sh/v1beta2 2020-09-01 19:57:11 +00:00
Matias Manavella b1e251ed03 selector:MatchLabel (#249)
* selector:MatchLabel

* selector:MatchLabel
2020-08-31 09:46:04 -07:00
Matias Manavella f7e4103d9b check Default SC 2020-08-31 11:54:49 -03:00
Matias Manavella 442c97f138 check Default SC 2020-08-31 11:52:45 -03:00
Matias Manavella 6862f0f6c1 K8s events (#248)
* K8s events collected

* collect events

* collect events
2020-08-24 14:41:38 -07:00
Matias Manavella 6ad9103f86 Copy collector enhanced (#237)
Copy collector enhanced
2020-08-24 10:57:40 -07:00
divolgin 016d6e4f18 Merge pull request #246 from manavellamnimble/add_checkNames
checkName in Distribution and Runtime
2020-08-18 15:55:31 -07:00
Matias Manavella 97db83b270 checkName in Distribution and Runtime 2020-08-18 13:57:53 -03:00
GraysonNull 20e82be101 Merge pull request #244 from GraysonNull/grayson-termui-scrolling
Add scrolling to table, use table widget for support bundle
2020-08-13 12:49:29 -05:00
GraysonNull 4e08ce4d93 remove commented code blocks, move appName func to shared package 2020-08-13 16:38:51 +00:00
GraysonNull e8dc5ae1b8 use table widget for bundle analysis so scrolling works 2020-08-13 16:02:29 +00:00
GraysonNull 0e667e9685 scrolling on analyzers table 2020-08-11 15:16:23 +00:00
Andrew Lavery 99f5e2d896 Merge pull request #238 from replicatedhq/laverya/latest-controller-gen
update controller-gen to v0.3.0
2020-08-10 17:55:45 -04:00
Andrew Lavery 407b80daf5 update controller-gen to v0.3.0
the first version to be k8s 1.18 compatible
2020-08-10 17:51:53 -04:00
Marc Campbell c84dc6de45 Merge pull request #233 from replicatedhq/support-bundle-command
Update help text to match the command
2020-08-08 06:47:45 -07:00
Matias Manavella a686e47fa2 Issue#228 (#230)
* Added timestamp to support-bundle file

* Added timestamp to support-bundle file

* Added timestamp to support-bundle file

* Added timestamp with second-level precision
2020-08-03 15:09:21 -07:00
Marc Campbell 56e58c0849 Update help text to match the command 2020-08-03 11:55:19 -07:00
GraysonNull 3b8e53bf90 Merge pull request #225 from GraysonNull/grayson/update-samples
fix invalid analyzer in sample support-bundle
2020-07-13 17:36:00 -05:00
GraysonNull cc9d3aedec move logs to collectors array 2020-07-13 22:26:17 +00:00
GraysonNull a70843cd69 add space 2020-07-13 22:07:37 +00:00
GraysonNull 08c52770a9 fix invalid analyzer in sample support-bundle 2020-07-13 22:06:37 +00:00
Mark Pundsack 52e385ffce Merge pull request #224 from replicatedhq/markpundsack-patch-1
Update URL
2020-07-13 16:24:51 -05:00
Mark Pundsack d63321bc43 Update URL 2020-07-13 16:19:01 -05:00
GraysonNull 37ae457aa1 Merge pull request #223 from GraysonNull/grayson/update-samples
update sample preflight and support bundles, update directory name
2020-07-13 14:14:30 -05:00
GraysonNull 4b1852c3e1 updates from feedback 2020-07-13 16:45:46 +00:00
GraysonNull dc80733397 update sample preflight and support bundles, update diretory name 2020-07-13 15:43:10 +00:00
GraysonNull 78e328be86 Merge pull request #219 from replicatedhq/msp-update-readme
Update readme
2020-07-07 10:50:57 -05:00
Mark Pundsack ea43d4d9b6 Simplify language 2020-07-06 12:23:16 -05:00
Mark Pundsack 8ce751f989 Update readme 2020-07-06 12:14:08 -05:00
Salah Aldeen Al Saleh f55b9b6ae4 update schemas + add redactor and supportbundle schemas (#218) 2020-06-23 10:08:59 -07:00
Andrew Lavery 086f85845a Merge pull request #217 from replicatedhq/laverya/krew-yaml-refactor
refactor krew yaml to match upstream format
2020-06-17 14:45:54 -04:00
Andrew Lavery eb90b6d935 remove extra trailing whitespace 2020-06-17 14:44:20 -04:00
Andrew Lavery 13df9a0f87 refactor krew yaml to match upstream format 2020-06-17 14:37:38 -04:00
Andrew Lavery 89b4979cbc Merge pull request #216 from replicatedhq/laverya/redactor-reformat
redactor reformat
2020-06-15 14:02:40 -04:00
Andrew Lavery 6e874483b6 update yaml key name, fixup example troubleshoot 2020-06-15 13:55:07 -04:00
Andrew Lavery afd2ee95ca Merge remote-tracking branch 'origin/master' into laverya/redactor-reformat 2020-06-15 11:21:37 -04:00
Andrew Lavery e66d12dab2 combine multiline and single line regex 2020-06-15 11:15:50 -04:00
Marc Campbell d98172eb9f Merge pull request #215 from replicatedhq/analyzer-cli
Interactive results for support bundle kinds
2020-06-12 14:48:08 -07:00
Marc Campbell b070b4009c Interactive results for support bundle kinds 2020-06-12 14:26:48 -07:00
Marc Campbell 890cbb1378 Merge pull request #214 from replicatedhq/analyzer-cli
Refactor to support K8s 1.18
2020-06-12 13:41:00 -07:00
Marc Campbell 0f1f8b511e checkout before download 2020-06-12 13:32:30 -07:00
Marc Campbell 19fb95e99b fix workflow 2020-06-12 13:24:30 -07:00
Marc Campbell a22e2e25df Analyze from the CLI 2020-06-12 12:47:45 -07:00
Marc Campbell 8d991e1f9e fix workflow 2020-06-12 10:25:34 -07:00
Marc Campbell 91e856d6d5 Add validation for collectors and support bundle in e2e 2020-06-12 10:23:28 -07:00
Marc Campbell 65f957db81 Refactor to support K8s 1.18 2020-06-12 09:28:49 -07:00
Andrew Lavery a561254756 break apart redactor type 2020-06-09 18:43:44 -04:00
Salah Aldeen Al Saleh 53626bb025 Default BoolString to string and bool to 0 (#211)
* default boolstring to string and bool to 0
2020-06-01 14:55:33 -07:00
Andrew Lavery 54d8d7585d Merge pull request #208 from replicatedhq/laverya/don-t-use-goreleaser-binary-template
use hardcoded binary name, not {{ .Binary }}
2020-05-28 21:29:11 -04:00
Andrew Lavery 4021a6c176 use hardcoded binary name, not {{ .Binary }} 2020-05-28 21:18:03 -04:00
Andrew Lavery 8c9734c19c Merge pull request #207 from replicatedhq/laverya/krew-autodeploy
goreleaser no longer includes .exe in download links
2020-05-27 18:07:29 -04:00
Andrew Lavery b6ac6e4702 goreleaser no longer includes .exe in download links 2020-05-27 18:03:58 -04:00
Andrew Lavery f256bdb653 Merge pull request #206 from replicatedhq/laverya/tidy
go mod tidy
2020-05-27 17:34:08 -04:00
Andrew Lavery 1c3496e2f7 go mod tidy 2020-05-27 17:24:17 -04:00
Andrew Lavery f5d737f2c5 Merge pull request #204 from replicatedhq/divolgin/panic
Don't panic when parsing resources, return error
2020-05-27 17:08:02 -04:00
Andrew Lavery 619c4550bc Merge pull request #203 from replicatedhq/laverya/better-default-redactor-names
better default redactor names
2020-05-27 16:31:22 -04:00
Marc Campbell 6f42f85705 Merge pull request #205 from replicatedhq/naming
Update names
2020-05-27 13:30:30 -07:00
Marc Campbell 661d7fcfc4 Update names 2020-05-27 13:10:46 -07:00
divolgin 47e715a350 Don't panic when parsing resources, return error 2020-05-27 19:56:23 +00:00
Andrew Lavery b9c3ad2635 better default redactor names 2020-05-27 14:36:40 -04:00
Andrew Lavery 2787cf385c Merge pull request #202 from replicatedhq/laverya/is-default-redaction
include whether a redaction is from a default redactor in reports
2020-05-27 14:08:23 -04:00
Andrew Lavery f03916cfd2 include whether a redaction is from a default redactor in reports 2020-05-27 13:46:39 -04:00
Andrew Lavery 252b29fb0a Merge pull request #201 from replicatedhq/laverya/better-redactor-names
default redactor name improvements
2020-05-26 19:49:32 -04:00
Andrew Lavery 553718eada fully spell out default redactor names 2020-05-26 19:33:40 -04:00
Andrew Lavery 171c440f27 improve generated names for custom redactors 2020-05-26 18:13:48 -04:00
Andrew Lavery 869a9eafd3 actually increment withinRedactNum 2020-05-26 18:07:23 -04:00
Andrew Lavery 6c61040f74 default redactor name improvements
for instance, defaultRegex.SECRET_ACCESS_KEY instead of the raw regex
2020-05-26 17:15:30 -04:00
Andrew Lavery bde882047f Merge pull request #199 from replicatedhq/laverya/redaction-reports
add yaml/json annotations for redaction reports
2020-05-20 15:03:25 -04:00
Andrew Lavery 0d84c62c78 add yaml/json annotations for redaction reports 2020-05-20 14:58:37 -04:00
Andrew Lavery f5183c62d6 Merge pull request #198 from replicatedhq/laverya/redaction-reports
redaction reports framework
2020-05-20 14:43:29 -04:00
Andrew Lavery 5a2c153026 add tests for redaction reports 2020-05-20 14:36:07 -04:00
Andrew Lavery 669cb2a145 send redaction report 2020-05-20 13:08:10 -04:00
Andrew Lavery fb2f028fb5 add methods to get and clear redactions 2020-05-20 10:28:46 -04:00
Andrew Lavery d37ace6e51 better naming scheme that does not leak secrets 2020-05-19 17:21:55 -04:00
Andrew Lavery b6e92e1bdf record yaml redactions 2020-05-14 18:49:30 -04:00
Andrew Lavery 27369acbf4 plumbing for literal/regex/multiline reports 2020-05-14 16:00:58 -04:00
Andrew Lavery 22d397cc7b Merge pull request #190 from MikaelSmith/error-on-connect-fail
Report errors connecting to the database
2020-05-13 19:38:20 -04:00
Andrew Lavery 428db221c3 Merge pull request #197 from replicatedhq/laverya/automate-krew-releases
automate krew releases
2020-05-13 19:09:53 -04:00
Andrew Lavery f6a5d40bfd Merge pull request #195 from replicatedhq/laverya/goreleaser-action-v2
use v2 of the goreleaser-action workflow
2020-05-13 19:07:55 -04:00
Andrew Lavery 8bc627d20f automate krew releases
this might work, might not - the action is only intended for one app per repo, but since it's all in one release I think it'll be fine
2020-05-13 19:04:27 -04:00
Andrew Lavery 7c95363afe Merge pull request #196 from replicatedhq/laverya/remove-unused-replace
remove an unused replace statement
2020-05-13 18:15:13 -04:00
Andrew Lavery f7aebd0745 remove an unused replace statement 2020-05-13 16:55:41 -04:00
Andrew Lavery 523332268b Merge pull request #194 from replicatedhq/laverya/go-1.14
use go 1.14 in ci
2020-05-13 16:52:41 -04:00
Andrew Lavery ca6f118c62 use v2 of the goreleaser-action workflow 2020-05-13 15:49:44 -04:00
Andrew Lavery 769d616ede use go 1.14 in ci 2020-05-13 15:35:10 -04:00
Salah Aldeen Al Saleh 620343e3a1 convert type BoolString to oneOf for api-schema (#193) 2020-05-11 12:57:27 -07:00
Marc Campbell 994978ccd8 Merge pull request #192 from replicatedhq/pg-collector
Parse postgres version output
2020-05-08 06:36:29 -07:00
Marc Campbell 0f31088bd1 Parse postgres version output 2020-05-07 19:41:59 -07:00
Michael Smith 4b9680be8b Report errors connecting to the database
If the postgres collector encounters an error, report it as a failure in
the analyzer. Otherwise the error is completely suppressed.

Fixes #187.
2020-05-07 17:04:10 -07:00
Andrew Lavery 20033b12d5 Merge pull request #188 from replicatedhq/laverya/improve-unexpected-operator-error
include the operator in the 'unexpected operator' error message
2020-05-07 18:39:59 -04:00
Andrew Lavery f795f909b3 include all the data 2020-05-07 18:15:33 -04:00
Andrew Lavery b3828b175d include the operator in the 'unexpected operator' error message 2020-05-07 18:04:37 -04:00
Andrew Lavery fa84d3fbd3 Merge pull request #180 from MikaelSmith/fix-allocatable-sum
Fix sum(memoryAllocatable) and sum(podAllocatable)
2020-05-07 17:42:32 -04:00
Andrew Lavery f377b7c1a8 Merge pull request #185 from replicatedhq/laverya/add-multiline-and-yaml-to-example
add multiline redactor and yaml to example spec
2020-04-27 22:06:38 -04:00
Andrew Lavery 6d3321cb43 Merge pull request #186 from replicatedhq/laverya/redact-yaml-star-map-support
support * when redacting yaml maps
2020-04-27 22:03:40 -04:00
Andrew Lavery 15b100e0ee support * when redacting yaml maps 2020-04-27 22:01:04 -04:00
Andrew Lavery cd84cfa629 add multiline redactor and yaml to example spec 2020-04-27 21:47:52 -04:00
Andrew Lavery 94ccf284b8 Merge pull request #184 from replicatedhq/laverya/custom-multiline-and-yaml-redactors
custom multiline and yaml redactors
2020-04-27 21:20:35 -04:00
Andrew Lavery 2f092ae4a1 add multiline redactor test 2020-04-27 20:52:01 -04:00
Andrew Lavery 56150c3345 add support for redacting items within yaml documents 2020-04-27 20:46:52 -04:00
Andrew Lavery 8f594e8764 add support for custom multiline redactors, add yaml redactors to spec 2020-04-27 16:50:25 -04:00
Andrew Lavery 7752a33268 Merge pull request #183 from replicatedhq/laverya/allow-specifying-multiple-redact-specs
allow specifying multiple redact specs
2020-04-27 16:28:58 -04:00
Andrew Lavery 94e27eb5e1 allow specifying multiple redact specs 2020-04-27 14:37:51 -04:00
Andrew Lavery 33580e9611 Merge pull request #182 from replicatedhq/laverya/no-regex-panic-when-not-found
analyzeRegexGroups should not have out of range error upon no match
2020-04-23 15:29:23 -04:00
Andrew Lavery 09bc81e144 analyzeRegexGroups should not have out of range error upon no match 2020-04-23 15:26:01 -04:00
Andrew Lavery 7626f7d7d7 Merge pull request #181 from replicatedhq/laverya/use-glob-file-matching
use gobwas/glob, not filepath, file matching
2020-04-23 13:23:31 -04:00
Andrew Lavery 37f75c1a3f use gobwas/glob, not filepath, file matching 2020-04-23 13:13:46 -04:00
Michael Smith 8f8b8b2c78 Fix sum(memoryAllocatable) and sum(podAllocatable)
Fixes `sum(memoryAllocatable)` and `sum(podAllocatable)`. These
previously tested the wrong resource (cpuAllocatable).

Also refactor comparison functions to unify resolving properties and add
more testing.

Fixes #179.
2020-04-21 11:39:31 -07:00
Andrew Lavery b1e1dbb42a Merge pull request #178 from replicatedhq/laverya/support-multidoc-collector-and-redactor-input
allow providing redactors as multidoc yaml after collectors
2020-04-21 14:15:51 -04:00
Michael Smith 1605b56090 Simplify tests by reusing same node data
Remove repetition across test cases that made it hard to read. Tweaks
tests where needed so they can all use the same node data. Also corrects
a test where the description didn't match the test.
2020-04-21 11:08:03 -07:00
Andrew Lavery a58913d1f6 allow providing redactors as multidoc yaml after collectors 2020-04-20 17:08:39 -04:00
Andrew Lavery eb84fc64e1 Merge pull request #177 from replicatedhq/laverya/remove-per-collector-redactors
remove per-collector redactors
2020-04-20 15:56:59 -04:00
Andrew Lavery 087505f8e5 fix example yaml 2020-04-20 15:44:19 -04:00
Andrew Lavery 8b54c28b4b remove per-collector redactors 2020-04-20 14:59:15 -04:00
Andrew Lavery 7be40ddf16 Merge pull request #176 from replicatedhq/laverya/include-collect-global-redactors
honor global redactors from collect spec
2020-04-17 13:15:50 -04:00
Andrew Lavery de9b832357 honor global redactors from collect spec 2020-04-17 13:06:52 -04:00
Andrew Lavery fc65ceb5b4 Merge pull request #175 from replicatedhq/laverya/custom-redactors
last-mile and per-collector redactor specs
2020-04-16 14:22:10 -04:00
Andrew Lavery d016e3269c add global and per-collector redactors
add redact type, and begin wiring global redactors

use per-collector redactors

add a test of the 'data' collector and redaction

handle literal string replacements

remove redundant types and redact calls

add proper redactor type, foundations of global redactors

accept global redactors from the CLI, include sample redaction spec
2020-04-16 14:03:00 -04:00
Andrew Lavery 079765b558 add 'no matching files' analyze result 2020-04-15 19:17:01 -04:00
Andrew Lavery 45ccd7be5b don't conglomerate results
doing so sort of breaks the 'invalid analyzer' message if no files match
2020-04-15 19:13:37 -04:00
Andrew Lavery 2bc9938a2a use filepath.Glob and filepath.Match 2020-04-15 18:59:17 -04:00
Andrew Lavery 5050f46b1e use gobwas/glob to match globs 2020-04-15 18:47:16 -04:00
Andrew Lavery 222a93162d allow textAnalyze to run on all files in a dir or matching a prefix 2020-04-15 18:08:08 -04:00
Andrew Lavery f06cd9e4a2 Merge pull request #172 from replicatedhq/laverya/refactor-byte-array-interfaces
refactor byte array interfaces
2020-04-14 18:14:57 -04:00
Andrew Lavery 7dc93ddade don't redact nil entries, discard them 2020-04-14 17:59:12 -04:00
Andrew Lavery a7c4f04a63 convert remaining collectors to map[string][]byte format 2020-04-14 17:15:53 -04:00
Andrew Lavery 527fe16bcc reduce marshal/unmarshal passes by returning map[string][]byte
WIP
2020-04-14 16:37:51 -04:00
Andrew Lavery 406e1e6d1a Merge pull request #168 from replicatedhq/laverya/collect-logs-from-all-containers-in-pod
collect logs from all containers in a pod if no container is specified
2020-04-08 18:46:06 -04:00
Andrew Lavery cbaf96691e collect logs from all containers in a pod if no container is specified 2020-04-08 16:05:44 -04:00
Andrew Lavery 4dfb02e7f7 Merge pull request #167 from replicatedhq/laverya/include-container-in-copy-path-if-provided
include the container name in the file copy path destination if provided
2020-04-06 18:29:45 -04:00
Andrew Lavery e19a5dee38 Merge pull request #166 from replicatedhq/laverya/respect-secret-includevalue-flag
support the 'includeValue' flag for secrets
2020-04-06 18:09:43 -04:00
Andrew Lavery 2c495b8a7a include the container name in the file copy path destination if provided 2020-04-06 18:02:37 -04:00
Andrew Lavery c3646bacd9 don't use a default filename in paths 2020-04-06 18:01:13 -04:00
Andrew Lavery 3844a3dbd3 don't override namespace 2020-04-06 17:44:57 -04:00
Andrew Lavery 544c832d6e support the 'includeValue' flag for secrets 2020-04-06 17:03:19 -04:00
Marc Campbell 38aef191ab Merge pull request #162 from ashwathishiva/fix_win_path_bug
textanalyze: fixes path handling in windows as well
2020-03-26 16:07:05 -07:00
Andrew Lavery 545ce24c04 Merge pull request #164 from replicatedhq/laverya/fix-build-after-k8s-1.18
fix build after k8s 1.18 was released
2020-03-26 18:42:30 -04:00
Andrew Lavery c262320cea fix build after k8s 1.18 was released 2020-03-26 18:50:23 +00:00
Ashwathi Shiva d1c45f1456 fixes path handling in windows as well 2020-03-26 00:58:40 -04:00
Andrew Lavery c4f841d420 Merge pull request #161 from replicatedhq/laverya/check-filepath-before-attempting-url
attempt to read the file at the provided path before trying url
2020-03-25 17:59:23 -04:00
Andrew Lavery 75ab7bb917 fix downloadAnalyzerSpec function too 2020-03-25 17:32:52 -04:00
Andrew Lavery 9692d5a457 attempt to read the file at the provided path before trying url 2020-03-25 17:27:16 -04:00
Marc Campbell 2775a6393e Docker login 2020-03-23 11:20:50 -07:00
Marc Campbell b0c46c5ac8 Rename 2020-03-23 11:03:01 -07:00
Marc Campbell e9ad961c0e Merge pull request #160 from replicatedhq/build-on-actions
Move all to github actions
2020-03-23 10:43:09 -07:00
Marc Campbell bd71222715 Removing more unused code 2020-03-23 10:01:30 -07:00
Marc Campbell 818f8b26dd Move all to github actions 2020-03-23 09:33:23 -07:00
divolgin 9dbf282b5b Merge pull request #156 from replicatedhq/divolgin/previous
Include previous logs from pods if available
2020-03-23 09:19:33 -07:00
Marc Campbell 374856798f Merge branch 'master' of github.com:replicatedhq/troubleshoot 2020-03-23 09:17:05 -07:00
Marc Campbell d754b3bb9f Go mod 2020-03-23 09:16:19 -07:00
Marc Campbell 225ebfbcbe Merge pull request #157 from replicatedhq/postgres-analyzer
Database analyzers (pg, mysql, redis)
2020-03-23 08:58:50 -07:00
Marc Campbell 821a132980 add some omitempty 2020-03-23 08:58:02 -07:00
Marc Campbell 4e3a627b21 Remove broken mysql example 2020-03-23 08:51:59 -07:00
Marc Campbell 206e5c01d7 Fix makefile 2020-03-23 08:37:53 -07:00
Marc Campbell e54ad171d8 Removing incorrectly generate client code 2020-03-23 08:36:58 -07:00
Marc Campbell 8f78827002 Redis 2020-03-20 11:03:49 -07:00
Marc Campbell 77eba55ee8 Abstract, add mysql 2020-03-20 07:19:03 -07:00
Marc Campbell 562a565f1f Adding postgres analyzer 2020-03-19 18:28:13 -07:00
divolgin db8533e69c Include previous logs from pods if available 2020-03-18 17:53:43 +00:00
Marc Campbell f37bbdb14c Merge pull request #153 from replicatedhq/export-function
Export function
2020-03-17 14:36:38 -07:00
mzaneri 35808423b2 Merge pull request #155 from replicatedhq/mike-provider-refactor-working
REFACTOR analyzeDistribution to allow vendoring to KOTS
2020-03-12 16:38:45 -07:00
mzaneri 86b745d6c2 Update distribution.go 2020-03-12 16:01:27 -07:00
mzaneri c773ebd894 Update distribution.go 2020-03-12 14:56:03 -07:00
Michael 2ba2849a38 Merge branch 'mike-provider-refactor-working' of github.com:replicatedhq/troubleshoot into mike-provider-refactor-working 2020-03-12 18:01:19 +00:00
Michael a1c5247c8b REFACTOR create helper functions for analyzeDistribution 2020-03-12 18:01:05 +00:00
Michael 47ff99bfe2 Merge branch 'mike-provider-refactor-working' of github.com:replicatedhq/troubleshoot into mike-provider-refactor-working 2020-03-12 17:55:12 +00:00
Michael 6d19794dc5 REFACTOR create helper functions for analyzeDistribution 2020-03-12 17:54:34 +00:00
Michael 0c3cc7afce FIX change string to only be empty on eks masters 2020-03-11 23:33:29 +00:00
Michael 5798a4aa11 change analyzers 2020-03-11 22:10:53 +00:00
Michael ae64a4d591 REFACTOR create helper functions for analyzeDistribution 2020-03-11 17:58:52 +00:00
Marc Campbell 983aaaacea Defining types in a package 2020-03-10 17:32:16 +00:00
Marc Campbell e74101070d Refactor 2020-03-10 01:07:57 +00:00
Andrew Lavery d9625477d2 Merge pull request #151 from replicatedhq/laverya/no-go-i18n-version-replace
move multitype package here from kots
2020-03-09 17:43:12 -07:00
Andrew Lavery 1c66eed2cd move multitype package here from kots 2020-03-09 17:37:27 -07:00
Marc Campbell 1dda832933 Export runCollectors 2020-03-10 00:04:23 +00:00
divolgin d019f87284 Merge pull request #149 from replicatedhq/divolgin/fix-tests
5 is definitely not more than 20....
2020-03-09 12:14:22 -07:00
divolgin 983481da07 5 is definitely not more than 20.... 2020-03-09 19:07:46 +00:00
Marc Campbell 7462e1cdee Merge pull request #148 from replicatedhq/equality
Fix equality in regex analyzer
2020-03-07 13:32:39 -08:00
Marc Campbell 6563290de9 More clear solutino: 2020-03-07 21:30:41 +00:00
Marc Campbell ff627dcf83 Fix equality in regex analyzer 2020-03-07 21:28:17 +00:00
Jeremy Cohn 2158dee58d Merge pull request #147 from replicatedhq/jeremy/fix-analyze
Added spec support to `analyze` function in support-bundle
2020-03-06 14:27:48 -08:00
Jeremy Cohn f6a56a9def A few minor updates in the analyze usage 2020-03-06 14:26:38 -07:00
Jeremy Cohn 63a81314bb Updated to allow an analyze spec from URL
This commit includes the following changes:
1. Updated to allow a analyze spec from URL
2. Removed spec flag
The analyzer spec is a positional argument consistent with preflight.
2020-03-06 13:33:29 -07:00
Jeremy Cohn 1d352298e1 Added spec support to analyze function in support-bundle 2020-03-05 17:43:34 -08:00
Marc Campbell 26d8211a08 Merge pull request #146 from replicatedhq/remove-invalid-tests
Remove unused code
2020-03-05 17:20:47 -08:00
Marc Campbell 6c212e24f0 Better marshaling 2020-03-06 01:15:49 +00:00
Marc Campbell c9b01f981d Remove unused code 2020-03-06 00:49:53 +00:00
Marc Campbell 4fca3ff4fc Merge pull request #145 from replicatedhq/json-yaml-json-yaml
BoolString can only unmarshal as json
2020-03-05 16:36:23 -08:00
Marc Campbell d81cff0d67 BoolString can only unmarshal as json 2020-03-06 00:33:39 +00:00
Marc Campbell 62d12d8fff Merge pull request #144 from replicatedhq/boolstring
Use bool string for exclude value
2020-03-05 15:42:46 -08:00
Marc Campbell 8126cb3d3d Fix 2020-03-05 23:41:55 +00:00
Marc Campbell 6277101574 Use bool string for exclude value 2020-03-05 23:35:21 +00:00
Marc Campbell 346c751bdf Merge pull request #134 from replicatedhq/openapischema
Generate OpenAPISchema
2020-03-05 13:42:21 -08:00
divolgin 812aa9bc30 Merge pull request #143 from replicatedhq/divolgin/kots-kurl
Better integration with embedded kots clusters
2020-03-03 14:43:18 -08:00
divolgin 5a7b155093 Better integration with embedded kots clusters 2020-03-03 22:30:47 +00:00
Frank Shotwell c6ecab39cc Merge pull request #141 from replicatedhq/scope-cleanup
set SCOPE_LOG_ROOT_PATH to /dev/null to avoid creating lots of logfiles
2020-02-28 11:33:09 -08:00
Salah Al Saleh 648564eb4d Fix text_analyze_test (#142) 2020-02-25 16:42:00 -08:00
Frank Shotwell 1b9a220e2d set SCOPE_LOG_ROOT_PATH to /dev/null to avoid creating lots of logfiles 2020-02-21 19:34:26 +00:00
GraysonNull 45c7d95ebe Merge pull request #140 from GraysonNull/grayson/icon-uri
add IconURI to insights
2020-02-19 13:02:18 -06:00
GraysonNull 42288a4ff3 add IconURI to insights 2020-02-18 21:23:44 +00:00
divolgin 2eb6518792 Merge pull request #137 from replicatedhq/divolgin/insecure
Don't verify TLS certs on support bundle requests
2020-02-14 15:15:37 -08:00
divolgin 78d2364199 Don't verify TLS certs on support bundle requests 2020-02-14 23:08:42 +00:00
divolgin 1f9e478a78 Merge pull request #135 from replicatedhq/divolgin/icons
New icons for analyzers
2020-02-14 10:20:41 -08:00
Frank Shotwell 0d3c58eccd Merge pull request #136 from replicatedhq/detect-aks
Add AKS detection
2020-02-13 13:17:36 -08:00
Frank Shotwell 1a117220cb add aks detection 2020-02-12 17:57:38 +00:00
divolgin 1c79403934 New icons for analyzers 2020-02-11 23:52:29 +00:00
Marc Campbell d1ab5a6991 Docs say exclude, code says when 2020-02-10 22:13:07 +00:00
Marc Campbell c91a8ee60d Filenames that match kubeval 2020-02-10 21:31:36 +00:00
Marc Campbell 899d5d7672 Generate OpenAPISchema 2020-02-10 21:17:11 +00:00
Marc Campbell b466188679 Merge pull request #133 from replicatedhq/node-aggregate-analyzers
Update example
2020-02-06 18:11:06 -05:00
Marc Campbell f15579a3b2 Update example 2020-02-06 23:10:40 +00:00
Marc Campbell 1424faacab Merge pull request #132 from replicatedhq/node-aggregate-analyzers
Node aggregate analyzers
2020-02-06 18:06:21 -05:00
Marc Campbell e94b152733 strings.fields 2020-02-06 19:54:02 +00:00
Marc Campbell 717ba13614 Sum, min, max and count aggregation functions 2020-02-06 19:30:50 +00:00
Marc Campbell 6765e6c030 Working on aggregation functions 2020-02-06 19:10:22 +00:00
Marc Campbell eea2315c52 Aggregate analyzers for node troubleshoot: 2020-02-06 10:06:09 -08:00
Frank Shotwell 1e834430c2 Merge pull request #131 from replicatedhq/scope-build
pass through necessary envs for scope
2020-02-05 09:24:33 -08:00
Frank Shotwell 729caa4a7b pass through necessary envs for scope 2020-02-04 21:10:48 +00:00
Frank Shotwell 130aa88f3a Merge pull request #128 from replicatedhq/scope
Add scope test instrumentation
2020-01-31 12:31:21 -08:00
Frank Shotwell f8870e5fc0 move scope instrumentation to handle table-driven tests 2020-01-31 06:25:07 +00:00
Marc Campbell 4472f10ae7 Merge pull request #127 from replicatedhq/node-analyzers
Node analyzers
2020-01-30 14:17:16 -08:00
Frank Shotwell 10b2941c57 Add scope test instrumentation 2020-01-30 21:01:06 +00:00
Marc Campbell 879c3a67d7 Node resource analyzer 2020-01-29 23:16:40 +00:00
Marc Campbell 299f3e0da7 Add node analyzers 2020-01-29 13:49:02 -08:00
emosbaugh 3982e2023b Treat empty preflight when condition as true (#125)
* Treat empty preflight when condition as true

* add test

* fix
2020-01-23 11:05:54 -08:00
emosbaugh 8eddab69ce Collect statefulsets (#123)
* Collect statefulsets

* go version
2020-01-22 16:43:47 -08:00
Andrew Lavery 58b642426b Merge pull request #122 from replicatedhq/laverya/properly-identify-openshift-clusters-on-eks
EKS clusters do not have masters within the node list
2020-01-21 12:17:46 -08:00
Andrew Lavery 6fe9e2e7e6 EKS clusters do not have masters within the node list 2020-01-21 12:10:29 -08:00
Jeremy Cohn ecfe34f24c Merge pull request #121 from replicatedhq/kurl-installations
Identify kurl clusters with distribution analyzer
2020-01-21 12:04:06 -08:00
Jeremy Cohn 190eeef657 Accidentally pushed these go.mod and go.sum changes 2020-01-21 03:29:32 +00:00
Jeremy Cohn db48de2494 Identify kurl clusters with distribution analyzer 2020-01-21 03:11:39 +00:00
Andrew Lavery 5d280aee02 Merge pull request #120 from replicatedhq/laverya/fix-DownloadAndAnalyze-calls
fix order of arguments in calls to DownloadAndAnalyze
2020-01-20 18:24:33 -08:00
Andrew Lavery f67cd31e80 fix order of arguments in calls to DownloadAndAnalyze 2020-01-20 18:17:15 -08:00
Grant Miller 8f87fd0f1e Merge pull request #118 from replicatedhq/grantmiller-patch-1
Community w/ slack link
2020-01-13 14:46:57 -08:00
Grant Miller 46a114478b Community w/ slack link 2020-01-13 14:44:36 -08:00
Andrew Lavery f8c9cbf381 Merge pull request #117 from replicatedhq/laverya/simplify-auth-cani
minor simplification of authCanI code in resources collector
2020-01-10 15:09:01 -08:00
Andrew Lavery 26f3540d98 minor simplification of authCanI code in resources collector 2020-01-10 15:03:47 -08:00
Marc Campbell 2208b7672e Merge pull request #116 from replicatedhq/limit-range-collector
Add limitranges to cluster-resource collector
2020-01-10 09:43:18 -08:00
Marc Campbell b24032519e Add limitranges to cluster-resource collector 2020-01-10 17:41:20 +00:00
divolgin 1ce5e7b70b Merge pull request #115 from replicatedhq/divolgin/analyzers
Treat analyzer errors as preflight check fails
2020-01-10 08:51:35 -08:00
divolgin 052c932e05 Treat analyzer errors as preflight check fails 2020-01-09 22:48:54 +00:00
Andrew Lavery 5f60b1f0cb Merge pull request #114 from laverya/dont-require-resources.json
if resources.json does not exist, do not fail the distribution analyzer
2020-01-09 12:10:14 -08:00
Andrew Lavery 0379274bb8 if cluster-resources/resources.json, do not fail the distribution analyzer
that file was not collected in v0.9.15 and earlier, so we shouldn't require it - particularly since the microk8s/dockerdesktop/eks/gke/DO detection doesn't depend on it
2020-01-09 12:07:36 -08:00
Andrew Lavery ff97a4eabf Merge pull request #113 from laverya/distribution-analyzer-openshift-support
identify openshift clusters with distribution analyzer
2020-01-08 16:03:52 -08:00
Andrew Lavery 033524a83a identify openshift clusters with distribution analyzer 2020-01-08 15:38:32 -08:00
Andrew Lavery 64675883eb Merge pull request #112 from laverya/include-resources-and-groups-in-troubleshoot-defaults
include ServerGroupsAndResources in troubleshoot cluster-resources
2020-01-08 15:17:50 -08:00
Andrew Lavery 0a04256d62 include ServerGroupsAndResources in troubleshoot cluster-resources
also run cluster-resources collector even when some rbac permissions are missing

print progress message when skipping a collector due to rbac issues

include a sample troubleshoot yaml spec in the repo
2020-01-08 15:10:32 -08:00
Andrew Lavery 30f4d5e3f8 Merge pull request #111 from laverya/include-precise-version-in-troubleshoot-version.yaml
include binary version info in 'version.yaml' troubleshoot file
2020-01-07 17:32:58 -08:00
Andrew Lavery 0fcf473f85 include versionNumber as spec.versionNumber to follow k8s struct standards 2020-01-07 17:21:59 -08:00
Andrew Lavery f9b9dea1c6 only include version number, not full build info 2020-01-07 17:04:41 -08:00
Andrew Lavery 1928f00b0f include binary version info in 'version.yaml' troubleshoot file 2020-01-07 16:28:57 -08:00
Grant Miller d6b5ae9b7c Merge pull request #110 from grantmiller/master
readme adjustments
2020-01-07 12:59:36 -08:00
Grant Miller 3c8e4de10d more details 2020-01-07 12:56:41 -08:00
divolgin 600a67510b Merge pull request #107 from replicatedhq/laverya/rbac-wip
Check RBAC before running collectors
2019-12-31 13:33:17 -08:00
Andrew Lavery 55f2ed44bf Check RBAC before running collectors 2019-12-31 21:32:42 +00:00
divolgin 0993f6efd4 Merge pull request #109 from replicatedhq/divolgin/show-errors
include errors in messages on failures
2019-12-26 09:08:13 -08:00
divolgin 89250b0a87 include errors in messages on failures 2019-12-26 16:32:17 +00:00
divolgin 46cebad731 Merge pull request #108 from replicatedhq/divolgin/usage
Don't print usage on error and no double-logging
2019-12-24 14:09:06 -08:00
divolgin 8e1cb615a5 Don't print usage on error and no double-logging 2019-12-24 22:04:43 +00:00
Marc Campbell 777d907f58 Merge pull request #106 from replicatedhq/two-regexes
Merging both types of regex analyzers together
2019-12-24 12:44:09 -08:00
Marc Campbell 0aafbb79a6 go mod! 2019-12-24 20:00:46 +00:00
Marc Campbell 47c686f352 Replace 2019-12-24 19:50:05 +00:00
Marc Campbell 0ad7a87e4d Bump makefile 2019-12-24 19:46:43 +00:00
Marc Campbell 4a31134d3a go mod tidy 2019-12-24 19:45:01 +00:00
Marc Campbell 2b97e524e3 No more controllers 2019-12-24 19:38:47 +00:00
Marc Campbell 3955dab9bc Removing the CRD 2019-12-24 19:26:26 +00:00
Marc Campbell 9de6b3fffd Merge pull request #99 from ashwathishiva/custom_text_analyzer
Adding a text analyzer
2019-12-23 12:45:32 -08:00
divolgin 90b7ac986d Merge pull request #105 from replicatedhq/divolgin/krew
Bump krew plugins to v0.9.14
2019-12-19 14:59:16 -08:00
divolgin 9a59d1b018 Bump krew plugins to v0.9.14 2019-12-19 22:56:21 +00:00
Marc Campbell af9defc753 Merge pull request #101 from replicatedhq/revert-100-regex-analyzer
Revert "Regex analyzer"
2019-12-18 17:31:28 -08:00
Marc Campbell 806b2fbb41 Revert "Regex analyzer" 2019-12-18 17:30:16 -08:00
Marc Campbell 8ca92b42c4 Merge pull request #100 from replicatedhq/regex-analyzer
Regex analyzer
2019-12-18 17:02:16 -08:00
Marc Campbell 1ef9368e7b Tests on the regex analuzer 2019-12-19 01:00:46 +00:00
Marc Campbell b22120acd8 remove debug 2019-12-19 00:49:37 +00:00
Marc Campbell 518f826fc2 Regex analyzer 2019-12-19 00:49:16 +00:00
Ashwathi Shiva 6a64146012 Added tests 2019-12-18 18:48:12 -05:00
Marc Campbell a0529b09cd Merge pull request #98 from replicatedhq/cani
Add rbac policies for the current user (operator) in the bundle
2019-12-18 13:56:26 -08:00
Marc Campbell f5fe442349 Printing rbac policies per namespace 2019-12-18 19:49:39 +00:00
Marc Campbell e2748c7b24 RBAC 2019-12-18 19:46:02 +00:00
Marc Campbell c962dc59f0 Merge pull request #97 from replicatedhq/build-fix
one more fix
2019-12-18 11:10:14 -08:00
Marc Campbell 8ba2c576c3 one more fix 2019-12-18 18:42:03 +00:00
Marc Campbell fd47d23ac0 Merge pull request #96 from replicatedhq/build-fix
Build fix
2019-12-18 10:03:52 -08:00
Marc Campbell 59a2281290 More cleanup 2019-12-18 18:01:39 +00:00
Marc Campbell 1465af2c09 Fix build 2019-12-18 17:59:43 +00:00
Marc Campbell 7f82ec1f09 Add snapshot release back 2019-12-18 17:45:13 +00:00
Marc Campbell 4338b22505 Merge pull request #95 from replicatedhq/github-actions
GitHub actions
2019-12-18 08:01:22 -08:00
Marc Campbell 1757af58eb only push event 2019-12-18 15:18:43 +00:00
Marc Campbell d8bae5dc8b spelling 2019-12-18 15:18:01 +00:00
Marc Campbell ca9106e7c9 Merge pull request #93 from replicatedhq/no-collector-cmd
Remove manager and collector commands
2019-12-18 07:14:43 -08:00
Marc Campbell 57094dbb44 json preflights 2019-12-18 15:12:11 +00:00
Marc Campbell 7ac973647d Add json output 2019-12-18 15:12:11 +00:00
Marc Campbell 94f812c7bd Preflights 2019-12-18 15:12:11 +00:00
Marc Campbell e5f0e09236 Work on github actions 2019-12-18 15:12:11 +00:00
Marc Campbell 1ee662944f Merge pull request #92 from replicatedhq/optional-collectors
Optional collectors and analyzers
2019-12-18 06:55:56 -08:00
Marc Campbell 7ab1734cb6 Remove manager and collector commands 2019-12-18 01:52:06 +00:00
Marc Campbell c61acdc5de Regenerate 2019-12-18 01:40:06 +00:00
Marc Campbell 98f926b46c Support for optional collectors and analyzers 2019-12-18 01:38:51 +00:00
Marc Campbell d0a0d925bb Cleaning up name / collectorName 2019-12-18 01:12:16 +00:00
Andrew Lavery fd257b5618 Merge pull request #91 from bearium/stdout_results
Added Namespace for Collection and Allows for tests to output to stdout
2019-12-13 15:01:54 -08:00
Ashwathi Shiva f35f5e4d57 removed unused import 2019-12-12 22:38:28 -05:00
Ashwathi Shiva 71e66c7402 modified output string 2019-12-12 22:22:20 -05:00
bearium 3afe32cd1e change global fail to return result 2019-12-11 07:34:15 -05:00
Ashwathi Shiva 714667d641 Initial version of a custom text analyzer 2019-12-10 22:56:35 -05:00
Marc Campbell 029282451e Merge pull request #89 from replicatedhq/version-command
Add version command
2019-12-06 07:22:41 -08:00
bearium 68c76867c7 go mod tidy 2019-12-02 10:36:48 -05:00
bearium e13cb35c82 added std out support and namespace functionality 2019-12-02 09:56:07 -05:00
Marc Campbell 9c4fa8ac14 Add version command 2019-11-30 00:03:43 +00:00
Frank Shotwell 1d3831f6d1 Merge pull request #86 from replicatedhq/gke
add missing gke test
2019-11-22 15:56:26 -08:00
Frank Shotwell 5812414093 add missing gke test 2019-11-22 15:40:38 -08:00
Marc Campbell 94e468ade3 Merge pull request #85 from replicatedhq/docker-desktop
More friendly parsing of Docker Desktop
2019-11-22 15:20:02 -08:00
Marc Campbell 3dc78d2ce8 More friendly parsing of Docker Desktop 2019-11-22 23:14:28 +00:00
divolgin c4dd568267 Merge pull request #84 from replicatedhq/divolgin/krew
Adding changes made in the krew-index repo
2019-11-18 16:02:07 -08:00
divolgin 00fa236525 Adding changes made in the krew-index repo 2019-11-18 23:57:16 +00:00
divolgin ec24967e50 Merge pull request #83 from laverya/update-release-tarball-naming
update tarball naming scheme to bin_os_arch, no longer include version
2019-11-14 14:05:02 -08:00
Andrew Lavery 430fdaa9e4 update tarball naming scheme to bin_os_arch, no longer include version 2019-11-14 13:48:52 -08:00
divolgin 58ed4c8fc2 Merge pull request #82 from replicatedhq/divolgin/data
support for data collector
2019-11-12 13:03:40 -08:00
divolgin 353569d59a support for data collector 2019-11-12 20:53:50 +00:00
Marc Campbell cd43fd6f56 Merge pull request #81 from replicatedhq/collector-node
Collector node
2019-11-08 15:29:03 -08:00
Marc Campbell ed8453ce6b Distribution analyzer 2019-11-08 23:15:58 +00:00
Marc Campbell 5744d608a4 Container runtime analyzer 2019-11-08 17:25:11 +00:00
Marc Campbell 0e3bcd29e4 Add nodes to the bundle 2019-11-08 16:57:33 +00:00
Marc Campbell 2a3e4e7d75 Merge pull request #79 from replicatedhq/regen
Updated from controller-gen
2019-11-07 18:00:46 -08:00
Marc Campbell 67b25e319b Updated from controller-gen 2019-11-08 01:31:20 +00:00
Marc Campbell b0bbaa4e6b Merge pull request #78 from replicatedhq/status-analyzer
Status analyzer
2019-11-07 17:22:04 -08:00
Marc Campbell 8a1e129dbe Add names so the analysis UI renders 2019-11-08 00:22:57 +00:00
Marc Campbell b926ff6fa2 Additional test 2019-11-07 17:19:01 +00:00
Marc Campbell fb5f1522ea Deployment and statefulset 2019-11-07 02:07:05 +00:00
Marc Campbell 6e7715a145 Deployment and Statefulset status analyzers 2019-11-07 01:54:32 +00:00
divolgin c0415dd100 Merge pull request #77 from replicatedhq/divolgin/krew
bump krew manifests to 0.9.11
2019-11-05 11:16:03 -08:00
divolgin 1d031d6897 bump krew manifests to 0.9.11 2019-11-04 15:32:25 +00:00
divolgin b19ac90512 Merge pull request #76 from replicatedhq/divolgin/containerz
Change containers to containerNames to not break kustomize
2019-10-31 16:09:27 -07:00
divolgin 13fb6abcaf Change containers to containerNames to not break kustomize 2019-10-31 19:52:04 +00:00
Marc Campbell 218b9c006d Merge pull request #75 from replicatedhq/analyze-spec
Fix
2019-10-29 14:10:05 -07:00
Marc Campbell 0b493a533b Fix 2019-10-29 21:08:58 +00:00
Marc Campbell 5830eb34a0 Merge pull request #74 from replicatedhq/analyze-spec
Analyze spec
2019-10-29 13:00:32 -07:00
Marc Campbell 8a1bb8a422 isURL 2019-10-29 19:56:29 +00:00
Marc Campbell 14ace5294f Analyze spec 2019-10-29 19:45:25 +00:00
Marc Campbell 25ec38bdf5 Merge pull request #73 from replicatedhq/url
Replace default collector URL
2019-10-29 10:49:37 -07:00
divolgin 223a4a6e0a Replace default collector URL 2019-10-29 03:28:27 +00:00
divolgin 3b6ab41e1b Merge pull request #72 from replicatedhq/divolgin/output-names
use file paths specified by the spec instead of hardcoded ones
2019-10-25 09:26:11 -07:00
divolgin 60ca35a5a6 use file paths specified by the spec instead of hardcoded ones 2019-10-25 16:23:22 +00:00
divolgin 36e3bf294d Merge pull request #71 from replicatedhq/divolgin/output-names
support multiple containers in pod logs
2019-10-24 11:31:45 -07:00
divolgin 3ea71c1d5a support multiple containers in pod logs 2019-10-24 18:27:53 +00:00
divolgin 26baaacee8 Merge pull request #70 from replicatedhq/divolgin/krew
bump krew manifests to 0.9.9
2019-10-18 09:31:24 -07:00
divolgin 6f868877d8 bump krew manifests to 0.9.9 2019-10-18 16:23:08 +00:00
Marc Campbell 075c0f6f16 Merge pull request #69 from replicatedhq/analyze-kotsadm
Wraping errors, no synlink in kotsadm
2019-10-17 13:03:29 -04:00
divolgin 2455f87ee1 Merge pull request #68 from replicatedhq/divolgin/better-messaging
Better messaging when support bundle is uploaded
2019-10-17 09:15:58 -07:00
Marc Campbell a4c482c74c Wraping errors, no synlink in kotsadm 2019-10-17 14:46:37 +00:00
divolgin 642c1d7e5b Better messaging when support bundle is uploaded 2019-10-15 22:45:57 +00:00
divolgin e88e3a4694 Merge pull request #66 from replicatedhq/divolgin/krew
bump krew manifests to 0.9.8
2019-09-09 15:22:07 -07:00
divolgin e23f799bed bump krew manifests to 0.9.8 2019-09-09 22:16:32 +00:00
Marc Campbell 25e884c43a Proxy 2019-09-08 15:09:02 +00:00
Marc Campbell 481aab7820 Merge pull request #65 from replicatedhq/error-handling
Error handling in cluster resources
2019-09-08 08:01:39 -07:00
Marc Campbell 0b7aff6597 Error handling in cluster resources 2019-09-08 14:35:56 +00:00
Marc Campbell 4153b9ac44 One extension is enough 2019-08-28 22:13:33 +00:00
Marc Campbell 48750ba1e5 Better release name for so 2019-08-28 21:59:57 +00:00
Marc Campbell 086d5569b3 Merge pull request #64 from replicatedhq/ffi
Support CGO for calling analysis from other languages
2019-08-28 14:39:09 -07:00
Marc Campbell 996a55bf90 Support CGO for calling analysis from other languages 2019-08-28 21:30:59 +00:00
divolgin 8125d5534b Merge pull request #63 from alrs/fix-analyze-swallowed-error
pkg/analyze: Fix swallowed error
2019-08-27 13:55:03 -07:00
Lars Lehtonen 09deffb507 pkg/analyze: Fix swallowed error 2019-08-26 17:16:18 -07:00
divolgin a8bdda483d Merge pull request #62 from replicatedhq/divolgin/run
run collector times out
2019-08-22 15:55:31 -07:00
divolgin c3e2748f3c run collector times out 2019-08-22 22:39:30 +00:00
divolgin 0c7c8c3927 Merge pull request #61 from replicatedhq/krew
update krew manifests
2019-08-22 15:16:45 -07:00
divolgin 9a1bb9fa7b update krew manifests 2019-08-22 16:35:22 +00:00
divolgin 143f24b1e6 Merge pull request #60 from replicatedhq/krew
update krew manifests
2019-08-22 09:27:13 -07:00
divolgin 45d537744f update krew manifests 2019-08-22 16:02:54 +00:00
divolgin 1855c42b16 Merge pull request #59 from replicatedhq/divolgin/cli
adding support for generic CLI options. closes #54
2019-08-22 08:04:27 -07:00
divolgin 2fb3a17783 adding support for generic CLI options. closes #54 2019-08-22 14:25:08 +00:00
divolgin b195b34fbe Merge pull request #57 from replicatedhq/divolgin/file
add numbers to support bundle name as needed
2019-08-21 10:01:37 -07:00
divolgin 1c6fe9f262 add numbers to support bundle name as needed 2019-08-21 16:18:57 +00:00
662 changed files with 111635 additions and 12447 deletions
-39
View File
@@ -1,39 +0,0 @@
steps:
- label: build
commands:
- make
plugins:
- docker#v3.2.0:
image: replicated/gitops-builder:buildkite-go12-node10
always-pull: true
mount-checkout: true
workdir: /go/src/github.com/replicatedhq/troubleshoot
- wait
- commands:
- make snapshot-release
branches: "master"
plugins:
- docker#v3.2.0:
image: replicated/gitops-builder:buildkite-go12-node10
always-pull: true
mount-checkout: true
workdir: /go/src/github.com/replicatedhq/troubleshoot
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/var/lib/buildkite-agent/.docker/config.json:/home/builder/.docker/config.json"
- label: release
commands:
- if [ -z "$BUILDKITE_TAG" ]; then echo "Not a tag, not releasing"; else git tag -f "$BUILDKITE_TAG" && make release; fi
plugins:
- docker#v3.2.0:
always-pull: true
image: replicated/gitops-builder:buildkite-go12-node10
workdir: /go/src/github.com/replicatedhq/troubleshoot
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
- "/var/lib/buildkite-agent/.docker/config.json:/home/builder/.docker/config.json"
environment:
- GITHUB_TOKEN_TROUBLESHOOT
+115
View File
@@ -0,0 +1,115 @@
#-------------------------------------------------------------------------------------------------------------
# Modified from Codespaces default container image: https://github.com/microsoft/vscode-dev-containers/blob/main/containers/codespaces-linux/history/1.6.3.md
# - Remove PHP, Ruby, Dotnet, Java, powershell, rust dependencies
# - Remove fish shell
# - Remove Oryx
# - Remove git-lfs
# - Change shell to zsh
#
# TODO (dans): find a better way to pull in library script dynamically from vscode repo
# TODO (dans): AWS CLI - make a common script in the dev-containers repo
# TODO (dans): Gcloud CLI - make a common script in the dev-containers repo
# TODO (dans): add gcommands alias
# TODO (dans): terraform
#-------------------------------------------------------------------------------------------------------------
FROM mcr.microsoft.com/oryx/build:vso-focal-20210902.1 as replicated
ARG USERNAME=codespace
ARG USER_UID=1000
ARG USER_GID=$USER_UID
ARG HOMEDIR=/home/$USERNAME
ARG GO_VERSION="latest"
# Default to bash shell (other shells available at /usr/bin/fish and /usr/bin/zsh)
ENV SHELL=/bin/bash \
ORYX_ENV_TYPE=vsonline-present \
NODE_ROOT="${HOMEDIR}/.nodejs" \
PYTHON_ROOT="${HOMEDIR}/.python" \
HUGO_ROOT="${HOMEDIR}/.hugo" \
NVM_SYMLINK_CURRENT=true \
NVM_DIR="/home/${USERNAME}/.nvm" \
NVS_HOME="/home/${USERNAME}/.nvs" \
NPM_GLOBAL="/home/${USERNAME}/.npm-global" \
KREW_HOME="/home/${USERNAME}/.krew/bin" \
PIPX_HOME="/usr/local/py-utils" \
PIPX_BIN_DIR="/usr/local/py-utils/bin" \
GOROOT="/usr/local/go" \
GOPATH="/go"
ENV PATH="${PATH}:${KREW_HOME}:${NVM_DIR}/current/bin:${NPM_GLOBAL}/bin:${ORIGINAL_PATH}:${GOROOT}/bin:${GOPATH}/bin:${PIPX_BIN_DIR}:/opt/conda/condabin:${NODE_ROOT}/current/bin:${PYTHON_ROOT}/current/bin:${HUGO_ROOT}/current/bin:${ORYX_PATHS}"
COPY library-scripts/* first-run-notice.txt /tmp/scripts/
COPY ./config/* /etc/replicated/
COPY ./lifecycle-scripts/* /var/lib/replicated/scripts/
# Install needed utilities and setup non-root user. Use a separate RUN statement to add your own dependencies.
RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
# Restore man command
&& yes | unminimize 2>&1 \
# Run common script and setup user
&& bash /tmp/scripts/common-debian.sh "true" "${USERNAME}" "${USER_UID}" "${USER_GID}" "true" "true" "true" \
&& bash /tmp/scripts/setup-user.sh "${USERNAME}" "${PATH}" \
# Change owner of opt contents since Oryx can dynamically install and will run as "codespace"
&& chown ${USERNAME} /opt/* \
&& chsh -s /bin/bash ${USERNAME} \
# Verify expected build and debug tools are present
&& apt-get -y install build-essential cmake python3-dev \
# Install tools and shells not in common script
&& apt-get install -yq vim vim-doc xtail software-properties-common libsecret-1-dev \
# Install additional tools (useful for 'puppeteer' project)
&& apt-get install -y --no-install-recommends libnss3 libnspr4 libatk-bridge2.0-0 libatk1.0-0 libx11-6 libpangocairo-1.0-0 \
libx11-xcb1 libcups2 libxcomposite1 libxdamage1 libxfixes3 libpango-1.0-0 libgbm1 libgtk-3-0 \
&& bash /tmp/scripts/sshd-debian.sh \
&& bash /tmp/scripts/github-debian.sh \
&& bash /tmp/scripts/azcli-debian.sh \
# Install Moby CLI and Engine
&& /bin/bash /tmp/scripts/docker-debian.sh "true" "/var/run/docker-host.sock" "/var/run/docker.sock" "${USERNAME}" "true" \
# && bash /tmp/scripts/docker-in-docker-debian.sh "true" "${USERNAME}" "true" \
&& bash /tmp/scripts/kubectl-helm-debian.sh \
# Build latest git from source
&& bash /tmp/scripts/git-from-src-debian.sh "latest" \
# Clean up
&& apt-get autoremove -y && apt-get clean -y \
# Move first run notice to right spot
&& mkdir -p /usr/local/etc/vscode-dev-containers/ \
&& mv -f /tmp/scripts/first-run-notice.txt /usr/local/etc/vscode-dev-containers/
# Install Python
RUN bash /tmp/scripts/python-debian.sh "none" "/opt/python/latest" "${PIPX_HOME}" "${USERNAME}" "true" \
&& apt-get clean -y
# Setup Node.js, install NVM and NVS
RUN bash /tmp/scripts/node-debian.sh "${NVM_DIR}" "none" "${USERNAME}" \
&& (cd ${NVM_DIR} && git remote get-url origin && echo $(git log -n 1 --pretty=format:%H -- .)) > ${NVM_DIR}/.git-remote-and-commit \
# Install nvs (alternate cross-platform Node.js version-management tool)
&& sudo -u ${USERNAME} git clone -c advice.detachedHead=false --depth 1 https://github.com/jasongin/nvs ${NVS_HOME} 2>&1 \
&& (cd ${NVS_HOME} && git remote get-url origin && echo $(git log -n 1 --pretty=format:%H -- .)) > ${NVS_HOME}/.git-remote-and-commit \
&& sudo -u ${USERNAME} bash ${NVS_HOME}/nvs.sh install \
&& rm ${NVS_HOME}/cache/* \
# Set npm global location
&& sudo -u ${USERNAME} npm config set prefix ${NPM_GLOBAL} \
&& npm config -g set prefix ${NPM_GLOBAL} \
# Clean up
&& rm -rf ${NVM_DIR}/.git ${NVS_HOME}/.git
# Install Go
RUN bash /tmp/scripts/go-debian.sh "${GO_VERSION}" "${GOROOT}" "${GOPATH}" "${USERNAME}"
# Install Replicated Tools
RUN bash /tmp/scripts/replicated-debian.sh \
&& rm -rf /tmp/scripts \
&& apt-get clean -y
# Userspace
ENV SHELL=/bin/zsh
USER ${USERNAME}
COPY --chown=${USERNAME}:root library-scripts/replicated-userspace.sh /tmp/scripts/
RUN bash /usr/local/share/docker-init.sh \
&& bash /tmp/scripts/replicated-userspace.sh \
&& rm -rf /tmp/scripts/scripts
# Fire Docker/Moby script if needed along with Oryx's benv
ENTRYPOINT [ "/usr/local/share/docker-init.sh", "/usr/local/share/ssh-init.sh", "benv" ]
CMD [ "sleep", "infinity" ]
+7
View File
@@ -0,0 +1,7 @@
# Replicated KOTS Codespace Container
Most of the code here is borrowed from this [Microsoft repo of base images](https://github.com/microsoft/vscode-dev-containers), except for replicated specific things.
## Notes
* k3d *DOES NOT* work with DinD. You have to use the docker with docker install instead.
* Might be faster to install kubectl plugins on the `$PATH` in the `Dockerfile` instead of downloading them `onCreate.sh`.
+10
View File
@@ -0,0 +1,10 @@
apiVersion: k3d.io/v1alpha3
kind: Simple
name: replicated
servers: 1
image: rancher/k3s:v1.21.4-k3s1 # v1.21.3-k3s1 default is broken
registries:
create:
name: k3d-replicated-registry.localhost
host: "0.0.0.0"
hostPort: "5000"
+63
View File
@@ -0,0 +1,63 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
// https://github.com/microsoft/vscode-dev-containers/tree/v0.162.0/containers/javascript-node
{
"name": "Replicated Codeserver",
"build": {
"dockerfile": "Dockerfile",
"args": {
"GO_VERSION": "1.17",
}
},
// Set *default* container specific settings.json values on container create.
"settings": {
"terminal.integrated.shell.linux": "/usr/bin/zsh",
"go.toolsManagement.checkForUpdates": "local",
"go.useLanguageServer": true,
"go.gopath": "/go",
"go.goroot": "/usr/local/go",
"python.pythonPath": "/opt/python/latest/bin/python",
"python.linting.enabled": true,
"python.linting.pylintEnabled": true,
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint",
"lldb.executable": "/usr/bin/lldb",
"files.watcherExclude": {
"**/target/**": true
}
},
"remoteUser": "codespace",
"overrideCommand": false,
"runArgs": [
"--privileged",
"--init"
],
"mounts": [
"source=/var/run/docker.sock,target=/var/run/docker-host.sock,type=bind",
],
// Add the IDs of extensions you want installed when the container is created.
"extensions": [
"dbaeumer.vscode-eslint",
"GitHub.vscode-pull-request-github",
"golang.go",
"github.copilot",
"lizebang.bash-extension-pack",
"streetsidesoftware.code-spell-checker",
],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "bash /var/lib/replicated/scripts/onCreate.sh",
// Use 'postStartCommand' to run commands after the container is created like starting minikube.
"postStartCommand": "bash /var/lib/replicated/scripts/onStart.sh",
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
// "remoteUser": "node"
}
+9
View File
@@ -0,0 +1,9 @@
👋 Welcome to your Replicated Codespace!
There's a local Kubernetes cluster set up for you.
Drivers Manual:
* `k` alias is available for `kubectl` with auto-completion for your pleasure
* This is a `zsh` terminal with Oh My Zsh installed. Just thought you should know.
@@ -0,0 +1,67 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/azcli.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./azcli-debian.sh
set -e
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
export DEBIAN_FRONTEND=noninteractive
# Install dependencies
check_packages apt-transport-https curl ca-certificates lsb-release gnupg2
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
. /etc/os-release
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/azure-cli/ ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/azure-cli.list
apt-get update
apt-get install -y azure-cli
echo "Done!"
@@ -0,0 +1,478 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/common.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./common-debian.sh [install zsh flag] [username] [user UID] [user GID] [upgrade packages flag] [install Oh My Zsh! flag] [Add non-free packages]
set -e
INSTALL_ZSH=${1:-"true"}
USERNAME=${2:-"automatic"}
USER_UID=${3:-"automatic"}
USER_GID=${4:-"automatic"}
UPGRADE_PACKAGES=${5:-"true"}
INSTALL_OH_MYS=${6:-"true"}
ADD_NON_FREE_PACKAGES=${7:-"false"}
SCRIPT_DIR="$(cd $(dirname "${BASH_SOURCE[0]}") && pwd)"
MARKER_FILE="/usr/local/etc/vscode-dev-containers/common"
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# If in automatic mode, determine if a user already exists, if not use vscode
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=vscode
fi
elif [ "${USERNAME}" = "none" ]; then
USERNAME=root
USER_UID=0
USER_GID=0
fi
# Load markers to see which steps have already run
if [ -f "${MARKER_FILE}" ]; then
echo "Marker file found:"
cat "${MARKER_FILE}"
source "${MARKER_FILE}"
fi
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Function to call apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Run install apt-utils to avoid debconf warning then verify presence of other common developer tools and dependencies
if [ "${PACKAGES_ALREADY_INSTALLED}" != "true" ]; then
package_list="apt-utils \
openssh-client \
gnupg2 \
iproute2 \
procps \
lsof \
htop \
net-tools \
psmisc \
curl \
wget \
rsync \
ca-certificates \
unzip \
zip \
nano \
vim-tiny \
less \
jq \
lsb-release \
apt-transport-https \
dialog \
libc6 \
libgcc1 \
libkrb5-3 \
libgssapi-krb5-2 \
libicu[0-9][0-9] \
liblttng-ust0 \
libstdc++6 \
zlib1g \
locales \
sudo \
ncdu \
man-db \
strace \
manpages \
manpages-dev \
init-system-helpers"
# Needed for adding manpages-posix and manpages-posix-dev which are non-free packages in Debian
if [ "${ADD_NON_FREE_PACKAGES}" = "true" ]; then
# Bring in variables from /etc/os-release like VERSION_CODENAME
. /etc/os-release
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httredir)\.debian\.org\/debian ${VERSION_CODENAME} main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME} main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i -E "s/deb-src http:\/\/(deb|httpredir)\.debian\.org\/debian ${VERSION_CODENAME}-updates main/deb http:\/\/\1\.debian\.org\/debian ${VERSION_CODENAME}-updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main/deb http:\/\/security\.debian\.org\/debian-security ${VERSION_CODENAME}\/updates main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
sed -i "s/deb-src http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main/deb http:\/\/deb\.debian\.org\/debian ${VERSION_CODENAME}-backports main contrib non-free/" /etc/apt/sources.list
echo "Running apt-get update..."
apt-get update
package_list="${package_list} manpages-posix manpages-posix-dev"
else
apt_get_update_if_needed
fi
# Install libssl1.1 if available
if [[ ! -z $(apt-cache --names-only search ^libssl1.1$) ]]; then
package_list="${package_list} libssl1.1"
fi
# Install appropriate version of libssl1.0.x if available
libssl_package=$(dpkg-query -f '${db:Status-Abbrev}\t${binary:Package}\n' -W 'libssl1\.0\.?' 2>&1 || echo '')
if [ "$(echo "$LIlibssl_packageBSSL" | grep -o 'libssl1\.0\.[0-9]:' | uniq | sort | wc -l)" -eq 0 ]; then
if [[ ! -z $(apt-cache --names-only search ^libssl1.0.2$) ]]; then
# Debian 9
package_list="${package_list} libssl1.0.2"
elif [[ ! -z $(apt-cache --names-only search ^libssl1.0.0$) ]]; then
# Ubuntu 18.04, 16.04, earlier
package_list="${package_list} libssl1.0.0"
fi
fi
echo "Packages to verify are installed: ${package_list}"
apt-get -y install --no-install-recommends ${package_list} 2> >( grep -v 'debconf: delaying package configuration, since apt-utils is not installed' >&2 )
# Install git if not already installed (may be more recent than distro version)
if ! type git > /dev/null 2>&1; then
apt-get -y install --no-install-recommends git
fi
PACKAGES_ALREADY_INSTALLED="true"
fi
# Get to latest versions of all packages
if [ "${UPGRADE_PACKAGES}" = "true" ]; then
apt_get_update_if_needed
apt-get -y upgrade --no-install-recommends
apt-get autoremove -y
fi
# Ensure at least the en_US.UTF-8 UTF-8 locale is available.
# Common need for both applications and things like the agnoster ZSH theme.
if [ "${LOCALE_ALREADY_SET}" != "true" ] && ! grep -o -E '^\s*en_US.UTF-8\s+UTF-8' /etc/locale.gen > /dev/null; then
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen
locale-gen
LOCALE_ALREADY_SET="true"
fi
# Create or update a non-root user to match UID/GID.
if id -u ${USERNAME} > /dev/null 2>&1; then
# User exists, update if needed
if [ "${USER_GID}" != "automatic" ] && [ "$USER_GID" != "$(id -G $USERNAME)" ]; then
groupmod --gid $USER_GID $USERNAME
usermod --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" != "automatic" ] && [ "$USER_UID" != "$(id -u $USERNAME)" ]; then
usermod --uid $USER_UID $USERNAME
fi
else
# Create user
if [ "${USER_GID}" = "automatic" ]; then
groupadd $USERNAME
else
groupadd --gid $USER_GID $USERNAME
fi
if [ "${USER_UID}" = "automatic" ]; then
useradd -s /bin/bash --gid $USERNAME -m $USERNAME
else
useradd -s /bin/bash --uid $USER_UID --gid $USERNAME -m $USERNAME
fi
fi
# Add add sudo support for non-root user
if [ "${USERNAME}" != "root" ] && [ "${EXISTING_NON_ROOT_USER}" != "${USERNAME}" ]; then
echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME
chmod 0440 /etc/sudoers.d/$USERNAME
EXISTING_NON_ROOT_USER="${USERNAME}"
fi
# ** Shell customization section **
if [ "${USERNAME}" = "root" ]; then
user_rc_path="/root"
else
user_rc_path="/home/${USERNAME}"
fi
# Restore user .bashrc defaults from skeleton file if it doesn't exist or is empty
if [ ! -f "${user_rc_path}/.bashrc" ] || [ ! -s "${user_rc_path}/.bashrc" ] ; then
cp /etc/skel/.bashrc "${user_rc_path}/.bashrc"
fi
# Restore user .profile defaults from skeleton file if it doesn't exist or is empty
if [ ! -f "${user_rc_path}/.profile" ] || [ ! -s "${user_rc_path}/.profile" ] ; then
cp /etc/skel/.profile "${user_rc_path}/.profile"
fi
# .bashrc/.zshrc snippet
rc_snippet="$(cat << 'EOF'
if [ -z "${USER}" ]; then export USER=$(whoami); fi
if [[ "${PATH}" != *"$HOME/.local/bin"* ]]; then export PATH="${PATH}:$HOME/.local/bin"; fi
# Display optional first run image specific notice if configured and terminal is interactive
if [ -t 1 ] && [[ "${TERM_PROGRAM}" = "vscode" || "${TERM_PROGRAM}" = "codespaces" ]] && [ ! -f "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed" ]; then
if [ -f "/usr/local/etc/vscode-dev-containers/first-run-notice.txt" ]; then
cat "/usr/local/etc/vscode-dev-containers/first-run-notice.txt"
elif [ -f "/workspaces/.codespaces/shared/first-run-notice.txt" ]; then
cat "/workspaces/.codespaces/shared/first-run-notice.txt"
fi
mkdir -p "$HOME/.config/vscode-dev-containers"
# Mark first run notice as displayed after 10s to avoid problems with fast terminal refreshes hiding it
((sleep 10s; touch "$HOME/.config/vscode-dev-containers/first-run-notice-already-displayed") &)
fi
# Set the default git editor if not already set
if [ -z "$(git config --get core.editor)" ] && [ -z "${GIT_EDITOR}" ]; then
if [ "${TERM_PROGRAM}" = "vscode" ]; then
if [[ -n $(command -v code-insiders) && -z $(command -v code) ]]; then
export GIT_EDITOR="code-insiders --wait"
else
export GIT_EDITOR="code --wait"
fi
fi
fi
EOF
)"
# code shim, it fallbacks to code-insiders if code is not available
cat << 'EOF' > /usr/local/bin/code
#!/bin/sh
get_in_path_except_current() {
which -a "$1" | grep -A1 "$0" | grep -v "$0"
}
code="$(get_in_path_except_current code)"
if [ -n "$code" ]; then
exec "$code" "$@"
elif [ "$(command -v code-insiders)" ]; then
exec code-insiders "$@"
else
echo "code or code-insiders is not installed" >&2
exit 127
fi
EOF
chmod +x /usr/local/bin/code
# systemctl shim - tells people to use 'service' if systemd is not running
cat << 'EOF' > /usr/local/bin/systemctl
#!/bin/sh
set -e
if [ -d "/run/systemd/system" ]; then
exec /bin/systemctl/systemctl "$@"
else
echo '\n"systemd" is not running in this container due to its overhead.\nUse the "service" command to start services intead. e.g.: \n\nservice --status-all'
fi
EOF
chmod +x /usr/local/bin/systemctl
# Codespaces bash and OMZ themes - partly inspired by https://github.com/ohmyzsh/ohmyzsh/blob/master/themes/robbyrussell.zsh-theme
codespaces_bash="$(cat \
<<'EOF'
# Codespaces bash prompt theme
__bash_prompt() {
local userpart='`export XIT=$? \
&& [ ! -z "${GITHUB_USER}" ] && echo -n "\[\033[0;32m\]@${GITHUB_USER} " || echo -n "\[\033[0;32m\]\u " \
&& [ "$XIT" -ne "0" ] && echo -n "\[\033[1;31m\]➜" || echo -n "\[\033[0m\]➜"`'
local gitbranch='`\
export BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || git rev-parse --short HEAD 2>/dev/null); \
if [ "${BRANCH}" != "" ]; then \
echo -n "\[\033[0;36m\](\[\033[1;31m\]${BRANCH}" \
&& if git ls-files --error-unmatch -m --directory --no-empty-directory -o --exclude-standard ":/*" > /dev/null 2>&1; then \
echo -n " \[\033[1;33m\]✗"; \
fi \
&& echo -n "\[\033[0;36m\]) "; \
fi`'
local lightblue='\[\033[1;34m\]'
local removecolor='\[\033[0m\]'
PS1="${userpart} ${lightblue}\w ${gitbranch}${removecolor}\$ "
unset -f __bash_prompt
}
__bash_prompt
EOF
)"
codespaces_zsh="$(cat \
<<'EOF'
# Codespaces zsh prompt theme
__zsh_prompt() {
local prompt_username
if [ ! -z "${GITHUB_USER}" ]; then
prompt_username="@${GITHUB_USER}"
else
prompt_username="%n"
fi
PROMPT="%{$fg[green]%}${prompt_username} %(?:%{$reset_color%}➜ :%{$fg_bold[red]%}➜ )" # User/exit code arrow
PROMPT+='%{$fg_bold[blue]%}%(5~|%-1~/…/%3~|%4~)%{$reset_color%} ' # cwd
PROMPT+='$(git_prompt_info)%{$fg[white]%}$ %{$reset_color%}' # Git status
unset -f __zsh_prompt
}
ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg_bold[cyan]%}(%{$fg_bold[red]%}"
ZSH_THEME_GIT_PROMPT_SUFFIX="%{$reset_color%} "
ZSH_THEME_GIT_PROMPT_DIRTY=" %{$fg_bold[yellow]%}✗%{$fg_bold[cyan]%})"
ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg_bold[cyan]%})"
__zsh_prompt
EOF
)"
# Add notice that Oh My Bash! has been removed from images and how to provide information on how to install manually
omb_readme="$(cat \
<<'EOF'
"Oh My Bash!" has been removed from this image in favor of a simple shell prompt. If you
still wish to use it, remove "~/.oh-my-bash" and install it from: https://github.com/ohmybash/oh-my-bash
You may also want to consider "Bash-it" as an alternative: https://github.com/bash-it/bash-it
See here for infomation on adding it to your image or dotfiles: https://aka.ms/codespaces/omb-remove
EOF
)"
omb_stub="$(cat \
<<'EOF'
#!/usr/bin/env bash
if [ -t 1 ]; then
cat $HOME/.oh-my-bash/README.md
fi
EOF
)"
# Add RC snippet and custom bash prompt
if [ "${RC_SNIPPET_ALREADY_ADDED}" != "true" ]; then
echo "${rc_snippet}" >> /etc/bash.bashrc
echo "${codespaces_bash}" >> "${user_rc_path}/.bashrc"
echo 'export PROMPT_DIRTRIM=4' >> "${user_rc_path}/.bashrc"
if [ "${USERNAME}" != "root" ]; then
echo "${codespaces_bash}" >> "/root/.bashrc"
echo 'export PROMPT_DIRTRIM=4' >> "/root/.bashrc"
fi
chown ${USERNAME}:${USERNAME} "${user_rc_path}/.bashrc"
RC_SNIPPET_ALREADY_ADDED="true"
fi
# Add stub for Oh My Bash!
if [ ! -d "${user_rc_path}/.oh-my-bash}" ] && [ "${INSTALL_OH_MYS}" = "true" ]; then
mkdir -p "${user_rc_path}/.oh-my-bash" "/root/.oh-my-bash"
echo "${omb_readme}" >> "${user_rc_path}/.oh-my-bash/README.md"
echo "${omb_stub}" >> "${user_rc_path}/.oh-my-bash/oh-my-bash.sh"
chmod +x "${user_rc_path}/.oh-my-bash/oh-my-bash.sh"
if [ "${USERNAME}" != "root" ]; then
echo "${omb_readme}" >> "/root/.oh-my-bash/README.md"
echo "${omb_stub}" >> "/root/.oh-my-bash/oh-my-bash.sh"
chmod +x "/root/.oh-my-bash/oh-my-bash.sh"
fi
chown -R "${USERNAME}:${USERNAME}" "${user_rc_path}/.oh-my-bash"
fi
# Optionally install and configure zsh and Oh My Zsh!
if [ "${INSTALL_ZSH}" = "true" ]; then
if ! type zsh > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get install -y zsh
fi
if [ "${ZSH_ALREADY_INSTALLED}" != "true" ]; then
echo "${rc_snippet}" >> /etc/zsh/zshrc
ZSH_ALREADY_INSTALLED="true"
fi
# Adapted, simplified inline Oh My Zsh! install steps that adds, defaults to a codespaces theme.
# See https://github.com/ohmyzsh/ohmyzsh/blob/master/tools/install.sh for official script.
oh_my_install_dir="${user_rc_path}/.oh-my-zsh"
if [ ! -d "${oh_my_install_dir}" ] && [ "${INSTALL_OH_MYS}" = "true" ]; then
template_path="${oh_my_install_dir}/templates/zshrc.zsh-template"
user_rc_file="${user_rc_path}/.zshrc"
umask g-w,o-w
mkdir -p ${oh_my_install_dir}
git clone --depth=1 \
-c core.eol=lf \
-c core.autocrlf=false \
-c fsck.zeroPaddedFilemode=ignore \
-c fetch.fsck.zeroPaddedFilemode=ignore \
-c receive.fsck.zeroPaddedFilemode=ignore \
"https://github.com/ohmyzsh/ohmyzsh" "${oh_my_install_dir}" 2>&1
echo -e "$(cat "${template_path}")\nDISABLE_AUTO_UPDATE=true\nDISABLE_UPDATE_PROMPT=true" > ${user_rc_file}
sed -i -e 's/ZSH_THEME=.*/ZSH_THEME="codespaces"/g' ${user_rc_file}
mkdir -p ${oh_my_install_dir}/custom/themes
echo "${codespaces_zsh}" > "${oh_my_install_dir}/custom/themes/codespaces.zsh-theme"
# Shrink git while still enabling updates
cd "${oh_my_install_dir}"
git repack -a -d -f --depth=1 --window=1
# Copy to non-root user if one is specified
if [ "${USERNAME}" != "root" ]; then
cp -rf "${user_rc_file}" "${oh_my_install_dir}" /root
chown -R ${USERNAME}:${USERNAME} "${user_rc_path}"
fi
fi
fi
# Persist image metadata info, script if meta.env found in same directory
meta_info_script="$(cat << 'EOF'
#!/bin/sh
. /usr/local/etc/vscode-dev-containers/meta.env
# Minimal output
if [ "$1" = "version" ] || [ "$1" = "image-version" ]; then
echo "${VERSION}"
exit 0
elif [ "$1" = "release" ]; then
echo "${GIT_REPOSITORY_RELEASE}"
exit 0
elif [ "$1" = "content" ] || [ "$1" = "content-url" ] || [ "$1" = "contents" ] || [ "$1" = "contents-url" ]; then
echo "${CONTENTS_URL}"
exit 0
fi
#Full output
echo
echo "Development container image information"
echo
if [ ! -z "${VERSION}" ]; then echo "- Image version: ${VERSION}"; fi
if [ ! -z "${DEFINITION_ID}" ]; then echo "- Definition ID: ${DEFINITION_ID}"; fi
if [ ! -z "${VARIANT}" ]; then echo "- Variant: ${VARIANT}"; fi
if [ ! -z "${GIT_REPOSITORY}" ]; then echo "- Source code repository: ${GIT_REPOSITORY}"; fi
if [ ! -z "${GIT_REPOSITORY_RELEASE}" ]; then echo "- Source code release/branch: ${GIT_REPOSITORY_RELEASE}"; fi
if [ ! -z "${BUILD_TIMESTAMP}" ]; then echo "- Timestamp: ${BUILD_TIMESTAMP}"; fi
if [ ! -z "${CONTENTS_URL}" ]; then echo && echo "More info: ${CONTENTS_URL}"; fi
echo
EOF
)"
if [ -f "${SCRIPT_DIR}/meta.env" ]; then
mkdir -p /usr/local/etc/vscode-dev-containers/
cp -f "${SCRIPT_DIR}/meta.env" /usr/local/etc/vscode-dev-containers/meta.env
echo "${meta_info_script}" > /usr/local/bin/devcontainer-info
chmod +x /usr/local/bin/devcontainer-info
fi
# Write marker file
mkdir -p "$(dirname "${MARKER_FILE}")"
echo -e "\
PACKAGES_ALREADY_INSTALLED=${PACKAGES_ALREADY_INSTALLED}\n\
LOCALE_ALREADY_SET=${LOCALE_ALREADY_SET}\n\
EXISTING_NON_ROOT_USER=${EXISTING_NON_ROOT_USER}\n\
RC_SNIPPET_ALREADY_ADDED=${RC_SNIPPET_ALREADY_ADDED}\n\
ZSH_ALREADY_INSTALLED=${ZSH_ALREADY_INSTALLED}" > "${MARKER_FILE}"
echo "Done!"
@@ -0,0 +1,224 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./docker-debian.sh [enable non-root docker socket access flag] [source socket] [target socket] [non-root user] [use moby]
ENABLE_NONROOT_DOCKER=${1:-"true"}
SOURCE_SOCKET=${2:-"/var/run/docker-host.sock"}
TARGET_SOCKET=${3:-"/var/run/docker.sock"}
USERNAME=${4:-"automatic"}
USE_MOBY=${5:-"true"}
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install dependencies
check_packages apt-transport-https curl ca-certificates gnupg2
# Install Docker / Moby CLI if not already installed
if type docker > /dev/null 2>&1; then
echo "Docker / Moby CLI already installed."
else
# Source /etc/os-release to get OS info
. /etc/os-release
if [ "${USE_MOBY}" = "true" ]; then
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
apt-get update
apt-get -y install --no-install-recommends moby-cli moby-buildx moby-compose
else
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
curl -fsSL https://download.docker.com/linux/${ID}/gpg | gpg --dearmor > /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get -y install --no-install-recommends docker-ce-cli
fi
fi
# Install Docker Compose if not already installed and is on a supported architecture
if type docker-compose > /dev/null 2>&1; then
echo "Docker Compose already installed."
else
TARGET_COMPOSE_ARCH="$(uname -m)"
if [ "${TARGET_COMPOSE_ARCH}" = "amd64" ]; then
TARGET_COMPOSE_ARCH="x86_64"
fi
if [ "${TARGET_COMPOSE_ARCH}" != "x86_64" ]; then
# Use pip to get a version that runns on this architecture
if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv pipx > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install python3-minimal python3-pip libffi-dev python3-venv pipx
fi
export PIPX_HOME=/usr/local/pipx
mkdir -p ${PIPX_HOME}
export PIPX_BIN_DIR=/usr/local/bin
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx install --system-site-packages --pip-args '--no-cache-dir --force-reinstall' docker-compose
rm -rf /tmp/pip-tmp
else
LATEST_COMPOSE_VERSION=$(basename "$(curl -fsSL -o /dev/null -w "%{url_effective}" https://github.com/docker/compose/releases/latest)")
curl -fsSL "https://github.com/docker/compose/releases/download/${LATEST_COMPOSE_VERSION}/docker-compose-$(uname -s)-${TARGET_COMPOSE_ARCH}" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
fi
# If init file already exists, exit
if [ -f "/usr/local/share/docker-init.sh" ]; then
exit 0
fi
# By default, make the source and target sockets the same
if [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ]; then
touch "${SOURCE_SOCKET}"
ln -s "${SOURCE_SOCKET}" "${TARGET_SOCKET}"
fi
# Add a stub if not adding non-root user access, user is root
if [ "${ENABLE_NONROOT_DOCKER}" = "false" ] || [ "${USERNAME}" = "root" ]; then
echo '/usr/bin/env bash -c "\$@"' > /usr/local/share/docker-init.sh
chmod +x /usr/local/share/docker-init.sh
exit 0
fi
# If enabling non-root access and specified user is found, setup socat and add script
chown -h "${USERNAME}":root "${TARGET_SOCKET}"
if ! dpkg -s socat > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install socat
fi
tee /usr/local/share/docker-init.sh > /dev/null \
<< EOF
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
set -e
SOCAT_PATH_BASE=/tmp/vscr-docker-from-docker
SOCAT_LOG=\${SOCAT_PATH_BASE}.log
SOCAT_PID=\${SOCAT_PATH_BASE}.pid
# Wrapper function to only use sudo if not already root
sudoIf()
{
if [ "\$(id -u)" -ne 0 ]; then
sudo "\$@"
else
"\$@"
fi
}
# Log messages
log()
{
echo -e "[\$(date)] \$@" | sudoIf tee -a \${SOCAT_LOG} > /dev/null
}
echo -e "\n** \$(date) **" | sudoIf tee -a \${SOCAT_LOG} > /dev/null
log "Ensuring ${USERNAME} has access to ${SOURCE_SOCKET} via ${TARGET_SOCKET}"
# If enabled, try to add a docker group with the right GID. If the group is root,
# fall back on using socat to forward the docker socket to another unix socket so
# that we can set permissions on it without affecting the host.
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ] && [ "${SOURCE_SOCKET}" != "${TARGET_SOCKET}" ] && [ "${USERNAME}" != "root" ] && [ "${USERNAME}" != "0" ]; then
SOCKET_GID=\$(stat -c '%g' ${SOURCE_SOCKET})
if [ "\${SOCKET_GID}" != "0" ]; then
log "Adding user to group with GID \${SOCKET_GID}."
if [ "\$(cat /etc/group | grep :\${SOCKET_GID}:)" = "" ]; then
sudoIf groupadd --gid \${SOCKET_GID} docker-host
fi
# Add user to group if not already in it
if [ "\$(id ${USERNAME} | grep -E "groups.*(=|,)\${SOCKET_GID}\(")" = "" ]; then
sudoIf usermod -aG \${SOCKET_GID} ${USERNAME}
fi
else
# Enable proxy if not already running
if [ ! -f "\${SOCAT_PID}" ] || ! ps -p \$(cat \${SOCAT_PID}) > /dev/null; then
log "Enabling socket proxy."
log "Proxying ${SOURCE_SOCKET} to ${TARGET_SOCKET} for vscode"
sudoIf rm -rf ${TARGET_SOCKET}
(sudoIf socat UNIX-LISTEN:${TARGET_SOCKET},fork,mode=660,user=${USERNAME} UNIX-CONNECT:${SOURCE_SOCKET} 2>&1 | sudoIf tee -a \${SOCAT_LOG} > /dev/null & echo "\$!" | sudoIf tee \${SOCAT_PID} > /dev/null)
else
log "Socket proxy already running."
fi
fi
log "Success"
fi
# Execute whatever commands were passed in (if any). This allows us
# to set this script to ENTRYPOINT while still executing the default CMD.
set +e
exec "\$@"
EOF
chmod +x /usr/local/share/docker-init.sh
chown ${USERNAME}:root /usr/local/share/docker-init.sh
echo "Done!"
@@ -0,0 +1,237 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./docker-in-docker-debian.sh [enable non-root docker access flag] [non-root user] [use moby]
ENABLE_NONROOT_DOCKER=${1:-"true"}
USERNAME=${2:-"automatic"}
USE_MOBY=${3:-"true"}
MICROSOFT_GPG_KEYS_URI="https://packages.microsoft.com/keys/microsoft.asc"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install dependencies
check_packages apt-transport-https curl ca-certificates lxc pigz iptables gnupg2
# Swap to legacy iptables for compatibility
if type iptables-legacy > /dev/null 2>&1; then
update-alternatives --set iptables /usr/sbin/iptables-legacy
update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
fi
# Install Docker / Moby CLI if not already installed
if type docker > /dev/null 2>&1 && type dockerd > /dev/null 2>&1; then
echo "Docker / Moby CLI and Engine already installed."
else
# Source /etc/os-release to get OS info
. /etc/os-release
if [ "${USE_MOBY}" = "true" ]; then
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
get_common_setting MICROSOFT_GPG_KEYS_URI
curl -sSL ${MICROSOFT_GPG_KEYS_URI} | gpg --dearmor > /usr/share/keyrings/microsoft-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/microsoft-archive-keyring.gpg] https://packages.microsoft.com/repos/microsoft-${ID}-${VERSION_CODENAME}-prod ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/microsoft.list
apt-get update
apt-get -y install --no-install-recommends moby-cli moby-buildx moby-compose moby-engine
else
# Import key safely (new 'signed-by' method rather than deprecated apt-key approach) and install
curl -fsSL https://download.docker.com/linux/${ID}/gpg | gpg --dearmor > /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/${ID} ${VERSION_CODENAME} stable" > /etc/apt/sources.list.d/docker.list
apt-get update
apt-get -y install --no-install-recommends docker-ce-cli docker-ce
fi
fi
echo "Finished installing docker / moby"
# Install Docker Compose if not already installed and is on a supported architecture
if type docker-compose > /dev/null 2>&1; then
echo "Docker Compose already installed."
else
TARGET_COMPOSE_ARCH="$(uname -m)"
if [ "${TARGET_COMPOSE_ARCH}" = "amd64" ]; then
TARGET_COMPOSE_ARCH="x86_64"
fi
if [ "${TARGET_COMPOSE_ARCH}" != "x86_64" ]; then
# Use pip to get a version that runns on this architecture
if ! dpkg -s python3-minimal python3-pip libffi-dev python3-venv > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install python3-minimal python3-pip libffi-dev python3-venv
fi
export PIPX_HOME=/usr/local/pipx
mkdir -p ${PIPX_HOME}
export PIPX_BIN_DIR=/usr/local/bin
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pipx_bin=pipx
if ! type pipx > /dev/null 2>&1; then
pip3 install --disable-pip-version-check --no-warn-script-location --no-cache-dir --user pipx
pipx_bin=/tmp/pip-tmp/bin/pipx
fi
${pipx_bin} install --system-site-packages --pip-args '--no-cache-dir --force-reinstall' docker-compose
rm -rf /tmp/pip-tmp
else
LATEST_COMPOSE_VERSION=$(basename "$(curl -fsSL -o /dev/null -w "%{url_effective}" https://github.com/docker/compose/releases/latest)")
curl -fsSL "https://github.com/docker/compose/releases/download/${LATEST_COMPOSE_VERSION}/docker-compose-$(uname -s)-${TARGET_COMPOSE_ARCH}" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
fi
fi
# If init file already exists, exit
if [ -f "/usr/local/share/docker-init.sh" ]; then
echo "/usr/local/share/docker-init.sh already exists, so exiting."
exit 0
fi
echo "docker-init doesnt exist..."
# Add user to the docker group
if [ "${ENABLE_NONROOT_DOCKER}" = "true" ]; then
if ! getent group docker > /dev/null 2>&1; then
groupadd docker
fi
usermod -aG docker ${USERNAME}
fi
tee /usr/local/share/docker-init.sh > /dev/null \
<< 'EOF'
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
sudoIf()
{
if [ "$(id -u)" -ne 0 ]; then
sudo "$@"
else
"$@"
fi
}
# explicitly remove dockerd and containerd PID file to ensure that it can start properly if it was stopped uncleanly
# ie: docker kill <ID>
sudoIf find /run /var/run -iname 'docker*.pid' -delete || :
sudoIf find /run /var/run -iname 'container*.pid' -delete || :
set -e
## Dind wrapper script from docker team
# Maintained: https://github.com/moby/moby/blob/master/hack/dind
export container=docker
if [ -d /sys/kernel/security ] && ! sudoIf mountpoint -q /sys/kernel/security; then
sudoIf mount -t securityfs none /sys/kernel/security || {
echo >&2 'Could not mount /sys/kernel/security.'
echo >&2 'AppArmor detection and --privileged mode might break.'
}
fi
# Mount /tmp (conditionally)
if ! sudoIf mountpoint -q /tmp; then
sudoIf mount -t tmpfs none /tmp
fi
# cgroup v2: enable nesting
if [ -f /sys/fs/cgroup/cgroup.controllers ]; then
# move the init process (PID 1) from the root group to the /init group,
# otherwise writing subtree_control fails with EBUSY.
sudoIf mkdir -p /sys/fs/cgroup/init
sudoIf echo 1 > /sys/fs/cgroup/init/cgroup.procs
# enable controllers
sudoIf sed -e 's/ / +/g' -e 's/^/+/' < /sys/fs/cgroup/cgroup.controllers \
> /sys/fs/cgroup/cgroup.subtree_control
fi
## Dind wrapper over.
# Handle DNS
set +e
cat /etc/resolv.conf | grep -i 'internal.cloudapp.net'
if [ $? -eq 0 ]
then
echo "Setting dockerd Azure DNS."
CUSTOMDNS="--dns 168.63.129.16"
else
echo "Not setting dockerd DNS manually."
CUSTOMDNS=""
fi
set -e
# Start docker/moby engine
( sudoIf dockerd $CUSTOMDNS > /tmp/dockerd.log 2>&1 ) &
set +e
# Execute whatever commands were passed in (if any). This allows us
# to set this script to ENTRYPOINT while still executing the default CMD.
exec "$@"
EOF
chmod +x /usr/local/share/docker-init.sh
chown ${USERNAME}:root /usr/local/share/docker-init.sh
@@ -0,0 +1,140 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/git-from-src.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./git-from-src-debian.sh [version] [use PPA if available]
GIT_VERSION=${1:-"latest"}
USE_PPA_IF_AVAILABLE=${2:-"false"}
GIT_CORE_PPA_ARCHIVE_GPG_KEY=E1DD270288B4E6030699E45FA1715D88E1DF1F24
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Import the specified key in a variable name passed in as
receive_gpg_keys() {
get_common_setting $1
local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
local keyring_args=""
if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to install rvm."
exit 1
fi
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
export DEBIAN_FRONTEND=noninteractive
# Source /etc/os-release to get OS info
. /etc/os-release
# If ubuntu, PPAs allowed, and latest - install from there
if ([ "${GIT_VERSION}" = "latest" ] || [ "${GIT_VERSION}" = "lts" ] || [ "${GIT_VERSION}" = "current" ]) && [ "${ID}" = "ubuntu" ] && [ "${USE_PPA_IF_AVAILABLE}" = "true" ]; then
echo "Using PPA to install latest git..."
check_packages apt-transport-https curl ca-certificates gnupg2
receive_gpg_keys GIT_CORE_PPA_ARCHIVE_GPG_KEY /usr/share/keyrings/gitcoreppa-archive-keyring.gpg
echo -e "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gitcoreppa-archive-keyring.gpg] http://ppa.launchpad.net/git-core/ppa/ubuntu ${VERSION_CODENAME} main\ndeb-src [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/gitcoreppa-archive-keyring.gpg] http://ppa.launchpad.net/git-core/ppa/ubuntu ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/git-core-ppa.list
apt-get update
apt-get -y install --no-install-recommends git
rm -rf "/tmp/tmp-gnupg"
exit 0
fi
# Install required packages to build if missing
check_packages build-essential curl ca-certificates tar gettext libssl-dev zlib1g-dev libcurl?-openssl-dev libexpat1-dev
# Partial version matching
if [ "$(echo "${GIT_VERSION}" | grep -o '\.' | wc -l)" != "2" ]; then
requested_version="${GIT_VERSION}"
version_list="$(curl -sSL -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/git/git/tags" | grep -oP '"name":\s*"v\K[0-9]+\.[0-9]+\.[0-9]+"' | tr -d '"' | sort -rV )"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "lts" ] || [ "${requested_version}" = "current" ]; then
GIT_VERSION="$(echo "${version_list}" | head -n 1)"
else
set +e
GIT_VERSION="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
if [ -z "${GIT_VERSION}" ] || ! echo "${version_list}" | grep "^${GIT_VERSION//./\\.}$" > /dev/null 2>&1; then
echo "Invalid git version: ${requested_version}" >&2
exit 1
fi
fi
echo "Downloading source for ${GIT_VERSION}..."
curl -sL https://github.com/git/git/archive/v${GIT_VERSION}.tar.gz | tar -xzC /tmp 2>&1
echo "Building..."
cd /tmp/git-${GIT_VERSION}
make -s prefix=/usr/local all && make -s prefix=/usr/local install 2>&1
rm -rf /tmp/git-${GIT_VERSION}
echo "Done!"
@@ -0,0 +1,188 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/github.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./github-debian.sh [version]
CLI_VERSION=${1:-"latest"}
GITHUB_CLI_ARCHIVE_GPG_KEY=C99B11DEB97541F0
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Import the specified key in a variable name passed in as
receive_gpg_keys() {
get_common_setting $1
local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to install rvm."
exit 1
fi
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Import the specified key in a variable name passed in as
receive_gpg_keys() {
get_common_setting $1
local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
local keyring_args=""
if [ ! -z "$2" ]; then
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to install rvm."
exit 1
fi
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
export DEBIAN_FRONTEND=noninteractive
# Install curl, apt-transport-https, curl, gpg, or dirmngr, git if missing
check_packages curl ca-certificates apt-transport-https dirmngr gnupg2
if ! type git > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends git
fi
# Soft version matching
if [ "${CLI_VERSION}" != "latest" ] && [ "${CLI_VERSION}" != "lts" ] && [ "${CLI_VERSION}" != "stable" ]; then
find_version_from_git_tags CLI_VERSION "https://github.com/cli/cli"
version_suffix="=${CLI_VERSION}"
else
version_suffix=""
fi
# Install the GitHub CLI
echo "Downloading github CLI..."
# Import key safely (new method rather than deprecated apt-key approach) and install
. /etc/os-release
receive_gpg_keys GITHUB_CLI_ARCHIVE_GPG_KEY /usr/share/keyrings/githubcli-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/github-cli.list
apt-get update
apt-get -y install "gh${version_suffix}"
rm -rf "/tmp/gh/gnupg"
echo "Done!"
+201
View File
@@ -0,0 +1,201 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/go.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./go-debian.sh [Go version] [GOROOT] [GOPATH] [non-root user] [Add GOPATH, GOROOT to rc files flag] [Install tools flag]
TARGET_GO_VERSION=${1:-"latest"}
TARGET_GOROOT=${2:-"/usr/local/go"}
TARGET_GOPATH=${3:-"/go"}
USERNAME=${4:-"automatic"}
UPDATE_RC=${5:-"true"}
INSTALL_GO_TOOLS=${6:-"true"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
echo -e "$1" >> /etc/bash.bashrc
if [ -f "/etc/zsh/zshrc" ]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
export DEBIAN_FRONTEND=noninteractive
# Install curl, tar, git, other dependencies if missing
check_packages curl ca-certificates tar g++ gcc libc6-dev make pkg-config
if ! type git > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends git
fi
# Get closest match for version number specified
find_version_from_git_tags TARGET_GO_VERSION "https://go.googlesource.com/go" "tags/go" "." "true"
architecture="$(uname -m)"
case $architecture in
x86_64) architecture="amd64";;
aarch64 | armv8*) architecture="arm64";;
aarch32 | armv7* | armvhf*) architecture="armv6l";;
i?86) architecture="386";;
*) echo "(!) Architecture $architecture unsupported"; exit 1 ;;
esac
# Install Go
GO_INSTALL_SCRIPT="$(cat <<EOF
set -e
echo "Downloading Go ${TARGET_GO_VERSION}..."
curl -sSL -o /tmp/go.tar.gz "https://golang.org/dl/go${TARGET_GO_VERSION}.linux-${architecture}.tar.gz"
echo "Extracting Go ${TARGET_GO_VERSION}..."
tar -xzf /tmp/go.tar.gz -C "${TARGET_GOROOT}" --strip-components=1
rm -f /tmp/go.tar.gz
EOF
)"
if [ "${TARGET_GO_VERSION}" != "none" ] && ! type go > /dev/null 2>&1; then
mkdir -p "${TARGET_GOROOT}" "${TARGET_GOPATH}"
chown -R ${USERNAME} "${TARGET_GOROOT}" "${TARGET_GOPATH}"
su ${USERNAME} -c "${GO_INSTALL_SCRIPT}"
else
echo "Go already installed. Skipping."
fi
# Install Go tools that are isImportant && !replacedByGopls based on
# https://github.com/golang/vscode-go/blob/0ff533d408e4eb8ea54ce84d6efa8b2524d62873/src/goToolsInformation.ts
# Exception `dlv-dap` is a copy of github.com/go-delve/delve/cmd/dlv built from the master.
GO_TOOLS="\
golang.org/x/tools/gopls@latest \
honnef.co/go/tools/cmd/staticcheck@latest \
golang.org/x/lint/golint@latest \
github.com/mgechev/revive@latest \
github.com/uudashr/gopkgs/v2/cmd/gopkgs@latest \
github.com/ramya-rao-a/go-outline@latest \
github.com/go-delve/delve/cmd/dlv@latest \
github.com/golangci/golangci-lint/cmd/golangci-lint@latest"
if [ "${INSTALL_GO_TOOLS}" = "true" ]; then
echo "Installing common Go tools..."
export PATH=${TARGET_GOROOT}/bin:${PATH}
mkdir -p /tmp/gotools /usr/local/etc/vscode-dev-containers ${TARGET_GOPATH}/bin
cd /tmp/gotools
export GOPATH=/tmp/gotools
export GOCACHE=/tmp/gotools/cache
# Use go get for versions of go under 1.17
go_install_command=install
if [[ "1.16" > "$(go version | grep -oP 'go\K[0-9]+\.[0-9]+(\.[0-9]+)?')" ]]; then
export GO111MODULE=on
go_install_command=get
echo "Go version < 1.17, using go get."
fi
(echo "${GO_TOOLS}" | xargs -n 1 go ${go_install_command} -v )2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log
# Move Go tools into path and clean up
mv /tmp/gotools/bin/* ${TARGET_GOPATH}/bin/
# install dlv-dap (dlv@master)
go ${go_install_command} -v github.com/go-delve/delve/cmd/dlv@master 2>&1 | tee -a /usr/local/etc/vscode-dev-containers/go.log
mv /tmp/gotools/bin/dlv ${TARGET_GOPATH}/bin/dlv-dap
rm -rf /tmp/gotools
chown -R ${USERNAME} "${TARGET_GOPATH}"
fi
# Add GOPATH variable and bin directory into PATH in bashrc/zshrc files (unless disabled)
updaterc "$(cat << EOF
export GOPATH="${TARGET_GOPATH}"
if [[ "\${PATH}" != *"\${GOPATH}/bin"* ]]; then export PATH="\${PATH}:\${GOPATH}/bin"; fi
export GOROOT="${TARGET_GOROOT}"
if [[ "\${PATH}" != *"\${GOROOT}/bin"* ]]; then export PATH="\${PATH}:\${GOROOT}/bin"; fi
EOF
)"
echo "Done!"
+105
View File
@@ -0,0 +1,105 @@
#!/usr/bin/env bash
#
# This is a replicated script.
#
# Syntax: ./k3s-debian.sh [k3s version] [k3s SHA256]
set -e
K3S_VERSION="${1:-"latest"}" # latest is also valid
K3S_SHA256="${2:-"automatic"}"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
architecture="$(uname -m)"
case $architecture in
x86_64) architecture="amd64";;
aarch64 | armv8*) architecture="arm64";;
aarch32 | armv7* | armvhf*) architecture="armhf";;
*) echo "(!) Architecture $architecture unsupported"; exit 1 ;;
esac
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9ks\+]+)?"
else
last_part="${escaped_separator}[0-9ks\+]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
echo $version_list
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s+]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Install K3s, verify checksum
if [ "${K3S_VERSION}" != "none" ]; then
echo "Downloading k3s..."
urlPrefix=
if [ "${K3S_VERSION}" = "latest" ] || [ "${K3S_VERSION}" = "lts" ] || [ "${K3S_VERSION}" = "current" ] || [ "${K3S_VERSION}" = "stable" ]; then
K3S_VERSION="latest"
urlPrefix="https://github.com/k3s-io/k3s/releases/latest/download"
else
find_version_from_git_tags K3S_VERSION https://github.com/k3s-io/k3s
if [ "${K3S_VERSION::1}" != "v" ]; then
K3S_VERSION="v${K3S_VERSION}"
fi
urlPrefix="https://github.com/k3s-io/k3s/releases/download/${K3S_VERSION}"
fi
# URL encode plus sign
K3S_VERSION="$(echo $K3S_VERSION | sed --expression='s/+/%2B/g')"
# latest is also valid in the download URLs
downloadUrl="${urlPrefix}/k3s${architecture}"
if [ "${architecture}" = "amd64" ]; then
downloadUrl="${urlPrefix}/k3s"
fi
curl -sSL -o /usr/local/bin/k3s "${downloadUrl}"
chmod 0755 /usr/local/bin/k3s
if [ "$K3S_SHA256" = "automatic" ]; then
shaUrl="${urlPrefix}/sha256sum-${architecture}.txt"
if [ "${architecture}" = "armhf" ]; then
shaUrl="${urlPrefix}/sha256sum-arm.txt"
fi
# Manifest contains image hashes, but we only need the binary
K3S_SHA256="$(curl -sSL $shaUrl | grep -P '(^|\s)\Kk3s(?=\s|$)' | cut -d ' ' -f1 )"
fi
echo $K3S_SHA256
([ "${K3S_SHA256}" = "dev-mode" ] || (echo "${K3S_SHA256} */usr/local/bin/k3s" | sha256sum -c -))
if ! type k3s > /dev/null 2>&1; then
echo '(!) k3s installation failed!'
exit 1
fi
fi
echo -e "\nDone!"
@@ -0,0 +1,218 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/kubectl-helm.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./kubectl-helm-debian.sh [kubectl verison] [Helm version] [minikube version] [kubectl SHA256] [Helm SHA256] [minikube SHA256]
set -e
KUBECTL_VERSION="${1:-"latest"}"
HELM_VERSION="${2:-"latest"}"
MINIKUBE_VERSION="${3:-"none"}" # latest is also valid
KUBECTL_SHA256="${4:-"automatic"}"
HELM_SHA256="${5:-"automatic"}"
MINIKUBE_SHA256="${6:-"automatic"}"
HELM_GPG_KEYS_URI="https://raw.githubusercontent.com/helm/helm/main/KEYS"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install dependencies
check_packages curl ca-certificates coreutils gnupg2 dirmngr bash-completion
if ! type git > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends git
fi
architecture="$(uname -m)"
case $architecture in
x86_64) architecture="amd64";;
aarch64 | armv8*) architecture="arm64";;
aarch32 | armv7* | armvhf*) architecture="arm";;
i?86) architecture="386";;
*) echo "(!) Architecture $architecture unsupported"; exit 1 ;;
esac
# Install the kubectl, verify checksum
echo "Downloading kubectl..."
if [ "${KUBECTL_VERSION}" = "latest" ] || [ "${KUBECTL_VERSION}" = "lts" ] || [ "${KUBECTL_VERSION}" = "current" ] || [ "${KUBECTL_VERSION}" = "stable" ]; then
KUBECTL_VERSION="$(curl -sSL https://dl.k8s.io/release/stable.txt)"
else
find_version_from_git_tags KUBECTL_VERSION https://github.com/kubernetes/kubernetes
fi
if [ "${KUBECTL_VERSION::1}" != 'v' ]; then
KUBECTL_VERSION="v${KUBECTL_VERSION}"
fi
curl -sSL -o /usr/local/bin/kubectl "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl"
chmod 0755 /usr/local/bin/kubectl
if [ "$KUBECTL_SHA256" = "automatic" ]; then
KUBECTL_SHA256="$(curl -sSL "https://dl.k8s.io/${KUBECTL_VERSION}/bin/linux/${architecture}/kubectl.sha256")"
fi
([ "${KUBECTL_SHA256}" = "dev-mode" ] || (echo "${KUBECTL_SHA256} */usr/local/bin/kubectl" | sha256sum -c -))
if ! type kubectl > /dev/null 2>&1; then
echo '(!) kubectl installation failed!'
exit 1
fi
# kubectl bash completion
kubectl completion bash > /etc/bash_completion.d/kubectl
# kubectl zsh completion
mkdir -p /home/${USERNAME}/.oh-my-zsh/completions
kubectl completion zsh > /home/${USERNAME}/.oh-my-zsh/completions/_kubectl
# Install Helm, verify signature and checksum
echo "Downloading Helm..."
find_version_from_git_tags HELM_VERSION "https://github.com/helm/helm"
if [ "${HELM_VERSION::1}" != 'v' ]; then
HELM_VERSION="v${HELM_VERSION}"
fi
mkdir -p /tmp/helm
helm_filename="helm-${HELM_VERSION}-linux-${architecture}.tar.gz"
tmp_helm_filename="/tmp/helm/${helm_filename}"
curl -sSL "https://get.helm.sh/${helm_filename}" -o "${tmp_helm_filename}"
curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.asc" -o "${tmp_helm_filename}.asc"
export GNUPGHOME="/tmp/helm/gnupg"
mkdir -p "${GNUPGHOME}"
chmod 700 ${GNUPGHOME}
get_common_setting HELM_GPG_KEYS_URI
get_common_setting GPG_KEY_SERVERS true
curl -sSL "${HELM_GPG_KEYS_URI}" -o /tmp/helm/KEYS
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
gpg -q --import "/tmp/helm/KEYS"
if ! gpg --verify "${tmp_helm_filename}.asc" > ${GNUPGHOME}/verify.log 2>&1; then
echo "Verification failed!"
cat /tmp/helm/gnupg/verify.log
exit 1
fi
if [ "${HELM_SHA256}" = "automatic" ]; then
curl -sSL "https://get.helm.sh/${helm_filename}.sha256" -o "${tmp_helm_filename}.sha256"
curl -sSL "https://github.com/helm/helm/releases/download/${HELM_VERSION}/${helm_filename}.sha256.asc" -o "${tmp_helm_filename}.sha256.asc"
if ! gpg --verify "${tmp_helm_filename}.sha256.asc" > /tmp/helm/gnupg/verify.log 2>&1; then
echo "Verification failed!"
cat /tmp/helm/gnupg/verify.log
exit 1
fi
HELM_SHA256="$(cat "${tmp_helm_filename}.sha256")"
fi
([ "${HELM_SHA256}" = "dev-mode" ] || (echo "${HELM_SHA256} *${tmp_helm_filename}" | sha256sum -c -))
tar xf "${tmp_helm_filename}" -C /tmp/helm
mv -f "/tmp/helm/linux-${architecture}/helm" /usr/local/bin/
chmod 0755 /usr/local/bin/helm
rm -rf /tmp/helm
if ! type helm > /dev/null 2>&1; then
echo '(!) Helm installation failed!'
exit 1
fi
# Install Minikube, verify checksum
if [ "${MINIKUBE_VERSION}" != "none" ]; then
echo "Downloading minikube..."
if [ "${MINIKUBE_VERSION}" = "latest" ] || [ "${MINIKUBE_VERSION}" = "lts" ] || [ "${MINIKUBE_VERSION}" = "current" ] || [ "${MINIKUBE_VERSION}" = "stable" ]; then
MINIKUBE_VERSION="latest"
else
find_version_from_git_tags MINIKUBE_VERSION https://github.com/kubernetes/minikube
if [ "${MINIKUBE_VERSION::1}" != "v" ]; then
MINIKUBE_VERSION="v${MINIKUBE_VERSION}"
fi
fi
# latest is also valid in the download URLs
curl -sSL -o /usr/local/bin/minikube "https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-linux-${architecture}"
chmod 0755 /usr/local/bin/minikube
if [ "$MINIKUBE_SHA256" = "automatic" ]; then
MINIKUBE_SHA256="$(curl -sSL "https://storage.googleapis.com/minikube/releases/${MINIKUBE_VERSION}/minikube-linux-${architecture}.sha256")"
fi
([ "${MINIKUBE_SHA256}" = "dev-mode" ] || (echo "${MINIKUBE_SHA256} */usr/local/bin/minikube" | sha256sum -c -))
if ! type minikube > /dev/null 2>&1; then
echo '(!) minikube installation failed!'
exit 1
fi
fi
if ! type docker > /dev/null 2>&1; then
echo -e '\n(*) Warning: The docker command was not found.\n\nYou can use one of the following scripts to install it:\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker-in-docker.md\n\nor\n\nhttps://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/docker.md'
fi
echo -e "\nDone!"
+1
View File
@@ -0,0 +1 @@
VERSION='dev'
@@ -0,0 +1,141 @@
#!/bin/bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/node.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./node-debian.sh [directory to install nvm] [node version to install (use "none" to skip)] [non-root user] [Update rc files flag]
export NVM_DIR=${1:-"/usr/local/share/nvm"}
export NODE_VERSION=${2:-"lts"}
USERNAME=${3:-"automatic"}
UPDATE_RC=${4:-"true"}
export NVM_VERSION="0.38.0"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
echo -e "$1" >> /etc/bash.bashrc
if [ -f "/etc/zsh/zshrc" ]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install dependencies
check_packages apt-transport-https curl ca-certificates tar gnupg2
# Install yarn
if type yarn > /dev/null 2>&1; then
echo "Yarn already installed."
else
# Import key safely (new method rather than deprecated apt-key approach) and install
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | gpg --dearmor > /usr/share/keyrings/yarn-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/yarn-archive-keyring.gpg] https://dl.yarnpkg.com/debian/ stable main" > /etc/apt/sources.list.d/yarn.list
apt-get update
apt-get -y install --no-install-recommends yarn
fi
# Adjust node version if required
if [ "${NODE_VERSION}" = "none" ]; then
export NODE_VERSION=
elif [ "${NODE_VERSION}" = "lts" ]; then
export NODE_VERSION="lts/*"
fi
# Install the specified node version if NVM directory already exists, then exit
if [ -d "${NVM_DIR}" ]; then
echo "NVM already installed."
if [ "${NODE_VERSION}" != "" ]; then
su ${USERNAME} -c ". $NVM_DIR/nvm.sh && nvm install ${NODE_VERSION} && nvm clear-cache"
fi
exit 0
fi
# Create nvm group, nvm dir, and set sticky bit
if ! cat /etc/group | grep -e "^nvm:" > /dev/null 2>&1; then
groupadd -r nvm
fi
umask 0002
usermod -a -G nvm ${USERNAME}
mkdir -p ${NVM_DIR}
chown :nvm ${NVM_DIR}
chmod g+s ${NVM_DIR}
su ${USERNAME} -c "$(cat << EOF
set -e
umask 0002
# Do not update profile - we'll do this manually
export PROFILE=/dev/null
curl -so- https://raw.githubusercontent.com/nvm-sh/nvm/v${NVM_VERSION}/install.sh | bash
source ${NVM_DIR}/nvm.sh
if [ "${NODE_VERSION}" != "" ]; then
nvm alias default ${NODE_VERSION}
fi
nvm clear-cache
EOF
)" 2>&1
# Update rc files
if [ "${UPDATE_RC}" = "true" ]; then
updaterc "$(cat <<EOF
export NVM_DIR="${NVM_DIR}"
[ -s "\$NVM_DIR/nvm.sh" ] && . "\$NVM_DIR/nvm.sh"
[ -s "\$NVM_DIR/bash_completion" ] && . "\$NVM_DIR/bash_completion"
EOF
)"
fi
echo "Done!"
@@ -0,0 +1,307 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/python.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./python-debian.sh [Python Version] [Python intall path] [PIPX_HOME] [non-root user] [Update rc files flag] [install tools]
PYTHON_VERSION=${1:-"latest"}
PYTHON_INSTALL_PATH=${2:-"/usr/local/python"}
export PIPX_HOME=${3:-"/usr/local/py-utils"}
USERNAME=${4:-"automatic"}
UPDATE_RC=${5:-"true"}
INSTALL_PYTHON_TOOLS=${6:-"true"}
USE_PPA_IF_AVAILABLE=${7:-"true"}
DEADSNAKES_PPA_ARCHIVE_GPG_KEY="F23C5A6CF475977595C89F51BA6932366A755776"
PYTHON_SOURCE_GPG_KEYS="64E628F8D684696D B26995E310250568 2D347EA6AA65421D FB9921286F5E1540 3A5CA953F73C700D 04C367C218ADD4FF 0EDDC5F26A45C816 6AF053F07D9DC8D2 C9BE28DEE6DF025C 126EB563A74B06BF D9866941EA5BBD71 ED9D77D5"
GPG_KEY_SERVERS="keyserver hkp://keyserver.ubuntu.com:80
keyserver hkps://keys.openpgp.org
keyserver hkp://keyserver.pgp.com"
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Ensure that login shells get the correct path if the user updated the PATH using ENV.
rm -f /etc/profile.d/00-restore-env.sh
echo "export PATH=${PATH//$(sh -lc 'echo $PATH')/\$PATH}" > /etc/profile.d/00-restore-env.sh
chmod +x /etc/profile.d/00-restore-env.sh
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
updaterc() {
if [ "${UPDATE_RC}" = "true" ]; then
echo "Updating /etc/bash.bashrc and /etc/zsh/zshrc..."
echo -e "$1" >> /etc/bash.bashrc
if [ -f "/etc/zsh/zshrc" ]; then
echo -e "$1" >> /etc/zsh/zshrc
fi
fi
}
# Get central common setting
get_common_setting() {
if [ "${common_settings_file_loaded}" != "true" ]; then
curl -sfL "https://aka.ms/vscode-dev-containers/script-library/settings.env" 2>/dev/null -o /tmp/vsdc-settings.env || echo "Could not download settings file. Skipping."
common_settings_file_loaded=true
fi
if [ -f "/tmp/vsdc-settings.env" ]; then
local multi_line=""
if [ "$2" = "true" ]; then multi_line="-z"; fi
local result="$(grep ${multi_line} -oP "$1=\"?\K[^\"]+" /tmp/vsdc-settings.env | tr -d '\0')"
if [ ! -z "${result}" ]; then declare -g $1="${result}"; fi
fi
echo "$1=${!1}"
}
# Import the specified key in a variable name passed in as
receive_gpg_keys() {
get_common_setting $1
local keys=${!1}
get_common_setting GPG_KEY_SERVERS true
local keyring_args=""
if [ ! -z "$2" ]; then
mkdir -p "$(dirname \"$2\")"
keyring_args="--no-default-keyring --keyring $2"
fi
# Use a temporary locaiton for gpg keys to avoid polluting image
export GNUPGHOME="/tmp/tmp-gnupg"
mkdir -p ${GNUPGHOME}
chmod 700 ${GNUPGHOME}
echo -e "disable-ipv6\n${GPG_KEY_SERVERS}" > ${GNUPGHOME}/dirmngr.conf
# GPG key download sometimes fails for some reason and retrying fixes it.
local retry_count=0
local gpg_ok="false"
set +e
until [ "${gpg_ok}" = "true" ] || [ "${retry_count}" -eq "5" ];
do
echo "(*) Downloading GPG key..."
( echo "${keys}" | xargs -n 1 gpg -q ${keyring_args} --recv-keys) 2>&1 && gpg_ok="true"
if [ "${gpg_ok}" != "true" ]; then
echo "(*) Failed getting key, retring in 10s..."
(( retry_count++ ))
sleep 10s
fi
done
set -e
if [ "${gpg_ok}" = "false" ]; then
echo "(!) Failed to install rvm."
exit 1
fi
}
# Figure out correct version of a three part version number is not passed
find_version_from_git_tags() {
local variable_name=$1
local requested_version=${!variable_name}
if [ "${requested_version}" = "none" ]; then return; fi
local repository=$2
local prefix=${3:-"tags/v"}
local separator=${4:-"."}
local last_part_optional=${5:-"false"}
if [ "$(echo "${requested_version}" | grep -o "." | wc -l)" != "2" ]; then
local escaped_separator=${separator//./\\.}
local last_part
if [ "${last_part_optional}" = "true" ]; then
last_part="(${escaped_separator}[0-9]+)?"
else
last_part="${escaped_separator}[0-9]+"
fi
local regex="${prefix}\\K[0-9]+${escaped_separator}[0-9]+${last_part}$"
local version_list="$(git ls-remote --tags ${repository} | grep -oP "${regex}" | tr -d ' ' | tr "${separator}" "." | sort -rV)"
if [ "${requested_version}" = "latest" ] || [ "${requested_version}" = "current" ] || [ "${requested_version}" = "lts" ]; then
declare -g ${variable_name}="$(echo "${version_list}" | head -n 1)"
else
set +e
declare -g ${variable_name}="$(echo "${version_list}" | grep -E -m 1 "^${requested_version//./\\.}([\\.\\s]|$)")"
set -e
fi
fi
if [ -z "${!variable_name}" ] || ! echo "${version_list}" | grep "^${!variable_name//./\\.}$" > /dev/null 2>&1; then
echo -e "Invalid ${variable_name} value: ${requested_version}\nValid values:\n${version_list}" >&2
exit 1
fi
echo "${variable_name}=${!variable_name}"
}
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
install_from_ppa() {
local requested_version="python${PYTHON_VERSION}"
echo "Using PPA to install Python..."
check_packages apt-transport-https curl ca-certificates gnupg2
receive_gpg_keys DEADSNAKES_PPA_ARCHIVE_GPG_KEY /usr/share/keyrings/deadsnakes-archive-keyring.gpg
echo -e "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/deadsnakes-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu ${VERSION_CODENAME} main\ndeb-src [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/deadsnakes-archive-keyring.gpg] http://ppa.launchpad.net/deadsnakes/ppa/ubuntu ${VERSION_CODENAME} main" > /etc/apt/sources.list.d/deadsnakes-ppa.list
apt-get update
if [ "${PYTHON_VERSION}" = "latest" ] || [ "${PYTHON_VERSION}" = "current" ] || [ "${PYTHON_VERSION}" = "lts" ]; then
requested_version="$(apt-cache search '^python3\.[0-9]$' | grep -oE '^python3\.[0-9]' | sort -rV | head -n 1)"
echo "Using ${requested_version} in place of ${PYTHON_VERSION}."
fi
apt-get -y install ${requested_version}
rm -rf /tmp/tmp-gnupg
exit 0
}
install_from_source() {
if [ -d "${PYTHON_INSTALL_PATH}" ]; then
echo "Path ${PYTHON_INSTALL_PATH} already exists. Remove this existing path or select a different one."
exit 1
else
echo "Building Python ${PYTHON_VERSION} from source..."
# Install prereqs if missing
check_packages curl ca-certificates tar make build-essential libssl-dev zlib1g-dev \
wget libbz2-dev libreadline-dev libxml2-dev xz-utils tk-dev gnupg2 \
libxmlsec1-dev libsqlite3-dev libffi-dev liblzma-dev llvm dirmngr
if ! type git > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends git
fi
# Find version using soft match
find_version_from_git_tags PYTHON_VERSION "https://github.com/python/cpython"
# Download tgz of source
mkdir -p /tmp/python-src "${PYTHON_INSTALL_PATH}"
cd /tmp/python-src
TGZ_FILENAME="Python-${PYTHON_VERSION}.tgz"
TGZ_URL="https://www.python.org/ftp/python/${PYTHON_VERSION}/${TGZ_FILENAME}"
echo "Downloading ${TGZ_FILENAME}..."
curl -sSL -o "/tmp/python-src/${TGZ_FILENAME}" "${TGZ_URL}"
# Verify signature
if [ "${SKIP_SIGNATURE_CHECK}" != "true" ]; then
receive_gpg_keys PYTHON_SOURCE_GPG_KEYS
echo "Downloading ${TGZ_FILENAME}.asc..."
curl -sSL -o "/tmp/python-src/${TGZ_FILENAME}.asc" "${TGZ_URL}.asc"
gpg --verify "${TGZ_FILENAME}.asc"
fi
# Update min protocol for testing only - https://bugs.python.org/issue41561
cp /etc/ssl/openssl.cnf /tmp/python-src/
sed -i -E 's/MinProtocol[=\ ]+.*/MinProtocol = TLSv1.0/g' /tmp/python-src/openssl.cnf
export OPENSSL_CONF=/tmp/python-src/openssl.cnf
# Untar and build
tar -xzf "/tmp/python-src/${TGZ_FILENAME}" -C "/tmp/python-src" --strip-components=1
./configure --prefix="${PYTHON_INSTALL_PATH}" --enable-optimizations --with-ensurepip=install
make -j 8
make install
cd /tmp
rm -rf /tmp/python-src ${GNUPGHOME} /tmp/vscdc-settings.env
chown -R ${USERNAME} "${PYTHON_INSTALL_PATH}"
ln -s ${PYTHON_INSTALL_PATH}/bin/python3 ${PYTHON_INSTALL_PATH}/bin/python
ln -s ${PYTHON_INSTALL_PATH}/bin/pip3 ${PYTHON_INSTALL_PATH}/bin/pip
ln -s ${PYTHON_INSTALL_PATH}/bin/idle3 ${PYTHON_INSTALL_PATH}/bin/idle
ln -s ${PYTHON_INSTALL_PATH}/bin/pydoc3 ${PYTHON_INSTALL_PATH}/bin/pydoc
ln -s ${PYTHON_INSTALL_PATH}/bin/python3-config ${PYTHON_INSTALL_PATH}/bin/python-config
updaterc "export PATH=${PYTHON_INSTALL_PATH}/bin:\${PATH}"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install python from source if needed
if [ "${PYTHON_VERSION}" != "none" ]; then
# Source /etc/os-release to get OS info
. /etc/os-release
# If ubuntu, PPAs allowed - install from there
if [ "${ID}" = "ubuntu" ] && [ "${USE_PPA_IF_AVAILABLE}" = "true" ]; then
install_from_ppa
else
install_from_source
fi
fi
# If not installing python tools, exit
if [ "${INSTALL_PYTHON_TOOLS}" != "true" ]; then
echo "Done!"
exit 0;
fi
DEFAULT_UTILS="\
pylint \
flake8 \
autopep8 \
black \
yapf \
mypy \
pydocstyle \
pycodestyle \
bandit \
pipenv \
virtualenv"
export PIPX_BIN_DIR=${PIPX_HOME}/bin
export PATH=${PYTHON_INSTALL_PATH}/bin:${PIPX_BIN_DIR}:${PATH}
# Update pip
echo "Updating pip..."
python3 -m pip install --no-cache-dir --upgrade pip
# Create pipx group, dir, and set sticky bit
if ! cat /etc/group | grep -e "^pipx:" > /dev/null 2>&1; then
groupadd -r pipx
fi
usermod -a -G pipx ${USERNAME}
umask 0002
mkdir -p ${PIPX_BIN_DIR}
chown :pipx ${PIPX_HOME} ${PIPX_BIN_DIR}
chmod g+s ${PIPX_HOME} ${PIPX_BIN_DIR}
# Install tools
echo "Installing Python tools..."
export PYTHONUSERBASE=/tmp/pip-tmp
export PIP_CACHE_DIR=/tmp/pip-tmp/cache
pip3 install --disable-pip-version-check --no-warn-script-location --no-cache-dir --user pipx
/tmp/pip-tmp/bin/pipx install --pip-args=--no-cache-dir pipx
echo "${DEFAULT_UTILS}" | xargs -n 1 /tmp/pip-tmp/bin/pipx install --system-site-packages --pip-args '--no-cache-dir --force-reinstall'
rm -rf /tmp/pip-tmp
updaterc "$(cat << EOF
export PIPX_HOME="${PIPX_HOME}"
export PIPX_BIN_DIR="${PIPX_BIN_DIR}"
if [[ "\${PATH}" != *"\${PIPX_BIN_DIR}"* ]]; then export PATH="\${PATH}:\${PIPX_BIN_DIR}"; fi
EOF
)"
@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# k3d
# v5 RC is needed to deterministically set the Registry port. Should be replaces with official release
curl -s https://raw.githubusercontent.com/rancher/k3d/main/install.sh | TAG=v5.0.0-rc.4 bash
# kustomize
pushd /tmp
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash
popd
sudo mv /tmp/kustomize /usr/local/bin/
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# install Krew
# TODO (dans): ditch krew and just download the latest binaries on the path in Dockerfile
(
set -x; cd "$(mktemp -d)" &&
OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
ARCH="$(uname -m | sed -e 's/x86_64/amd64/' -e 's/\(arm\)\(64\)\?.*/\1\2/' -e 's/aarch64$/arm64/')" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/krew.tar.gz" &&
tar zxvf krew.tar.gz &&
KREW=./krew-"${OS}_${ARCH}" &&
"$KREW" install krew
)
# install krew plugins
kubectl krew install schemahero
kubectl krew install support-bundle
kubectl krew install preflights
kubectl krew install view-secret
# Make the cache from master branch
pushd /tmp
git clone https://github.com/replicatedhq/troubleshoot.git
pushd troubleshoot
# TODO (dans): find a way to cache images on image build
go mod download
popd
rm -rf kots
popd
# Clone any extra repos here
# Autocomplete Kubernetes
cat >> ~/.zshrc << EOF
source <(kubectl completion zsh)
alias k=kubectl
complete -F __start_kubectl k
EOF
# Set Git Editor Preference
cat >> ~/.zshrc << EOF
export VISUAL=vim
export EDITOR="$VISUAL"
EOF
@@ -0,0 +1,16 @@
#!/bin/bash
# modified from https://github.com/microsoft/vscode-dev-containers/blob/main/containers/codespaces-linux/.devcontainer/setup-user.sh
# not part of the standard script library
USERNAME=${1:-codespace}
SECURE_PATH_BASE=${2:-$PATH}
echo "Defaults secure_path=\"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/bin:${SECURE_PATH_BASE}\"" >> /etc/sudoers.d/securepath
# Add user to a Docker group
sudo -u ${USERNAME} mkdir /home/${USERNAME}/.vsonline
groupadd -g 800 docker
usermod -a -G docker ${USERNAME}
# Create user's .local/bin
sudo -u ${USERNAME} mkdir -p /home/${USERNAME}/.local/bin
@@ -0,0 +1,165 @@
#!/usr/bin/env bash
#-------------------------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See https://go.microsoft.com/fwlink/?linkid=2090316 for license information.
#-------------------------------------------------------------------------------------------------------------
#
# Docs: https://github.com/microsoft/vscode-dev-containers/blob/main/script-library/docs/sshd.md
# Maintainer: The VS Code and Codespaces Teams
#
# Syntax: ./sshd-debian.sh [SSH Port (don't use 22)] [non-root user] [start sshd now flag] [new password for user] [fix environment flag]
#
# Note: You can change your user's password with "sudo passwd $(whoami)" (or just "passwd" if running as root).
SSHD_PORT=${1:-"2222"}
USERNAME=${2:-"automatic"}
START_SSHD=${3:-"false"}
NEW_PASSWORD=${4:-"skip"}
FIX_ENVIRONMENT=${5:-"true"}
set -e
if [ "$(id -u)" -ne 0 ]; then
echo -e 'Script must be run as root. Use sudo, su, or add "USER root" to your Dockerfile before running this script.'
exit 1
fi
# Determine the appropriate non-root user
if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
USERNAME=""
POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
if id -u ${CURRENT_USER} > /dev/null 2>&1; then
USERNAME=${CURRENT_USER}
break
fi
done
if [ "${USERNAME}" = "" ]; then
USERNAME=root
fi
elif [ "${USERNAME}" = "none" ] || ! id -u ${USERNAME} > /dev/null 2>&1; then
USERNAME=root
fi
# Function to run apt-get if needed
apt_get_update_if_needed()
{
if [ ! -d "/var/lib/apt/lists" ] || [ "$(ls /var/lib/apt/lists/ | wc -l)" = "0" ]; then
echo "Running apt-get update..."
apt-get update
else
echo "Skipping apt-get update."
fi
}
# Checks if packages are installed and installs them if not
check_packages() {
if ! dpkg -s "$@" > /dev/null 2>&1; then
apt_get_update_if_needed
apt-get -y install --no-install-recommends "$@"
fi
}
# Ensure apt is in non-interactive to avoid prompts
export DEBIAN_FRONTEND=noninteractive
# Install openssh-server openssh-client
check_packages openssh-server openssh-client lsof
# Generate password if new password set to the word "random"
if [ "${NEW_PASSWORD}" = "random" ]; then
NEW_PASSWORD="$(openssl rand -hex 16)"
EMIT_PASSWORD="true"
elif [ "${NEW_PASSWORD}" != "skip" ]; then
# If new password not set to skip, set it for the specified user
echo "${USERNAME}:${NEW_PASSWORD}" | chpasswd
fi
# Add user to ssh group
if [ "${USERNAME}" != "root" ]; then
usermod -aG ssh ${USERNAME}
fi
# Setup sshd
mkdir -p /var/run/sshd
sed -i 's/session\s*required\s*pam_loginuid\.so/session optional pam_loginuid.so/g' /etc/pam.d/sshd
sed -i 's/#*PermitRootLogin prohibit-password/PermitRootLogin yes/g' /etc/ssh/sshd_config
sed -i -E "s/#*\s*Port\s+.+/Port ${SSHD_PORT}/g" /etc/ssh/sshd_config
# Need to UsePAM so /etc/environment is processed
sed -i -E "s/#?\s*UsePAM\s+.+/UsePAM yes/g" /etc/ssh/sshd_config
# Script to store variables that exist at the time the ENTRYPOINT is fired
store_env_script="$(cat << 'EOF'
# Wire in codespaces secret processing to zsh if present (since may have been added to image after script was run)
if [ -f /etc/zsh/zlogin ] && ! grep '/etc/profile.d/00-restore-secrets.sh' /etc/zsh/zlogin > /dev/null 2>&1; then
echo -e "if [ -f /etc/profile.d/00-restore-secrets.sh ]; then . /etc/profile.d/00-restore-secrets.sh; fi\n$(cat /etc/zsh/zlogin 2>/dev/null || echo '')" | sudoIf tee /etc/zsh/zlogin > /dev/null
fi
EOF
)"
# Script to ensure login shells get the latest Codespaces secrets
restore_secrets_script="$(cat << 'EOF'
#!/bin/sh
if [ "${CODESPACES}" != "true" ] || [ "${VSCDC_FIXED_SECRETS}" = "true" ] || [ ! -z "${GITHUB_CODESPACES_TOKEN}" ]; then
# Not codespaces, already run, or secrets already in environment, so return
return
fi
if [ -f /workspaces/.codespaces/shared/.env ]; then
set -o allexport
. /workspaces/.codespaces/shared/.env
set +o allexport
fi
export VSCDC_FIXED_SECRETS=true
EOF
)"
# Write out a scripts that can be referenced as an ENTRYPOINT to auto-start sshd and fix login environments
tee /usr/local/share/ssh-init.sh > /dev/null \
<< 'EOF'
#!/usr/bin/env bash
# This script is intended to be run as root with a container that runs as root (even if you connect with a different user)
# However, it supports running as a user other than root if passwordless sudo is configured for that same user.
set -e
sudoIf()
{
if [ "$(id -u)" -ne 0 ]; then
sudo "$@"
else
"$@"
fi
}
EOF
if [ "${FIX_ENVIRONMENT}" = "true" ]; then
echo "${store_env_script}" >> /usr/local/share/ssh-init.sh
echo "${restore_secrets_script}" > /etc/profile.d/00-restore-secrets.sh
chmod +x /etc/profile.d/00-restore-secrets.sh
# Wire in zsh if present
if type zsh > /dev/null 2>&1; then
echo -e "if [ -f /etc/profile.d/00-restore-secrets.sh ]; then . /etc/profile.d/00-restore-secrets.sh; fi\n$(cat /etc/zsh/zlogin 2>/dev/null || echo '')" > /etc/zsh/zlogin
fi
fi
tee -a /usr/local/share/ssh-init.sh > /dev/null \
<< 'EOF'
# ** Start SSH server **
sudoIf /etc/init.d/ssh start 2>&1 | sudoIf tee /tmp/sshd.log > /dev/null
set +e
exec "$@"
EOF
chmod +x /usr/local/share/ssh-init.sh
# If we should start sshd now, do so
if [ "${START_SSHD}" = "true" ]; then
/usr/local/share/ssh-init.sh
fi
# Output success details
echo -e "Done!\n\n- Port: ${SSHD_PORT}\n- User: ${USERNAME}"
if [ "${EMIT_PASSWORD}" = "true" ]; then
echo "- Password: ${NEW_PASSWORD}"
fi
echo -e "\nForward port ${SSHD_PORT} to your local machine and run:\n\n ssh -p ${SSHD_PORT} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o GlobalKnownHostsFile=/dev/null ${USERNAME}@localhost\n"
@@ -0,0 +1,8 @@
#!/usr/bin/env bash
# Setup the cluster
k3d cluster create --config /etc/replicated/k3d-cluster.yaml --kubeconfig-update-default
# Clone any extra repos here
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
# Start the cluster here
k3d cluster start replicated
+1
View File
@@ -0,0 +1 @@
* @replicatedhq/day2
+27
View File
@@ -0,0 +1,27 @@
---
name: Bug report
about: Report a problem with Troubleshoot
labels: 'bug'
---
**Bug Description**
Write a concise description of the problem here.
**Expected Behavior**
Include a description of the expected behaviour here.
**Steps To Reproduce**
Include the commands to reproduce the issue including any output. Any information that will help us to understand the problem is useful. Feel free to paste long output into a [Github gist](https://gist.github.com) and include the link here.
**Additional Context**
Include the following information.
- Troubleshoot version. If you built from source, note that including the version of Go you used to build with.
- Operating system
- Operating system version
- Other details that might be helpful in diagnosing the problem
+22
View File
@@ -0,0 +1,22 @@
---
name: Feature Request
about: Suggest a feature
labels: 'feature'
---
**Describe the rationale for the suggested feature.**
Insert a description of the rationale for the new feature here. For example, you could describe a problem that Troubleshoot doesn't address, a limitation, or an idea to improve Troubleshoot.
**Describe the feature**
Insert a description of the feature here. Be specific about how it addresses the any problems, limitations, or suggested improvements outlined in the rationale for the feature.
**Describe alternatives you've considered**
Describe alternative solutions here. Include any workarounds you've considered.
**Additional context**
Add additional context about the feature request. If the change is substantial, consider attaching files to the issue outlining architectural changes, data flows, file formats etc., anything that helps describe the requested change.
+15
View File
@@ -0,0 +1,15 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: "gomod" # See documentation for possible values
directory: "/" # Location of package manifests
labels:
- "dependencies"
- "go"
- "type::chore"
schedule:
interval: "weekly"
+196
View File
@@ -0,0 +1,196 @@
on:
pull_request:
branches:
- main
push:
branches:
- "main"
tags:
- "v*.*.*"
jobs:
build:
runs-on: ubuntu-18.04
steps:
- uses: actions/setup-go@v1
with:
go-version: "1.17"
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
shell: bash
- uses: actions/checkout@v2
- run: make
compile-preflight:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/setup-go@v1
with:
go-version: '1.17'
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
shell: bash
- uses: actions/checkout@master
- run: make preflight
- uses: actions/upload-artifact@v1
with:
name: preflight
path: bin/preflight
validate-preflight:
runs-on: ubuntu-latest
needs: compile-preflight
steps:
- name: Download preflight binary
uses: actions/download-artifact@v1
with:
name: preflight
path: bin/
- uses: engineerd/setup-kind@v0.5.0
- run: chmod +x bin/preflight
- run: |
./bin/preflight --interactive=false --format=json https://preflight.replicated.com > result.json
cat result.json
EXIT_STATUS=0
if grep -q "was not collected" result.json; then
echo "Some files were not collected"
EXIT_STATUS=1
fi
if (( `jq '.pass | length' result.json` < 1 )); then
echo "No passing preflights found"
EXIT_STATUS=1
fi
if (( `jq '.warn | length' result.json` < 1 )); then
echo "No warnings found"
EXIT_STATUS=1
fi
if (( `jq '.fail | length' result.json` < 1 )); then
echo "No failed preflights found"
EXIT_STATUS=1
fi
exit $EXIT_STATUS
compile-supportbundle:
runs-on: ubuntu-latest
needs: build
steps:
- uses: actions/setup-go@v1
with:
go-version: '1.17'
- name: setup env
run: |
echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV
echo "$(go env GOPATH)/bin" >> $GITHUB_PATH
shell: bash
- uses: actions/checkout@master
- run: make support-bundle
- uses: actions/upload-artifact@v1
with:
name: support-bundle
path: bin/support-bundle
validate-supportbundle:
runs-on: ubuntu-latest
needs: compile-supportbundle
steps:
- uses: actions/checkout@v1
- name: Download support-bundle binary
uses: actions/download-artifact@v1
with:
name: support-bundle
path: bin/
- uses: engineerd/setup-kind@v0.5.0
- run: chmod +x bin/support-bundle
- run: ./bin/support-bundle ./examples/support-bundle/sample-collectors.yaml
- run: ./bin/support-bundle ./examples/support-bundle/sample-supportbundle.yaml
- run: ./bin/support-bundle https://kots.io
goreleaser-test:
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') != true
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Unshallow
run: git fetch --prune --unshallow
- uses: actions/setup-go@v1
with:
go-version: "1.17"
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
version: "v0.183.0"
args: build --rm-dist --snapshot --config deploy/.goreleaser.yaml
goreleaser:
runs-on: ubuntu-latest
needs:
- validate-preflight
- validate-supportbundle
if: startsWith(github.ref, 'refs/tags/v')
steps:
- name: Checkout
uses: actions/checkout@v2
- uses: azure/docker-login@v1
with:
username: repldeploy2
password: ${{ secrets.DOCKERHUB_PASSWORD }}
- name: Unshallow
run: git fetch --prune --unshallow
- uses: actions/setup-go@v1
with:
go-version: "1.17"
- uses: sigstore/cosign-installer@main
with:
cosign-release: "v1.2.1"
- name: Get Cosign Key
run: |
echo $COSIGN_KEY | base64 -d > ./cosign.key
env:
COSIGN_KEY: ${{secrets.COSIGN_KEY}}
- name: Generate SBOM
run: |
make sbom
env:
COSIGN_PASSWORD: ${{ secrets.COSIGN_PASSWORD }}
COSIGN_KEY: ${{ secrets.COSIGN_KEY }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
version: "v0.183.0"
args: release --rm-dist --config deploy/.goreleaser.yaml
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Update new preflight version in krew-index
uses: rajatjindal/krew-release-bot@v0.0.38
with:
krew_template_file: deploy/krew/preflight.yaml
- name: Update new support-bundle version in krew-index
uses: rajatjindal/krew-release-bot@v0.0.38
with:
krew_template_file: deploy/krew/support-bundle.yaml
+7
View File
@@ -27,3 +27,10 @@ vendor
*~
dist
try.sh
.vscode/
workspace.*
cosign.key
sbom/
+128
View File
@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
oss@replicated.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
+11
View File
@@ -0,0 +1,11 @@
# Contributing to Troubleshoot
Thank you for your interest in Troubleshoot, we welcome your participation. Please familiarize yourself with our [Code of Conduct](https://github.com/replicatedhq/troubleshoot/blob/master/CODE_OF_CONDUCT.md) prior to contributing. There are a number of ways to participate in Troubleshoot as outlined below:
## Issues
- [Request a New Feature](https://github.com/replicatedhq/troubleshoot/issues/new?assignees=&labels=feature&template=feature_enhancement.md) Create an issue to add functionality that addresses a problem or adds an enhancement.
- [Report a Bug](https://github.com/replicatedhq/troubleshoot/issues/new?assignees=&labels=bug&template=bug_report.md) Report a problem or unexpected behaviour with Troubleshoot.
## Pull Requests
If you are interested in contributing a change to the code or documentation please open a pull request with your set of changes. The pull request will be reviewed in a timely manner.
+121 -61
View File
@@ -1,46 +1,65 @@
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
export GO111MODULE=on
all: test manager
SHELL := /bin/bash -o pipefail
VERSION_PACKAGE = github.com/replicatedhq/troubleshoot/pkg/version
VERSION ?=`git describe --tags --dirty`
DATE=`date -u +"%Y-%m-%dT%H:%M:%SZ"`
GIT_TREE = $(shell git rev-parse --is-inside-work-tree 2>/dev/null)
ifneq "$(GIT_TREE)" ""
define GIT_UPDATE_INDEX_CMD
git update-index --assume-unchanged
endef
define GIT_SHA
`git rev-parse HEAD`
endef
else
define GIT_UPDATE_INDEX_CMD
echo "Not a git repo, skipping git update-index"
endef
define GIT_SHA
""
endef
endif
define LDFLAGS
-ldflags "\
-s -w \
-X ${VERSION_PACKAGE}.version=${VERSION} \
-X ${VERSION_PACKAGE}.gitSHA=${GIT_SHA} \
-X ${VERSION_PACKAGE}.buildTime=${DATE} \
"
endef
BUILDFLAGS = -tags "netgo containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" -installsuffix netgo
all: test
.PHONY: ffi
ffi: fmt vet
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/troubleshoot.so -buildmode=c-shared ffi/main.go
# Run tests
test: generate fmt vet manifests
go test ./pkg/... ./cmd/... -coverprofile cover.out
.PHONY: manager
manager: generate fmt vet
go build -o bin/manager github.com/replicatedhq/troubleshoot/cmd/manager
test: generate fmt vet
go test ${BUILDFLAGS} ./pkg/... ./cmd/... -coverprofile cover.out
.PHONY: support-bundle
support-bundle: generate fmt vet
go build -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
.PHONY: collector
collector: generate fmt vet
go build -o bin/collector github.com/replicatedhq/troubleshoot/cmd/collector
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
.PHONY: preflight
preflight: generate fmt vet
go build -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
.PHONY: run
run: generate fmt vet
TROUBLESHOOT_EXTERNAL_MANAGER=1 go run ./cmd/manager/main.go
.PHONY: install
install: manifests
kubectl apply -f config/crds
.PHONY: deploy
deploy: manifests
kubectl apply -f config/crds
kustomize build config/default | kubectl apply -f -
.PHONY: manifests
manifests:
controller-gen paths=./pkg/apis/... output:dir=./config/crds
.PHONY: analyze
analyze: generate fmt vet
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/analyze github.com/replicatedhq/troubleshoot/cmd/analyze
.PHONY: collect
collect: generate fmt vet
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/collect github.com/replicatedhq/troubleshoot/cmd/collect
.PHONY: fmt
fmt:
@@ -48,64 +67,105 @@ fmt:
.PHONY: vet
vet:
go vet ./pkg/... ./cmd/...
go vet ${BUILDFLAGS} ./pkg/... ./cmd/...
.PHONY: generate
generate: controller-gen # client-gen
controller-gen object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/...
# client-gen --output-package=github.com/replicatedhq/troubleshoot/pkg/client --clientset-name troubleshootclientset --input-base github.com/replicatedhq/troubleshoot/pkg/apis --input troubleshoot/v1beta1 -h ./hack/boilerplate.go.txt
generate: controller-gen client-gen
$(CONTROLLER_GEN) \
object:headerFile=./hack/boilerplate.go.txt paths=./pkg/apis/...
$(CLIENT_GEN) \
--output-package=github.com/replicatedhq/troubleshoot/pkg/client \
--clientset-name troubleshootclientset \
--input-base github.com/replicatedhq/troubleshoot/pkg/apis \
--input troubleshoot/v1beta1 \
--input troubleshoot/v1beta2 \
-h ./hack/boilerplate.go.txt
.PHONY: openapischema
openapischema: controller-gen
controller-gen crd +output:dir=./config/crds paths=./pkg/apis/troubleshoot/v1beta1
controller-gen crd +output:dir=./config/crds paths=./pkg/apis/troubleshoot/v1beta2
.PHONY: schemas
schemas: fmt vet openapischema
go build ${LDFLAGS} -o bin/schemagen github.com/replicatedhq/troubleshoot/cmd/schemagen
./bin/schemagen --output-dir ./schemas
# find or download controller-gen
# download controller-gen if necessary
controller-gen:
ifeq (, $(shell which controller-gen))
go get sigs.k8s.io/controller-tools/cmd/controller-gen@v0.2.0-beta.2
CONTROLLER_GEN=$(shell go env GOPATH)/bin/controller-gen
else
go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.7.0
CONTROLLER_GEN=$(shell which controller-gen)
endif
# find or download client-gen
.PHONY: client-gen
client-gen:
ifeq (, $(shell which client-gen))
go get k8s.io/code-generator/cmd/client-gen@kubernetes-1.13.5
go install k8s.io/code-generator/cmd/client-gen@v0.22.2
CLIENT_GEN=$(shell go env GOPATH)/bin/client-gen
else
CLIENT_GEN=$(shell which client-gen)
endif
.PHONY: snapshot-release
snapshot-release:
curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --snapshot --config deploy/.goreleaser.snapshot.yml
docker push replicated/troubleshoot:alpha
docker push replicated/preflight:alpha
docker push replicated/troubleshoot-manager:alpha
.PHONY: release
release: export GITHUB_TOKEN = $(shell echo ${GITHUB_TOKEN_TROUBLESHOOT})
release:
curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --config deploy/.goreleaser.yml
.PHONY: snapshot-release
snapshot-release:
curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --snapshot --config deploy/.goreleaser.snapshot.yml
docker push replicated/troubleshoot:alpha
docker push replicated/preflight:alpha
.PHONY: local-release
local-release:
curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --snapshot --config deploy/.goreleaser.local.yml
curl -sL https://git.io/goreleaser | bash -s -- --rm-dist --snapshot --config deploy/.goreleaser.yaml
docker tag replicated/troubleshoot:alpha localhost:32000/troubleshoot:alpha
docker tag replicated/preflight:alpha localhost:32000/preflight:alpha
docker tag replicated/troubleshoot-manager:alpha localhost:32000/troubleshoot-manager:alpha
docker push localhost:32000/troubleshoot:alpha
docker push localhost:32000/preflight:alpha
docker push localhost:32000/troubleshoot-manager:alpha
.PHONY: run-preflight
run-preflight: preflight
./bin/preflight \
--image=localhost:32000/troubleshoot:alpha \
--pullpolicy=Always \
./examples/preflight/sample-preflight.yaml
./bin/preflight ./examples/preflight/sample-preflight.yaml
.PHONY: run-troubleshoot
run-troubleshoot: support-bundle
./bin/support-bundle \
--image=localhost:32000/troubleshoot:alpha \
--pullpolicy=Always \
./examples/troubleshoot/sample-troubleshoot.yaml
./bin/support-bundle ./examples/support-bundle/sample-supportbundle.yaml
.PHONY: run-analyze
run-analyze: analyze
./bin/analyze --analyzers ./examples/support-bundle/sample-analyzers.yaml ./support-bundle.tar.gz
.PHONY: init-sbom
init-sbom:
mkdir -p sbom/spdx sbom/assets
.PHONY: install-spdx-sbom-generator
install-spdx-sbom-generator: init-sbom
./scripts/initialize-sbom-build.sh
SPDX_GENERATOR=./sbom/spdx-sbom-generator
.PHONY: generate-sbom
generate-sbom: install-spdx-sbom-generator
$(SPDX_GENERATOR) -o ./sbom/spdx
sbom/assets/troubleshoot-sbom.tgz: generate-sbom
tar -czf sbom/assets/troubleshoot-sbom.tgz sbom/spdx/*.spdx
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
+37 -6
View File
@@ -1,23 +1,54 @@
# Replicated Troubleshoot
Replicated Troubleshoot is a CLI tool that provides pre-installation cluster conformance testing and validation (preflight checks) and post-installation troubleshooting and diagnostics (support bundles).
Replicated Troubleshoot is a framework for collecting, redacting, and analyzing highly customizable diagnostic information about a Kubernetes cluster. Troubleshoot specs are created by 3rd-party application developers/maintainers and run by cluster operators in the initial and ongoing operation of those applications.
Troubleshoot provides two CLI tools as kubectl plugins (using [Krew](https://krew.dev)): `kubectl preflight` and `kubectl support-bundle`. Preflight provides pre-installation cluster conformance testing and validation (preflight checks) and support-bundle provides post-installation troubleshooting and diagnostics (support bundles).
## Preflight Checks
Preflight checks are an easy-to-run set of conformance tests that can be written to verify that specific requirements in a cluster are met.
To run a sample preflight check from a sample application, [install the preflight kubectl plugin](https://help.replicated.com/docs/troubleshoot/kubernetes/preflight/executing/) and run:
To run a sample preflight check from a sample application, install the preflight kubectl plugin:
```shell
curl https://krew.sh/preflight | bash
```
and run:
```shell
kubectl preflight https://preflight.replicated.com
```
For a full description of the supported preflight checks, visit the [docs](https://help.replicated.com/docs/troubleshoot/kubernetes/analysis/).
For more details on creating the custom resource files that drive preflight checks, visit [creating preflight checks](https://troubleshoot.sh/docs/preflight/introduction/).
## Support Bundle
A support bundle is an archive that's created in-cluster, by collecting logs, cluster information and executing various commands. After creating a support bundle, the cluster operator will normally deliver it to the application vendor for analysis and remote debugging.
A support bundle is an archive that's created in-cluster, by collecting logs and cluster information, and executing specified commands (including redaction of sensitive information). After creating a support bundle, the cluster operator will normally deliver it to the 3rd-party application vendor for analysis and disconnected debugging. Another Replicated project, [KOTS](https://github.com/replicatedhq/kots), provides k8s apps an in-cluster UI for processing support bundles and viewing analyzers (as well as support bundle collection).
To collect a sample support bundle, [install the troubleshoot kubectl plugin](https://help.replicated.com/docs/troubleshoot/kubernetes/support-bundle/collecting/) and run:
To collect a sample support bundle, install the troubleshoot kubectl plugin:
```shell
kubectl support-bundle https://troubleshoot.replicated.com
curl https://krew.sh/support-bundle | bash
```
and run:
```shell
kubectl support-bundle https://support-bundle.replicated.com
```
For more details on creating the custom resource files that drive support-bundle collection, visit [creating collectors](https://troubleshoot.sh/docs/collect/) and [creating analyzers](https://troubleshoot.sh/docs/analyze/).
# Community
For questions about using Troubleshoot, there's a [Replicated Community](https://help.replicated.com/community) forum, and a [#app-troubleshoot channel in Kubernetes Slack](https://kubernetes.slack.com/channels/app-troubleshoot).
# Software Bill of Materials
A signed SBOM that includes Troubleshoot dependencies is included in each release.
- **troubleshoot-sbom.tgz** contains a software bill of materials for Troubleshoot.
- **troubleshoot-sbom.tgz.sig** is the digital signature for troubleshoot-sbom.tgz
- **key.pub** is the public key from the key pair used to sign troubleshoot-sbom.tgz
The following example illustrates using [cosign](https://github.com/sigstore/cosign) to verify that **troubleshoot-sbom.tgz** has
not been tampered with.
```shell
$ cosign verify-blob -key key.pub -signature troubleshoot-sbom.tgz.sig troubleshoot-sbom.tgz
Verified OK
```
+54
View File
@@ -0,0 +1,54 @@
package cli
import (
"os"
"strings"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "analyze [url]",
Args: cobra.MinimumNArgs(1),
Short: "Analyze a support bundle",
Long: `Run a series of analyzers on a support bundle archive`,
SilenceUsage: true,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
logger.SetQuiet(v.GetBool("quiet"))
return runAnalyzers(v, args[0])
},
}
cobra.OnInitialize(initConfig)
cmd.Flags().String("analyzers", "", "filename or url of the analyzers to use")
viper.BindPFlags(cmd.Flags())
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
k8sutil.AddFlags(cmd.Flags())
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
os.Exit(1)
}
}
func initConfig() {
viper.SetEnvPrefix("TROUBLESHOOT")
viper.AutomaticEnv()
}
+67
View File
@@ -0,0 +1,67 @@
package cli
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/spf13/viper"
)
func runAnalyzers(v *viper.Viper, bundlePath string) error {
specPath := v.GetString("analyzers")
specContent := ""
var err error
if _, err = os.Stat(specPath); err == nil {
b, err := ioutil.ReadFile(specPath)
if err != nil {
return err
}
specContent = string(b)
} else {
if !util.IsURL(specPath) {
return fmt.Errorf("%s is not a URL and was not found (err %s)", specPath, err)
}
req, err := http.NewRequest("GET", specPath, nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Replicated_Analyzer/v1beta1")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
specContent = string(body)
}
analyzeResults, err := analyzer.DownloadAndAnalyze(bundlePath, specContent)
if err != nil {
return errors.Wrap(err, "failed to download and analyze bundle")
}
for _, analyzeResult := range analyzeResults {
if analyzeResult.IsPass {
fmt.Printf("Pass: %s\n %s\n", analyzeResult.Title, analyzeResult.Message)
} else if analyzeResult.IsWarn {
fmt.Printf("Warn: %s\n %s\n", analyzeResult.Title, analyzeResult.Message)
} else if analyzeResult.IsFail {
fmt.Printf("Fail: %s\n %s\n", analyzeResult.Title, analyzeResult.Message)
}
}
return nil
}
+10
View File
@@ -0,0 +1,10 @@
package main
import (
"github.com/replicatedhq/troubleshoot/cmd/analyze/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
func main() {
cli.InitAndExecute()
}
+65
View File
@@ -0,0 +1,65 @@
package cli
import (
"os"
"strings"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "collect [url]",
Args: cobra.MinimumNArgs(1),
Short: "Run a collector",
Long: `Run a collector and output the results.`,
SilenceUsage: true,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
logger.SetQuiet(v.GetBool("quiet"))
return runCollect(v, args[0])
},
}
cobra.OnInitialize(initConfig)
cmd.AddCommand(VersionCmd())
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
cmd.Flags().String("format", "json", "output format, one of json or raw.")
cmd.Flags().String("collector-image", "", "the full name of the collector image to use")
cmd.Flags().String("collector-pull-policy", "", "the pull policy of the collector image")
cmd.Flags().String("selector", "", "selector (label query) to filter remote collection nodes on.")
cmd.Flags().Bool("collect-without-permissions", false, "always generate a support bundle, even if it some require additional permissions")
// hidden in favor of the `insecure-skip-tls-verify` flag
cmd.Flags().Bool("allow-insecure-connections", false, "when set, do not verify TLS certs when retrieving spec and reporting results")
cmd.Flags().MarkHidden("allow-insecure-connections")
viper.BindPFlags(cmd.Flags())
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
k8sutil.AddFlags(cmd.Flags())
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
os.Exit(1)
}
}
func initConfig() {
viper.SetEnvPrefix("TROUBLESHOOT")
viper.AutomaticEnv()
}
+184
View File
@@ -0,0 +1,184 @@
package cli
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"strings"
"time"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/specs"
"github.com/replicatedhq/troubleshoot/pkg/supportbundle"
"github.com/spf13/viper"
"k8s.io/apimachinery/pkg/labels"
)
const (
defaultTimeout = 30 * time.Second
)
func runCollect(v *viper.Viper, arg string) error {
go func() {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
<-signalChan
os.Exit(0)
}()
var collectorContent []byte
var err error
if strings.HasPrefix(arg, "secret/") {
// format secret/namespace-name/secret-name
pathParts := strings.Split(arg, "/")
if len(pathParts) != 3 {
return errors.Errorf("path %s must have 3 components", arg)
}
spec, err := specs.LoadFromSecret(pathParts[1], pathParts[2], "collect-spec")
if err != nil {
return errors.Wrap(err, "failed to get spec from secret")
}
collectorContent = spec
} else if _, err = os.Stat(arg); err == nil {
b, err := ioutil.ReadFile(arg)
if err != nil {
return err
}
collectorContent = b
} else {
if !util.IsURL(arg) {
return fmt.Errorf("%s is not a URL and was not found (err %s)", arg, err)
}
req, err := http.NewRequest("GET", arg, nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Replicated_Collect/v1beta2")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
collectorContent = body
}
collectorContent, err = docrewrite.ConvertToV1Beta2(collectorContent)
if err != nil {
return errors.Wrap(err, "failed to convert to v1beta2")
}
multidocs := strings.Split(string(collectorContent), "\n---\n")
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
additionalRedactors := &troubleshootv1beta2.Redactor{}
for idx, redactor := range v.GetStringSlice("redactors") {
redactorObj, err := supportbundle.GetRedactorFromURI(redactor)
if err != nil {
return errors.Wrapf(err, "failed to get redactor spec %s, #%d", redactor, idx)
}
if redactorObj != nil {
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorObj.Spec.Redactors...)
}
}
for i, additionalDoc := range multidocs {
if i == 0 {
continue
}
additionalDoc, err := docrewrite.ConvertToV1Beta2([]byte(additionalDoc))
if err != nil {
return errors.Wrap(err, "failed to convert to v1beta2")
}
obj, _, err := decode(additionalDoc, nil, nil)
if err != nil {
return errors.Wrapf(err, "failed to parse additional doc %d", i)
}
multidocRedactors, ok := obj.(*troubleshootv1beta2.Redactor)
if !ok {
continue
}
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, multidocRedactors.Spec.Redactors...)
}
// make sure we don't block any senders
progressCh := make(chan interface{})
defer close(progressCh)
go func() {
for range progressCh {
}
}()
restConfig, err := k8sutil.GetRESTConfig()
if err != nil {
return errors.Wrap(err, "failed to convert kube flags to rest config")
}
labelSelector, err := labels.Parse(v.GetString("selector"))
if err != nil {
return errors.Wrap(err, "unable to parse selector")
}
namespace := v.GetString("namespace")
if namespace == "" {
namespace = "default"
}
timeout := v.GetDuration("request-timeout")
if timeout == 0 {
timeout = defaultTimeout
}
createOpts := collect.CollectorRunOpts{
CollectWithoutPermissions: v.GetBool("collect-without-permissions"),
KubernetesRestConfig: restConfig,
Image: v.GetString("collector-image"),
PullPolicy: v.GetString("collector-pullpolicy"),
LabelSelector: labelSelector.String(),
Namespace: namespace,
Timeout: timeout,
ProgressChan: progressCh,
}
// we only support HostCollector or RemoteCollector kinds.
hostCollector, err := collect.ParseHostCollectorFromDoc([]byte(multidocs[0]))
if err == nil {
results, err := collect.CollectHost(hostCollector, additionalRedactors, createOpts)
if err != nil {
return errors.Wrap(err, "failed to collect from host")
}
return showHostStdoutResults(v.GetString("format"), hostCollector.Name, results)
}
remoteCollector, err := collect.ParseRemoteCollectorFromDoc([]byte(multidocs[0]))
if err == nil {
results, err := collect.CollectRemote(remoteCollector, additionalRedactors, createOpts)
if err != nil {
return errors.Wrap(err, "failed to collect from remote host(s)")
}
return showRemoteStdoutResults(v.GetString("format"), remoteCollector.Name, results)
}
return errors.New("failed to parse hostCollector or remoteCollector")
}
+103
View File
@@ -0,0 +1,103 @@
package cli
import (
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/pkg/collect"
)
const (
// FormatJSON is intended for CLI output.
FormatJSON = "json"
// FormatRaw is intended for consumption by a remote collector. Output is a
// string of quoted JSON.
FormatRaw = "raw"
)
func showHostStdoutResults(format string, collectName string, results *collect.HostCollectResult) error {
switch format {
case FormatJSON:
return showHostStdoutResultsJSON(collectName, results.AllCollectedData)
case FormatRaw:
return showHostStdoutResultsRaw(collectName, results.AllCollectedData)
default:
return errors.Errorf("unknown output format: %q", format)
}
}
func showRemoteStdoutResults(format string, collectName string, results *collect.RemoteCollectResult) error {
switch format {
case FormatJSON:
return showRemoteStdoutResultsJSON(collectName, results.AllCollectedData)
case FormatRaw:
return errors.Errorf("raw format not supported for remote collectors")
default:
return errors.Errorf("unknown output format: %q", format)
}
}
func showHostStdoutResultsJSON(collectName string, results map[string][]byte) error {
output := make(map[string]interface{})
for file, collectorResult := range results {
var collectedItems map[string]interface{}
if err := json.Unmarshal([]byte(collectorResult), &collectedItems); err != nil {
return errors.Wrap(err, "failed to marshal collector results")
}
output[file] = collectedItems
}
formatted, err := json.MarshalIndent(output, "", " ")
if err != nil {
return errors.Wrap(err, "failed to convert output to json")
}
fmt.Print(string(formatted))
return nil
}
// showHostStdoutResultsRaw outputs the collector output as a string of quoted json.
func showHostStdoutResultsRaw(collectName string, results map[string][]byte) error {
strData := map[string]string{}
for k, v := range results {
strData[k] = string(v)
}
formatted, err := json.MarshalIndent(strData, "", " ")
if err != nil {
return errors.Wrap(err, "failed to convert output to json")
}
fmt.Print(string(formatted))
return nil
}
func showRemoteStdoutResultsJSON(collectName string, results map[string][]byte) error {
type CollectorResult map[string]interface{}
type NodeResult map[string]CollectorResult
var output = make(map[string]NodeResult)
for node, result := range results {
var nodeResult map[string]string
if err := json.Unmarshal(result, &nodeResult); err != nil {
return errors.Wrap(err, "failed to marshal node results")
}
nr := make(NodeResult)
for file, collectorResult := range nodeResult {
var collectedItems map[string]interface{}
if err := json.Unmarshal([]byte(collectorResult), &collectedItems); err != nil {
return errors.Wrap(err, "failed to marshal collector results")
}
nr[file] = collectedItems
}
output[node] = nr
}
formatted, err := json.MarshalIndent(output, "", " ")
if err != nil {
return errors.Wrap(err, "failed to convert output to json")
}
fmt.Print(string(formatted))
return nil
}
+22
View File
@@ -0,0 +1,22 @@
package cli
import (
"fmt"
"github.com/replicatedhq/troubleshoot/pkg/version"
"github.com/spf13/cobra"
)
func VersionCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Print the current version and exit",
Long: `Print the current version and exit`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Printf("Replicated Collect %s\n", version.Version())
return nil
},
}
return cmd
}
+10
View File
@@ -0,0 +1,10 @@
package main
import (
"github.com/replicatedhq/troubleshoot/cmd/collect/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
func main() {
cli.InitAndExecute()
}
-39
View File
@@ -1,39 +0,0 @@
package cli
import (
"fmt"
"os"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "collector",
Short: "Run the cluster-side server for bundle collection",
Long: ``,
SilenceUsage: true,
}
cobra.OnInitialize(initConfig)
cmd.AddCommand(Run())
cmd.AddCommand(Server())
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
func initConfig() {
viper.SetEnvPrefix("TROUBLESHOOT")
viper.AutomaticEnv()
}
-57
View File
@@ -1,57 +0,0 @@
package cli
import (
"fmt"
"io/ioutil"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func Run() *cobra.Command {
cmd := &cobra.Command{
Use: "run",
Short: "run a single collector",
Long: `...`,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("collector", cmd.Flags().Lookup("collector"))
viper.BindPFlag("redact", cmd.Flags().Lookup("redact"))
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
specContents, err := ioutil.ReadFile(v.GetString("collector"))
if err != nil {
return err
}
c, err := collect.ParseSpec(string(specContents))
if err != nil {
return err
}
collector := collect.Collector{
Collect: c,
Redact: v.GetBool("redact"),
}
b, err := collector.RunCollectorSync()
if err != nil {
return err
}
fmt.Printf("%s", b)
return nil
},
}
cmd.Flags().String("collector", "", "path to a single collector spec to collect")
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
cmd.MarkFlagRequired("collector")
viper.BindPFlags(cmd.Flags())
return cmd
}
-43
View File
@@ -1,43 +0,0 @@
package cli
import (
"context"
"fmt"
"os"
"os/signal"
"github.com/replicatedhq/troubleshoot/pkg/server"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func Server() *cobra.Command {
cmd := &cobra.Command{
Use: "server",
Short: "run the http server",
Hidden: true,
Long: `...`,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("port", cmd.Flags().Lookup("port"))
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
server.ServeCollector(context.Background(), fmt.Sprintf(":%d", v.GetInt("port")))
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
select {
case <-c:
return nil
}
},
}
cmd.Flags().Int("port", 8000, "port to listen on")
viper.BindPFlags(cmd.Flags())
return cmd
}
-7
View File
@@ -1,7 +0,0 @@
package main
import "github.com/replicatedhq/troubleshoot/cmd/collector/cli"
func main() {
cli.InitAndExecute()
}
-84
View File
@@ -1,84 +0,0 @@
/*
Copyright 2019 Replicated, Inc..
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main
import (
"flag"
"os"
"github.com/replicatedhq/troubleshoot/pkg/apis"
"github.com/replicatedhq/troubleshoot/pkg/controller"
"github.com/replicatedhq/troubleshoot/pkg/webhook"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
)
func main() {
var metricsAddr string
flag.StringVar(&metricsAddr, "metrics-addr", ":8088", "The address the metric endpoint binds to.")
flag.Parse()
logf.SetLogger(logf.ZapLogger(false))
log := logf.Log.WithName("entrypoint")
// Get a config to talk to the apiserver
log.Info("setting up client for manager")
cfg, err := config.GetConfig()
if err != nil {
log.Error(err, "unable to set up client config")
os.Exit(1)
}
// Create a new Cmd to provide shared dependencies and start components
log.Info("setting up manager")
mgr, err := manager.New(cfg, manager.Options{MetricsBindAddress: metricsAddr})
if err != nil {
log.Error(err, "unable to set up overall controller manager")
os.Exit(1)
}
log.Info("Registering Components.")
// Setup Scheme for all resources
log.Info("setting up scheme")
if err := apis.AddToScheme(mgr.GetScheme()); err != nil {
log.Error(err, "unable add APIs to scheme")
os.Exit(1)
}
// Setup all Controllers
log.Info("Setting up controller")
if err := controller.AddToManager(mgr); err != nil {
log.Error(err, "unable to register controllers to the manager")
os.Exit(1)
}
log.Info("setting up webhooks")
if err := webhook.AddToManager(mgr); err != nil {
log.Error(err, "unable to register webhooks to the manager")
os.Exit(1)
}
// Start the Cmd
log.Info("Starting the Cmd.")
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
log.Error(err, "unable to run the manager")
os.Exit(1)
}
}
+34 -27
View File
@@ -4,22 +4,23 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"strings"
"time"
ui "github.com/gizak/termui/v3"
"github.com/gizak/termui/v3/widgets"
"github.com/pkg/errors"
ui "github.com/replicatedhq/termui/v3"
"github.com/replicatedhq/termui/v3/widgets"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/convert"
)
var (
selectedResult = 0
table = widgets.NewTable()
isShowingSaved = false
)
func showInteractiveResults(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
func showInteractiveResults(preflightName string, outputPath string, analyzeResults []*analyzerunner.AnalyzeResult) error {
if err := ui.Init(); err != nil {
return errors.Wrap(err, "failed to create terminal ui")
}
@@ -43,7 +44,7 @@ func showInteractiveResults(preflightName string, analyzeResults []*analyzerunne
return nil
}
case "s":
filename, err := save(preflightName, analyzeResults)
filename, err := save(preflightName, outputPath, analyzeResults)
if err != nil {
// show
} else {
@@ -63,7 +64,9 @@ func showInteractiveResults(preflightName string, analyzeResults []*analyzerunne
selectedResult++
} else {
selectedResult = 0
table.SelectedRow = 0
}
table.ScrollDown()
ui.Clear()
drawUI(preflightName, analyzeResults)
case "<Up>":
@@ -71,7 +74,9 @@ func showInteractiveResults(preflightName string, analyzeResults []*analyzerunne
selectedResult--
} else {
selectedResult = len(analyzeResults) - 1
table.SelectedRow = len(analyzeResults)
}
table.ScrollUp()
ui.Clear()
drawUI(preflightName, analyzeResults)
}
@@ -94,7 +99,7 @@ func drawHeader(preflightName string) {
termWidth, _ := ui.TerminalDimensions()
title := widgets.NewParagraph()
title.Text = fmt.Sprintf("%s Preflight Checks", appName(preflightName))
title.Text = fmt.Sprintf("%s Preflight Checks", util.AppName(preflightName))
title.TextStyle.Fg = ui.ColorWhite
title.TextStyle.Bg = ui.ColorClear
title.TextStyle.Modifier = ui.ModifierBold
@@ -126,7 +131,6 @@ func drawFooter() {
func drawPreflightTable(analyzeResults []*analyzerunner.AnalyzeResult) {
termWidth, termHeight := ui.TerminalDimensions()
table := widgets.NewTable()
table.SetRect(0, 3, termWidth/2, termHeight-6)
table.FillRow = true
table.Border = true
@@ -135,6 +139,9 @@ func drawPreflightTable(analyzeResults []*analyzerunner.AnalyzeResult) {
for i, analyzeResult := range analyzeResults {
title := analyzeResult.Title
if analyzeResult.Strict {
title = title + fmt.Sprintf(" (Strict: %t)", analyzeResult.Strict)
}
if analyzeResult.IsPass {
title = fmt.Sprintf("✔ %s", title)
} else if analyzeResult.IsWarn {
@@ -213,14 +220,26 @@ func estimateNumberOfLines(text string, width int) int {
return lines
}
func save(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) (string, error) {
filename := path.Join(homeDir(), fmt.Sprintf("%s-results.txt", preflightName))
func save(preflightName string, outputPath string, analyzeResults []*analyzerunner.AnalyzeResult) (string, error) {
filename := ""
if outputPath != "" {
// use override output path
overridePath, err := convert.ValidateOutputPath(outputPath)
if err != nil {
return "", errors.Wrap(err, "override output file path")
}
filename = overridePath
} else {
// use default output path
filename = fmt.Sprintf("%s-results-%s.txt", preflightName, time.Now().Format("2006-01-02T15_04_05"))
}
_, err := os.Stat(filename)
if err == nil {
os.Remove(filename)
}
results := fmt.Sprintf("%s Preflight Checks\n\n", appName(preflightName))
results := fmt.Sprintf("%s Preflight Checks\n\n", util.AppName(preflightName))
for _, analyzeResult := range analyzeResults {
result := ""
@@ -239,6 +258,10 @@ func save(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) (
result = result + fmt.Sprintf("URI: %s\n", analyzeResult.URI)
}
if analyzeResult.Strict {
result = result + fmt.Sprintf("Strict: %t\n", analyzeResult.Strict)
}
result = result + "\n------------\n"
results = results + result
@@ -269,19 +292,3 @@ func showSaved(filename string) {
isShowingSaved = true
}
func appName(preflightName string) string {
words := strings.Split(strings.Title(strings.Replace(preflightName, "-", " ", -1)), " ")
casedWords := []string{}
for i, word := range words {
if strings.ToLower(word) == "ai" {
casedWords = append(casedWords, "AI")
} else if strings.ToLower(word) == "io" && i > 0 {
casedWords[i-1] += ".io"
} else {
casedWords = append(casedWords, word)
}
}
return strings.Join(casedWords, " ")
}
-68
View File
@@ -1,68 +0,0 @@
package cli
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/replicatedhq/troubleshoot/pkg/logger"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func receivePreflightResults(preflightJobNamespace string, preflightJobName string) error {
// poll until there are no more "running" collectors
troubleshootClient, err := createTroubleshootK8sClient()
if err != nil {
return err
}
bundlePath, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
return err
}
defer os.RemoveAll(bundlePath)
receivedPreflights := []string{}
for {
job, err := troubleshootClient.PreflightJobs(preflightJobNamespace).Get(preflightJobName, metav1.GetOptions{})
if err != nil && kuberneteserrors.IsNotFound(err) {
// where did it go!
return nil
} else if err != nil {
return err
}
for _, readyPreflight := range job.Status.AnalyzersSuccessful {
alreadyReceived := false
for _, receivedPreflight := range receivedPreflights {
if receivedPreflight == readyPreflight {
alreadyReceived = true
}
}
if alreadyReceived {
continue
}
preflightResp, err := http.Get(fmt.Sprintf("http://localhost:8000/preflight/%s", readyPreflight))
if err != nil {
return err
}
defer preflightResp.Body.Close()
body, err := ioutil.ReadAll(preflightResp.Body)
if err != nil {
return err
}
logger.Printf("%s\n", body)
receivedPreflights = append(receivedPreflights, readyPreflight)
}
if len(job.Status.AnalyzersRunning) == 0 {
return nil
}
}
}
+14 -33
View File
@@ -1,12 +1,10 @@
package cli
import (
"fmt"
"os"
"path/filepath"
"strings"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
@@ -14,47 +12,43 @@ import (
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "preflight [url]",
Args: cobra.MinimumNArgs(1),
Short: "Run and retrieve preflight checks in a cluster",
Long: `A preflight check is a set of validations that can and should be run to ensure
that a cluster meets the requirements to run an application.`,
SilenceUsage: true,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
if len(args) == 0 {
return runPreflightsCRD(v)
}
return runPreflightsNoCRD(v, args[0])
return runPreflights(v, args[0])
},
}
cobra.OnInitialize(initConfig)
cmd.AddCommand(VersionCmd())
cmd.Flags().Bool("interactive", true, "interactive preflights")
cmd.Flags().String("format", "human", "output format, one of human, json, yaml. only used when interactive is set to false")
cmd.Flags().String("preflight", "", "name of the preflight to use")
cmd.Flags().String("namespace", "default", "namespace the preflight can be found in")
cmd.Flags().String("kubecontext", filepath.Join(homeDir(), ".kube", "config"), "the kubecontext to use when connecting")
cmd.Flags().String("image", "", "the full name of the preflight image to use")
cmd.Flags().String("pullpolicy", "", "the pull policy of the preflight image")
cmd.Flags().String("collector-image", "", "the full name of the collector image to use")
cmd.Flags().String("collector-pullpolicy", "", "the pull policy of the collector image")
cmd.Flags().String("serviceaccount", "", "name of the service account to use. if not provided, one will be created")
cmd.Flags().Bool("collect-without-permissions", true, "always run preflight checks even if some require permissions that preflight does not have")
cmd.Flags().String("selector", "", "selector (label query) to filter remote collection nodes on.")
cmd.Flags().String("since-time", "", "force pod logs collectors to return logs after a specific date (RFC3339)")
cmd.Flags().String("since", "", "force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.")
cmd.Flags().StringP("output", "o", "", "specify the output file path for the preflight checks")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
k8sutil.AddFlags(cmd.Flags())
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
@@ -63,16 +57,3 @@ func initConfig() {
viper.SetEnvPrefix("PREFLIGHT")
viper.AutomaticEnv()
}
func ensureCollectorInList(list []*troubleshootv1beta1.Collect, collector troubleshootv1beta1.Collect) []*troubleshootv1beta1.Collect {
for _, inList := range list {
if collector.ClusterResources != nil && inList.ClusterResources != nil {
return list
}
if collector.ClusterInfo != nil && inList.ClusterInfo != nil {
return list
}
}
return append(list, &collector)
}
+353
View File
@@ -0,0 +1,353 @@
package cli
import (
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/signal"
"strings"
"time"
cursor "github.com/ahmetalpbalkan/go-cursor"
"github.com/fatih/color"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/preflight"
"github.com/replicatedhq/troubleshoot/pkg/specs"
"github.com/spf13/viper"
spin "github.com/tj/go-spin"
"golang.org/x/sync/errgroup"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes/scheme"
)
func runPreflights(v *viper.Viper, arg string) error {
if v.GetBool("interactive") {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
}
go func() {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
<-signalChan
os.Exit(0)
}()
var preflightContent []byte
var err error
if strings.HasPrefix(arg, "secret/") {
// format secret/namespace-name/secret-name
pathParts := strings.Split(arg, "/")
if len(pathParts) != 3 {
return errors.Errorf("path %s must have 3 components", arg)
}
spec, err := specs.LoadFromSecret(pathParts[1], pathParts[2], "preflight-spec")
if err != nil {
return errors.Wrap(err, "failed to get spec from secret")
}
preflightContent = spec
} else if _, err = os.Stat(arg); err == nil {
b, err := ioutil.ReadFile(arg)
if err != nil {
return err
}
preflightContent = b
} else {
if !util.IsURL(arg) {
return fmt.Errorf("%s is not a URL and was not found (err %s)", arg, err)
}
req, err := http.NewRequest("GET", arg, nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Replicated_Preflight/v1beta2")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
preflightContent = body
}
preflightContent, err = docrewrite.ConvertToV1Beta2(preflightContent)
if err != nil {
return errors.Wrap(err, "failed to convert to v1beta2")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode([]byte(preflightContent), nil, nil)
if err != nil {
return errors.Wrapf(err, "failed to parse %s", arg)
}
var collectResults []preflight.CollectResult
preflightSpecName := ""
progressCh := make(chan interface{})
defer close(progressCh)
ctx, stopProgressCollection := context.WithCancel(context.Background())
// make sure we shut down progress collection goroutines if an error occurs
defer stopProgressCollection()
progressCollection, ctx := errgroup.WithContext(ctx)
if v.GetBool("interactive") {
progressCollection.Go(collectInteractiveProgress(ctx, progressCh))
} else {
progressCollection.Go(collectNonInteractiveProgess(ctx, progressCh))
}
if preflightSpec, ok := obj.(*troubleshootv1beta2.Preflight); ok {
r, err := collectInCluster(preflightSpec, progressCh)
if err != nil {
return errors.Wrap(err, "failed to collect in cluster")
}
collectResults = append(collectResults, *r)
preflightSpecName = preflightSpec.Name
} else if hostPreflightSpec, ok := obj.(*troubleshootv1beta2.HostPreflight); ok {
if len(hostPreflightSpec.Spec.Collectors) > 0 {
r, err := collectHost(hostPreflightSpec, progressCh)
if err != nil {
return errors.Wrap(err, "failed to collect from host")
}
collectResults = append(collectResults, *r)
}
if len(hostPreflightSpec.Spec.RemoteCollectors) > 0 {
r, err := collectRemote(hostPreflightSpec, progressCh)
if err != nil {
return errors.Wrap(err, "failed to collect remotely")
}
collectResults = append(collectResults, *r)
}
preflightSpecName = hostPreflightSpec.Name
}
if collectResults == nil {
return errors.New("no results")
}
analyzeResults := []*analyzer.AnalyzeResult{}
for _, res := range collectResults {
analyzeResults = append(analyzeResults, res.Analyze()...)
}
if preflightSpec, ok := obj.(*troubleshootv1beta2.Preflight); ok {
if preflightSpec.Spec.UploadResultsTo != "" {
err := uploadResults(preflightSpec.Spec.UploadResultsTo, analyzeResults)
if err != nil {
progressCh <- err
}
}
}
stopProgressCollection()
progressCollection.Wait()
if v.GetBool("interactive") {
if len(analyzeResults) == 0 {
return errors.New("no data has been collected")
}
return showInteractiveResults(preflightSpecName, v.GetString("output"), analyzeResults)
}
return showStdoutResults(v.GetString("format"), preflightSpecName, analyzeResults)
}
func collectInteractiveProgress(ctx context.Context, progressCh <-chan interface{}) func() error {
return func() error {
spinner := spin.New()
lastMsg := ""
errorTxt := color.New(color.FgHiRed)
infoTxt := color.New(color.FgCyan)
for {
select {
case msg := <-progressCh:
switch msg := msg.(type) {
case error:
errorTxt.Printf("%s\r * %v\n", cursor.ClearEntireLine(), msg)
case string:
if lastMsg == msg {
break
}
lastMsg = msg
infoTxt.Printf("%s\r * %s\n", cursor.ClearEntireLine(), msg)
}
case <-time.After(time.Millisecond * 100):
fmt.Printf("\r %s %s ", color.CyanString("Running Preflight Checks"), spinner.Next())
case <-ctx.Done():
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
return nil
}
}
}
}
func collectNonInteractiveProgess(ctx context.Context, progressCh <-chan interface{}) func() error {
return func() error {
for {
select {
case msg := <-progressCh:
switch msg := msg.(type) {
case error:
fmt.Fprintf(os.Stderr, "error - %v\n", msg)
case string:
fmt.Fprintf(os.Stderr, "%s\n", msg)
case preflight.CollectProgress:
fmt.Fprintf(os.Stderr, "%s\n", msg.String())
}
case <-ctx.Done():
return nil
}
}
}
}
func collectInCluster(preflightSpec *troubleshootv1beta2.Preflight, progressCh chan interface{}) (*preflight.CollectResult, error) {
v := viper.GetViper()
restConfig, err := k8sutil.GetRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to convert kube flags to rest config")
}
collectOpts := preflight.CollectOpts{
Namespace: v.GetString("namespace"),
IgnorePermissionErrors: v.GetBool("collect-without-permissions"),
ProgressChan: progressCh,
KubernetesRestConfig: restConfig,
}
if v.GetString("since") != "" || v.GetString("since-time") != "" {
err := parseTimeFlags(v, preflightSpec.Spec.Collectors)
if err != nil {
return nil, err
}
}
collectResults, err := preflight.Collect(collectOpts, preflightSpec)
if err != nil {
if !collectResults.IsRBACAllowed() {
if preflightSpec.Spec.UploadResultsTo != "" {
clusterCollectResults := collectResults.(preflight.ClusterCollectResult)
err := uploadErrors(preflightSpec.Spec.UploadResultsTo, clusterCollectResults.Collectors)
if err != nil {
progressCh <- err
}
}
}
return nil, err
}
return &collectResults, nil
}
func collectRemote(preflightSpec *troubleshootv1beta2.HostPreflight, progressCh chan interface{}) (*preflight.CollectResult, error) {
v := viper.GetViper()
restConfig, err := k8sutil.GetRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to convert kube flags to rest config")
}
labelSelector, err := labels.Parse(v.GetString("selector"))
if err != nil {
return nil, errors.Wrap(err, "unable to parse selector")
}
namespace := v.GetString("namespace")
if namespace == "" {
namespace = "default"
}
timeout := v.GetDuration("request-timeout")
if timeout == 0 {
timeout = 30 * time.Second
}
collectOpts := preflight.CollectOpts{
Namespace: namespace,
IgnorePermissionErrors: v.GetBool("collect-without-permissions"),
ProgressChan: progressCh,
KubernetesRestConfig: restConfig,
Image: v.GetString("collector-image"),
PullPolicy: v.GetString("collector-pullpolicy"),
LabelSelector: labelSelector.String(),
Timeout: timeout,
}
collectResults, err := preflight.CollectRemote(collectOpts, preflightSpec)
if err != nil {
return nil, errors.Wrap(err, "failed to collect from remote")
}
return &collectResults, nil
}
func collectHost(hostPreflightSpec *troubleshootv1beta2.HostPreflight, progressCh chan interface{}) (*preflight.CollectResult, error) {
collectOpts := preflight.CollectOpts{
ProgressChan: progressCh,
}
collectResults, err := preflight.CollectHost(collectOpts, hostPreflightSpec)
if err != nil {
return nil, errors.Wrap(err, "failed to collect from host")
}
return &collectResults, nil
}
func parseTimeFlags(v *viper.Viper, collectors []*troubleshootv1beta2.Collect) error {
var (
sinceTime time.Time
err error
)
if v.GetString("since-time") != "" {
if v.GetString("since") != "" {
return errors.Errorf("at most one of `sinceTime` or `since` may be specified")
}
sinceTime, err = time.Parse(time.RFC3339, v.GetString("since-time"))
if err != nil {
return errors.Wrap(err, "unable to parse --since-time flag")
}
} else {
parsedDuration, err := time.ParseDuration(v.GetString("since"))
if err != nil {
return errors.Wrap(err, "unable to parse --since flag")
}
now := time.Now()
sinceTime = now.Add(0 - parsedDuration)
}
for _, collector := range collectors {
if collector.Logs != nil {
if collector.Logs.Limits == nil {
collector.Logs.Limits = new(troubleshootv1beta2.LogLimits)
}
collector.Logs.Limits.SinceTime = metav1.NewTime(sinceTime)
}
}
return nil
}
-103
View File
@@ -1,103 +0,0 @@
package cli
import (
"errors"
"fmt"
"time"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/spf13/viper"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func runPreflightsCRD(v *viper.Viper) error {
troubleshootClient, err := createTroubleshootK8sClient()
if err != nil {
return err
}
preflightName := v.GetString("preflight")
if preflightName == "" {
preflights, err := troubleshootClient.Preflights(v.GetString("namespace")).List(metav1.ListOptions{})
if err != nil {
return err
}
if len(preflights.Items) == 1 {
preflightName = preflights.Items[0].Name
}
}
if preflightName == "" {
return errors.New("unable to preflight, try using the --preflight flags")
}
// generate a unique name
now := time.Now()
suffix := fmt.Sprintf("%d", now.Unix())
preflightJobName := fmt.Sprintf("%s-job-%s", preflightName, suffix[len(suffix)-4:])
preflightJob := troubleshootv1beta1.PreflightJob{
ObjectMeta: metav1.ObjectMeta{
Name: preflightJobName,
Namespace: v.GetString("namespace"),
},
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "preflightjob.troubleshoot.replicated.com",
},
Spec: troubleshootv1beta1.PreflightJobSpec{
Preflight: troubleshootv1beta1.PreflightRef{
Name: preflightName,
Namespace: v.GetString("namespace"),
},
Image: v.GetString("image"),
ImagePullPolicy: v.GetString("pullpolicy"),
CollectorImage: v.GetString("collector-image"),
CollectorImagePullPolicy: v.GetString("collector-pullpolicy"),
},
}
if _, err := troubleshootClient.PreflightJobs(v.GetString("namespace")).Create(&preflightJob); err != nil {
return err
}
// Poll the status of the Custom Resource for it to include a callback
var found *troubleshootv1beta1.PreflightJob
start := time.Now()
for {
current, err := troubleshootClient.PreflightJobs(v.GetString("namespace")).Get(preflightJobName, metav1.GetOptions{})
if err != nil && kuberneteserrors.IsNotFound(err) {
continue
} else if err != nil {
return err
}
if current.Status.IsServerReady {
found = current
break
}
if time.Now().Sub(start) > time.Duration(time.Second*10) {
return errors.New("preflightjob failed to start")
}
time.Sleep(time.Millisecond * 200)
}
// Connect to the callback
stopChan, err := k8sutil.PortForward(v.GetString("kubecontext"), 8000, 8000, found.Status.ServerPodNamespace, found.Status.ServerPodName)
if err != nil {
return err
}
if err := receivePreflightResults(found.Namespace, found.Name); err != nil {
return err
}
// Write
close(stopChan)
return nil
}
-195
View File
@@ -1,195 +0,0 @@
package cli
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strings"
"time"
"github.com/ahmetalpbalkan/go-cursor"
"github.com/pkg/errors"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/viper"
"github.com/tj/go-spin"
"gopkg.in/yaml.v2"
)
func runPreflightsNoCRD(v *viper.Viper, arg string) error {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
preflightContent := ""
if !isURL(arg) {
if _, err := os.Stat(arg); os.IsNotExist(err) {
return fmt.Errorf("%s was not found", arg)
}
b, err := ioutil.ReadFile(arg)
if err != nil {
return err
}
preflightContent = string(b)
} else {
req, err := http.NewRequest("GET", arg, nil)
if err != nil {
return err
}
req.Header.Set("User-Agent", "Replicated_Preflight/v1beta1")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return err
}
preflightContent = string(body)
}
preflight := troubleshootv1beta1.Preflight{}
if err := yaml.Unmarshal([]byte(preflightContent), &preflight); err != nil {
return fmt.Errorf("unable to parse %s as a preflight", arg)
}
s := spin.New()
finishedCh := make(chan bool, 1)
go func() {
for {
select {
case <-finishedCh:
fmt.Printf("\r")
return
case <-time.After(time.Millisecond * 100):
fmt.Printf("\r \033[36mRunning Preflight checks\033[m %s ", s.Next())
}
}
}()
defer func() {
finishedCh <- true
}()
allCollectedData, err := runCollectors(v, preflight)
if err != nil {
return err
}
getCollectedFileContents := func(fileName string) ([]byte, error) {
contents, ok := allCollectedData[fileName]
if !ok {
return nil, fmt.Errorf("file %s was not collected", fileName)
}
return contents, nil
}
getChildCollectedFileContents := func(prefix string) (map[string][]byte, error) {
matching := make(map[string][]byte)
for k, v := range allCollectedData {
if strings.HasPrefix(k, prefix) {
matching[k] = v
}
}
return matching, nil
}
analyzeResults := []*analyzerunner.AnalyzeResult{}
for _, analyzer := range preflight.Spec.Analyzers {
analyzeResult, err := analyzerunner.Analyze(analyzer, getCollectedFileContents, getChildCollectedFileContents)
if err != nil {
logger.Printf("an analyzer failed to run: %v\n", err)
continue
}
analyzeResults = append(analyzeResults, analyzeResult)
}
finishedCh <- true
if preflight.Spec.UploadResultsTo != "" {
tryUploadResults(preflight.Spec.UploadResultsTo, preflight.Name, analyzeResults)
}
if v.GetBool("interactive") {
return showInteractiveResults(preflight.Name, analyzeResults)
}
logger.Printf("only interactive results are supported\n")
return nil
}
func runCollectors(v *viper.Viper, preflight troubleshootv1beta1.Preflight) (map[string][]byte, error) {
desiredCollectors := make([]*troubleshootv1beta1.Collect, 0, 0)
for _, definedCollector := range preflight.Spec.Collectors {
desiredCollectors = append(desiredCollectors, definedCollector)
}
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterInfo: &troubleshootv1beta1.ClusterInfo{}})
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterResources: &troubleshootv1beta1.ClusterResources{}})
allCollectedData := make(map[string][]byte)
// Run preflights collectors synchronously
for _, desiredCollector := range desiredCollectors {
collector := collect.Collector{
Redact: true,
Collect: desiredCollector,
}
result, err := collector.RunCollectorSync()
if err != nil {
return nil, errors.Wrap(err, "failed to run collector")
}
output, err := parseCollectorOutput(string(result))
if err != nil {
return nil, errors.Wrap(err, "failed to parse collector output")
}
for k, v := range output {
allCollectedData[k] = v
}
}
return allCollectedData, nil
}
func parseCollectorOutput(output string) (map[string][]byte, error) {
input := make(map[string]interface{})
files := make(map[string][]byte)
if err := json.Unmarshal([]byte(output), &input); err != nil {
return nil, err
}
for filename, maybeContents := range input {
fileDir, fileName := filepath.Split(filename)
switch maybeContents.(type) {
case string:
decoded, err := base64.StdEncoding.DecodeString(maybeContents.(string))
if err != nil {
return nil, err
}
files[filepath.Join(fileDir, fileName)] = decoded
case map[string]interface{}:
for k, v := range maybeContents.(map[string]interface{}) {
decoded, err := base64.StdEncoding.DecodeString(v.(string))
if err != nil {
return nil, err
}
files[filepath.Join(fileDir, fileName, k)] = decoded
}
}
}
return files, nil
}
-151
View File
@@ -1,151 +0,0 @@
package cli
import (
"fmt"
"github.com/pkg/errors"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
func createServiceAccount(preflight troubleshootv1beta1.Preflight, namespace string, clientset *kubernetes.Clientset) (string, error) {
name := fmt.Sprintf("preflight-%s", preflight.Name)
serviceAccount := corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Secrets: []corev1.ObjectReference{
{
APIVersion: "v1",
Kind: "Secret",
Name: name,
Namespace: namespace,
},
},
}
_, err := clientset.CoreV1().ServiceAccounts(namespace).Get(serviceAccount.Name, metav1.GetOptions{})
if err != nil && !kuberneteserrors.IsNotFound(err) {
return "", errors.Wrap(err, "failed to get existing service account")
}
if kuberneteserrors.IsNotFound(err) {
_, err := clientset.CoreV1().ServiceAccounts(namespace).Create(&serviceAccount)
if err != nil {
return "", errors.Wrap(err, "failed to create service account")
}
}
role := rbacv1.ClusterRole{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ClusterRole",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{
"namespaces",
"pods",
"services",
"secrets",
},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"apps"},
Resources: []string{"deployments"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"extensions"},
Resources: []string{"ingresses"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"storage.k8s.io"},
Resources: []string{"storageclasses"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"apiextensions.k8s.io"},
Resources: []string{"customresourcedefinitions"},
Verbs: metav1.Verbs{"list"},
},
},
}
_, err = clientset.RbacV1().ClusterRoles().Get(role.Name, metav1.GetOptions{})
if err != nil && !kuberneteserrors.IsNotFound(err) {
return "", errors.Wrap(err, "failed to get eisting cluster role")
}
if kuberneteserrors.IsNotFound(err) {
_, err = clientset.RbacV1().ClusterRoles().Create(&role)
if err != nil {
return "", errors.Wrap(err, "failed to create cluster role")
}
}
roleBinding := rbacv1.ClusterRoleBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ClusterRoleBinding",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: name,
Namespace: namespace,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: name,
},
}
_, err = clientset.RbacV1().ClusterRoleBindings().Get(roleBinding.Name, metav1.GetOptions{})
if err != nil && !kuberneteserrors.IsNotFound(err) {
return "", errors.Wrap(err, "failed to get existing cluster role binding")
}
if kuberneteserrors.IsNotFound(err) {
_, err = clientset.RbacV1().ClusterRoleBindings().Create(&roleBinding)
if err != nil {
return "", errors.Wrap(err, "failed to create cluster role binding")
}
}
return name, nil
}
func removeServiceAccount(name string, namespace string, clientset *kubernetes.Clientset) error {
if err := clientset.RbacV1().ClusterRoleBindings().Delete(name, &metav1.DeleteOptions{}); err != nil {
return errors.Wrap(err, "failed to delete cluster role binding")
}
if err := clientset.RbacV1().ClusterRoles().Delete(name, &metav1.DeleteOptions{}); err != nil {
return errors.Wrap(err, "failed to delete cluster role")
}
if err := clientset.CoreV1().ServiceAccounts(namespace).Delete(name, &metav1.DeleteOptions{}); err != nil {
return errors.Wrap(err, "failed to delete service account")
}
return nil
}
+109
View File
@@ -0,0 +1,109 @@
package cli
import (
"encoding/json"
"fmt"
"github.com/pkg/errors"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
)
func showStdoutResults(format string, preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
if format == "human" {
return showStdoutResultsHuman(preflightName, analyzeResults)
} else if format == "json" {
return showStdoutResultsJSON(preflightName, analyzeResults)
}
return errors.Errorf("unknown output format: %q", format)
}
func showStdoutResultsHuman(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
fmt.Println("")
var failed bool
for _, analyzeResult := range analyzeResults {
testResultfailed := outputResult(analyzeResult)
if testResultfailed {
failed = true
}
}
if failed {
fmt.Printf("--- FAIL %s\n", preflightName)
fmt.Println("FAILED")
} else {
fmt.Printf("--- PASS %s\n", preflightName)
fmt.Println("PASS")
}
return nil
}
func showStdoutResultsJSON(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
type ResultOutput struct {
Title string `json:"title"`
Message string `json:"message"`
URI string `json:"uri,omitempty"`
Strict bool `json:"strict,omitempty"`
}
type Output struct {
Pass []ResultOutput `json:"pass,omitempty"`
Warn []ResultOutput `json:"warn,omitempty"`
Fail []ResultOutput `json:"fail,omitempty"`
}
output := Output{
Pass: []ResultOutput{},
Warn: []ResultOutput{},
Fail: []ResultOutput{},
}
for _, analyzeResult := range analyzeResults {
resultOutput := ResultOutput{
Title: analyzeResult.Title,
Message: analyzeResult.Message,
URI: analyzeResult.URI,
}
if analyzeResult.Strict {
resultOutput.Strict = analyzeResult.Strict
}
if analyzeResult.IsPass {
output.Pass = append(output.Pass, resultOutput)
} else if analyzeResult.IsWarn {
output.Warn = append(output.Warn, resultOutput)
} else if analyzeResult.IsFail {
output.Fail = append(output.Fail, resultOutput)
}
}
b, err := json.MarshalIndent(output, "", " ")
if err != nil {
return errors.Wrap(err, "failed to marshal results")
}
fmt.Printf("%s\n", b)
return nil
}
func outputResult(analyzeResult *analyzerunner.AnalyzeResult) bool {
if analyzeResult.IsPass {
fmt.Printf(" --- PASS %s\n", analyzeResult.Title)
fmt.Printf(" --- %s\n", analyzeResult.Message)
} else if analyzeResult.IsWarn {
fmt.Printf(" --- WARN: %s\n", analyzeResult.Title)
fmt.Printf(" --- %s\n", analyzeResult.Message)
} else if analyzeResult.IsFail {
fmt.Printf(" --- FAIL: %s\n", analyzeResult.Title)
fmt.Printf(" --- %s\n", analyzeResult.Message)
}
if analyzeResult.Strict {
fmt.Printf(" --- Strict: %t\n", analyzeResult.Strict)
}
if analyzeResult.IsFail {
return true
}
return false
}
+34 -23
View File
@@ -5,29 +5,19 @@ import (
"encoding/json"
"net/http"
"github.com/pkg/errors"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/replicatedhq/troubleshoot/pkg/preflight"
)
type UploadPreflightResult struct {
IsFail bool `json:"isFail,omitempty"`
IsWarn bool `json:"isWarn,omitempty"`
IsPass bool `json:"isPass,omitempty"`
Title string `json:"title"`
Message string `json:"message"`
URI string `json:"uri,omitempty"`
}
type UploadPreflightResults struct {
Results []*UploadPreflightResult `json:"results"`
}
func tryUploadResults(uri string, preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
uploadPreflightResults := UploadPreflightResults{
Results: []*UploadPreflightResult{},
func uploadResults(uri string, analyzeResults []*analyzerunner.AnalyzeResult) error {
uploadPreflightResults := &preflight.UploadPreflightResults{
Results: []*preflight.UploadPreflightResult{},
}
for _, analyzeResult := range analyzeResults {
uploadPreflightResult := &UploadPreflightResult{
uploadPreflightResult := &preflight.UploadPreflightResult{
Strict: analyzeResult.Strict,
IsFail: analyzeResult.IsFail,
IsWarn: analyzeResult.IsWarn,
IsPass: analyzeResult.IsPass,
@@ -39,14 +29,35 @@ func tryUploadResults(uri string, preflightName string, analyzeResults []*analyz
uploadPreflightResults.Results = append(uploadPreflightResults.Results, uploadPreflightResult)
}
b, err := json.Marshal(uploadPreflightResults)
return upload(uri, uploadPreflightResults)
}
func uploadErrors(uri string, collectors collect.Collectors) error {
errors := []*preflight.UploadPreflightError{}
for _, collector := range collectors {
for _, e := range collector.RBACErrors {
errors = append(errors, &preflight.UploadPreflightError{
Error: e.Error(),
})
}
}
results := &preflight.UploadPreflightResults{
Errors: errors,
}
return upload(uri, results)
}
func upload(uri string, payload *preflight.UploadPreflightResults) error {
b, err := json.Marshal(payload)
if err != nil {
return err
return errors.Wrap(err, "failed to marshal payload")
}
req, err := http.NewRequest("POST", uri, bytes.NewBuffer(b))
if err != nil {
return err
return errors.Wrap(err, "failed to create request")
}
req.Header.Set("Content-Type", "application/json")
@@ -54,11 +65,11 @@ func tryUploadResults(uri string, preflightName string, analyzeResults []*analyz
client := http.DefaultClient
resp, err := client.Do(req)
if err != nil {
return err
return errors.Wrap(err, "failed to execute request")
}
if resp.StatusCode > 290 {
return err
return errors.Errorf("unexpected status code: %d", resp.StatusCode)
}
return nil
-41
View File
@@ -1,41 +0,0 @@
package cli
import (
"net/url"
"os"
troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1"
"github.com/spf13/viper"
"k8s.io/client-go/tools/clientcmd"
)
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}
func isURL(str string) bool {
_, err := url.ParseRequestURI(str)
if err != nil {
return false
}
return true
}
func createTroubleshootK8sClient() (*troubleshootclientv1beta1.TroubleshootV1beta1Client, error) {
v := viper.GetViper()
config, err := clientcmd.BuildConfigFromFlags("", v.GetString("kubecontext"))
if err != nil {
return nil, err
}
troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(config)
if err != nil {
return nil, err
}
return troubleshootClient, nil
}
+23
View File
@@ -0,0 +1,23 @@
package cli
import (
"fmt"
"github.com/spf13/cobra"
"github.com/replicatedhq/troubleshoot/pkg/version"
)
func VersionCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Print the current version and exit",
Long: `Print the current version and exit`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Printf("Replicated Preflight %s\n", version.Version())
return nil
},
}
return cmd
}
+1 -1
View File
@@ -2,7 +2,7 @@ package main
import (
"github.com/replicatedhq/troubleshoot/cmd/preflight/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
func main() {
+174
View File
@@ -0,0 +1,174 @@
package cli
import (
"encoding/json"
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
extensionsscheme "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/scheme"
"k8s.io/client-go/kubernetes/scheme"
)
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "schemagen",
Short: "Generate openapischemas for the kinds in this project",
SilenceUsage: true,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
return generateSchemas(v)
},
}
cobra.OnInitialize(initConfig)
cmd.Flags().String("output-dir", "./schemas", "directory to save the schemas in")
viper.BindPFlags(cmd.Flags())
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
os.Exit(1)
}
}
func initConfig() {
viper.SetEnvPrefix("TROUBLESHOOT")
viper.AutomaticEnv()
}
func generateSchemas(v *viper.Viper) error {
// we generate schemas from the config/crds in the root of this project
// those crds can be created from controller-gen or by running `make openapischema`
workdir, err := os.Getwd()
if err != nil {
return errors.Wrap(err, "failed to get workdir")
}
files := []struct {
inFilename string
outFilename string
}{
{
"troubleshoot.replicated.com_preflights.yaml",
"preflight-troubleshoot-v1beta1.json",
},
{
"troubleshoot.replicated.com_analyzers.yaml",
"analyzer-troubleshoot-v1beta1.json",
},
{
"troubleshoot.replicated.com_collectors.yaml",
"collector-troubleshoot-v1beta1.json",
},
{
"troubleshoot.replicated.com_redactors.yaml",
"redactor-troubleshoot-v1beta1.json",
},
{
"troubleshoot.replicated.com_supportbundles.yaml",
"supportbundle-troubleshoot-v1beta1.json",
},
{
"troubleshoot.sh_analyzers.yaml",
"analyzer-troubleshoot-v1beta2.json",
},
{
"troubleshoot.sh_collectors.yaml",
"collector-troubleshoot-v1beta2.json",
},
{
"troubleshoot.sh_preflights.yaml",
"preflight-troubleshoot-v1beta2.json",
},
{
"troubleshoot.sh_redactors.yaml",
"redactor-troubleshoot-v1beta2.json",
},
{
"troubleshoot.sh_supportbundles.yaml",
"supportbundle-troubleshoot-v1beta2.json",
},
}
for _, file := range files {
contents, err := ioutil.ReadFile(filepath.Join(workdir, "config", "crds", file.inFilename))
if err != nil {
return errors.Wrapf(err, "failed to read crd from %s", file.inFilename)
}
if err := generateSchemaFromCRD(contents, filepath.Join(workdir, v.GetString("output-dir"), file.outFilename)); err != nil {
return errors.Wrapf(err, "failed to write crd schema to %s", file.outFilename)
}
}
return nil
}
func generateSchemaFromCRD(crd []byte, outfile string) error {
extensionsscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
obj, _, err := decode(crd, nil, nil)
if err != nil {
return errors.Wrap(err, "failed to decode crd")
}
customResourceDefinition := obj.(*extensionsv1.CustomResourceDefinition)
if len(customResourceDefinition.Spec.Versions) == 0 {
return errors.New("no versions found for CRD")
}
crdSchema := customResourceDefinition.Spec.Versions[0].Schema
if crdSchema == nil {
return errors.New("CRD has a nil schema")
}
b, err := json.MarshalIndent(crdSchema.OpenAPIV3Schema, "", " ")
if err != nil {
return errors.Wrap(err, "failed to marshal json")
}
_, err = os.Stat(outfile)
if err == nil {
if err := os.Remove(outfile); err != nil {
return errors.Wrap(err, "failed to remove file")
}
}
d, _ := path.Split(outfile)
_, err = os.Stat(d)
if os.IsNotExist(err) {
if err = os.MkdirAll(d, 0755); err != nil {
return errors.Wrap(err, "failed to mkdir")
}
}
// whoa now
// working around the fact that controller-gen doesn't have tags to generate oneOf schemas, so this is hacky.
// going to work to add an issue there to support and if they accept, this terrible thing can go away
boolStringed := strings.ReplaceAll(string(b), `"type": "BoolString"`, `"oneOf": [{"type": "string"},{"type": "boolean"}]`)
err = ioutil.WriteFile(outfile, []byte(boolStringed), 0644)
if err != nil {
return errors.Wrap(err, "failed to write file")
}
return nil
}
+9
View File
@@ -0,0 +1,9 @@
package main
import (
"github.com/replicatedhq/troubleshoot/cmd/schemagen/cli"
)
func main() {
cli.InitAndExecute()
}
+57 -7
View File
@@ -1,10 +1,13 @@
package cli
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/replicatedhq/troubleshoot/pkg/logger"
@@ -15,11 +18,12 @@ import (
func Analyze() *cobra.Command {
cmd := &cobra.Command{
Use: "analyze",
Use: "analyze [url]",
Args: cobra.MinimumNArgs(1),
Short: "analyze a support bundle",
Long: `...`,
Long: `Analyze a support bundle using the Analyzer definitions provided`,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("url", cmd.Flags().Lookup("url"))
viper.BindPFlag("bundle", cmd.Flags().Lookup("bundle"))
viper.BindPFlag("output", cmd.Flags().Lookup("output"))
viper.BindPFlag("quiet", cmd.Flags().Lookup("quiet"))
},
@@ -28,7 +32,13 @@ func Analyze() *cobra.Command {
logger.SetQuiet(v.GetBool("quiet"))
result, err := analyzer.DownloadAndAnalyze(context.TODO(), v.GetString("url"))
specPath := args[0]
analyzerSpec, err := downloadAnalyzerSpec(specPath)
if err != nil {
return err
}
result, err := analyzer.DownloadAndAnalyze(v.GetString("bundle"), analyzerSpec)
if err != nil {
return err
}
@@ -60,8 +70,8 @@ func Analyze() *cobra.Command {
},
}
cmd.Flags().String("url", "", "URL of the support bundle to analyze")
cmd.MarkFlagRequired("url")
cmd.Flags().String("bundle", "", "filename of the support bundle to analyze")
cmd.MarkFlagRequired("bundle")
cmd.Flags().String("output", "", "output format: json, yaml")
cmd.Flags().String("compatibility", "", "output compatibility mode: support-bundle")
cmd.Flags().MarkHidden("compatibility")
@@ -71,3 +81,43 @@ func Analyze() *cobra.Command {
return cmd
}
func downloadAnalyzerSpec(specPath string) (string, error) {
specContent := ""
var err error
if _, err = os.Stat(specPath); err == nil {
if _, err := os.Stat(specPath); os.IsNotExist(err) {
return "", fmt.Errorf("%s was not found", specPath)
}
b, err := ioutil.ReadFile(specPath)
if err != nil {
return "", err
}
specContent = string(b)
} else {
if !util.IsURL(specPath) {
return "", fmt.Errorf("%s is not a URL and was not found (err %s)", specPath, err)
}
req, err := http.NewRequest("GET", specPath, nil)
if err != nil {
return "", err
}
req.Header.Set("User-Agent", "Replicated_Analyzer/v1beta1")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", err
}
specContent = string(body)
}
return specContent, nil
}
+274
View File
@@ -0,0 +1,274 @@
package cli
import (
"fmt"
"io/ioutil"
"os"
"path"
"time"
"github.com/pkg/errors"
ui "github.com/replicatedhq/termui/v3"
"github.com/replicatedhq/termui/v3/widgets"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzerunner "github.com/replicatedhq/troubleshoot/pkg/analyze"
)
var (
selectedResult = 0
table = widgets.NewTable()
isShowingSaved = false
)
func showInteractiveResults(supportBundleName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
if err := ui.Init(); err != nil {
return errors.Wrap(err, "failed to create terminal ui")
}
defer ui.Close()
drawUI(supportBundleName, analyzeResults)
uiEvents := ui.PollEvents()
for {
select {
case e := <-uiEvents:
switch e.ID {
case "<C-c>":
return nil
case "q":
if isShowingSaved == true {
isShowingSaved = false
ui.Clear()
drawUI(supportBundleName, analyzeResults)
} else {
return nil
}
case "s":
filename, err := save(analyzeResults)
if err != nil {
// show
} else {
showSaved(filename)
go func() {
time.Sleep(time.Second * 5)
isShowingSaved = false
ui.Clear()
drawUI(supportBundleName, analyzeResults)
}()
}
case "<Resize>":
ui.Clear()
drawUI(supportBundleName, analyzeResults)
case "<Down>":
if selectedResult < len(analyzeResults)-1 {
selectedResult++
} else {
selectedResult = 0
table.SelectedRow = 0
}
table.ScrollDown()
ui.Clear()
drawUI(supportBundleName, analyzeResults)
case "<Up>":
if selectedResult > 0 {
selectedResult--
} else {
selectedResult = len(analyzeResults) - 1
table.SelectedRow = len(analyzeResults)
}
table.ScrollUp()
ui.Clear()
drawUI(supportBundleName, analyzeResults)
}
}
}
}
func drawUI(supportBundleName string, analyzeResults []*analyzerunner.AnalyzeResult) {
drawGrid(analyzeResults)
drawHeader(supportBundleName)
drawFooter()
}
func drawGrid(analyzeResults []*analyzerunner.AnalyzeResult) {
drawAnalyzersTable(analyzeResults)
drawDetails(analyzeResults[selectedResult])
}
func drawHeader(supportBundleName string) {
termWidth, _ := ui.TerminalDimensions()
title := widgets.NewParagraph()
title.Text = fmt.Sprintf("%s Support Bundle Analysis", util.AppName(supportBundleName))
title.TextStyle.Fg = ui.ColorWhite
title.TextStyle.Bg = ui.ColorClear
title.TextStyle.Modifier = ui.ModifierBold
title.Border = false
left := termWidth/2 - 2*len(title.Text)/3
right := termWidth/2 + (termWidth/2 - left)
title.SetRect(left, 0, right, 1)
ui.Render(title)
}
func drawFooter() {
termWidth, termHeight := ui.TerminalDimensions()
instructions := widgets.NewParagraph()
instructions.Text = "[q] quit [s] save [↑][↓] scroll"
instructions.Border = false
left := 0
right := termWidth
top := termHeight - 1
bottom := termHeight
instructions.SetRect(left, top, right, bottom)
ui.Render(instructions)
}
func drawAnalyzersTable(analyzeResults []*analyzerunner.AnalyzeResult) {
termWidth, termHeight := ui.TerminalDimensions()
table.SetRect(0, 3, termWidth/2, termHeight-6)
table.FillRow = true
table.Border = true
table.Rows = [][]string{}
table.ColumnWidths = []int{termWidth}
for i, analyzeResult := range analyzeResults {
title := analyzeResult.Title
if analyzeResult.IsPass {
title = fmt.Sprintf("✔ %s", title)
} else if analyzeResult.IsWarn {
title = fmt.Sprintf("⚠️ %s", title)
} else if analyzeResult.IsFail {
title = fmt.Sprintf("✘ %s", title)
}
table.Rows = append(table.Rows, []string{
title,
})
if analyzeResult.IsPass {
if i == selectedResult {
table.RowStyles[i] = ui.NewStyle(ui.ColorGreen, ui.ColorClear, ui.ModifierReverse)
} else {
table.RowStyles[i] = ui.NewStyle(ui.ColorGreen, ui.ColorClear)
}
} else if analyzeResult.IsWarn {
if i == selectedResult {
table.RowStyles[i] = ui.NewStyle(ui.ColorYellow, ui.ColorClear, ui.ModifierReverse)
} else {
table.RowStyles[i] = ui.NewStyle(ui.ColorYellow, ui.ColorClear)
}
} else if analyzeResult.IsFail {
if i == selectedResult {
table.RowStyles[i] = ui.NewStyle(ui.ColorRed, ui.ColorClear, ui.ModifierReverse)
} else {
table.RowStyles[i] = ui.NewStyle(ui.ColorRed, ui.ColorClear)
}
}
}
ui.Render(table)
}
func drawDetails(analysisResult *analyzerunner.AnalyzeResult) {
termWidth, _ := ui.TerminalDimensions()
currentTop := 4
title := widgets.NewParagraph()
title.Text = analysisResult.Title
title.Border = false
if analysisResult.IsPass {
title.TextStyle = ui.NewStyle(ui.ColorGreen, ui.ColorClear, ui.ModifierBold)
} else if analysisResult.IsWarn {
title.TextStyle = ui.NewStyle(ui.ColorYellow, ui.ColorClear, ui.ModifierBold)
} else if analysisResult.IsFail {
title.TextStyle = ui.NewStyle(ui.ColorRed, ui.ColorClear, ui.ModifierBold)
}
height := estimateNumberOfLines(title.Text, termWidth/2)
title.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(title)
currentTop = currentTop + height + 1
message := widgets.NewParagraph()
message.Text = analysisResult.Message
message.Border = false
height = estimateNumberOfLines(message.Text, termWidth/2) + 2
message.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(message)
currentTop = currentTop + height + 1
if analysisResult.URI != "" {
uri := widgets.NewParagraph()
uri.Text = fmt.Sprintf("For more information: %s", analysisResult.URI)
uri.Border = false
height = estimateNumberOfLines(uri.Text, termWidth/2)
uri.SetRect(termWidth/2, currentTop, termWidth, currentTop+height)
ui.Render(uri)
currentTop = currentTop + height + 1
}
}
func estimateNumberOfLines(text string, width int) int {
lines := len(text)/width + 1
return lines
}
func showSaved(filename string) {
termWidth, termHeight := ui.TerminalDimensions()
savedMessage := widgets.NewParagraph()
savedMessage.Text = fmt.Sprintf("Support Bundle analysis results saved to\n\n%s", filename)
savedMessage.WrapText = true
savedMessage.Border = true
left := termWidth/2 - 20
right := termWidth/2 + 20
top := termHeight/2 - 4
bottom := termHeight/2 + 4
savedMessage.SetRect(left, top, right, bottom)
ui.Render(savedMessage)
isShowingSaved = true
}
func save(analyzeResults []*analyzerunner.AnalyzeResult) (string, error) {
filename := path.Join(util.HomeDir(), fmt.Sprintf("%s-results.txt", "support-bundle"))
_, err := os.Stat(filename)
if err == nil {
os.Remove(filename)
}
results := ""
for _, analyzeResult := range analyzeResults {
result := ""
if analyzeResult.IsPass {
result = "Check PASS\n"
} else if analyzeResult.IsWarn {
result = "Check WARN\n"
} else if analyzeResult.IsFail {
result = "Check FAIL\n"
}
result = result + fmt.Sprintf("Title: %s\n", analyzeResult.Title)
result = result + fmt.Sprintf("Message: %s\n", analyzeResult.Message)
if analyzeResult.URI != "" {
result = result + fmt.Sprintf("URI: %s\n", analyzeResult.URI)
}
result = result + "\n------------\n"
results = results + result
}
if err := ioutil.WriteFile(filename, []byte(results), 0644); err != nil {
return "", errors.Wrap(err, "failed to save preflight results")
}
return filename, nil
}
-148
View File
@@ -1,148 +0,0 @@
package cli
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"github.com/mholt/archiver"
"github.com/replicatedhq/troubleshoot/pkg/logger"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func receiveSupportBundle(collectorJobNamespace string, collectorJobName string) error {
// poll until there are no more "running" collectors
troubleshootClient, err := createTroubleshootK8sClient()
if err != nil {
return err
}
bundlePath, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
return err
}
defer os.RemoveAll(bundlePath)
versionFilename, err := writeVersionFile(bundlePath)
if err != nil {
return err
}
receivedCollectors := []string{}
for {
job, err := troubleshootClient.CollectorJobs(collectorJobNamespace).Get(collectorJobName, metav1.GetOptions{})
if err != nil && kuberneteserrors.IsNotFound(err) {
// where did it go!
return nil
} else if err != nil {
return err
}
for _, readyCollector := range job.Status.Successful {
alreadyReceived := false
for _, receivedCollector := range receivedCollectors {
if receivedCollector == readyCollector {
alreadyReceived = true
}
}
if alreadyReceived {
continue
}
collectorResp, err := http.Get(fmt.Sprintf("http://localhost:8000/collector/%s", readyCollector))
if err != nil {
return err
}
defer collectorResp.Body.Close()
body, err := ioutil.ReadAll(collectorResp.Body)
if err != nil {
return err
}
decoded, err := base64.StdEncoding.DecodeString(string(body))
if err != nil {
logger.Printf("failed to output for collector %s\n", readyCollector)
continue
}
files := make(map[string]interface{})
if err := json.Unmarshal(decoded, &files); err != nil {
logger.Printf("failed to unmarshal output for collector %s\n", readyCollector)
}
for filename, maybeContents := range files {
fileDir, fileName := filepath.Split(filename)
outPath := filepath.Join(bundlePath, fileDir)
if err := os.MkdirAll(outPath, 0777); err != nil {
return err
}
switch maybeContents.(type) {
case string:
decoded, err := base64.StdEncoding.DecodeString(maybeContents.(string))
if err != nil {
return err
}
if err := writeFile(filepath.Join(outPath, fileName), decoded); err != nil {
return err
}
case map[string]interface{}:
for k, v := range maybeContents.(map[string]interface{}) {
s, _ := filepath.Split(filepath.Join(outPath, fileName, k))
if err := os.MkdirAll(s, 0777); err != nil {
return err
}
decoded, err := base64.StdEncoding.DecodeString(v.(string))
if err != nil {
return err
}
if err := writeFile(filepath.Join(outPath, fileName, k), decoded); err != nil {
return err
}
}
}
}
receivedCollectors = append(receivedCollectors, readyCollector)
}
if len(job.Status.Running) == 0 {
tarGz := archiver.TarGz{
Tar: &archiver.Tar{
ImplicitTopLevelFolder: false,
},
}
// version file should be first in tar archive for quick extraction
paths := []string{
versionFilename,
}
for _, id := range receivedCollectors {
paths = append(paths, filepath.Join(bundlePath, id))
}
if err := tarGz.Archive(paths, "support-bundle.tar.gz"); err != nil {
return err
}
return nil
}
}
}
func writeFile(filename string, contents []byte) error {
if err := ioutil.WriteFile(filename, contents, 0644); err != nil {
return err
}
return nil
}
-80
View File
@@ -1,80 +0,0 @@
package cli
import (
"errors"
"path/filepath"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func Retrieve() *cobra.Command {
cmd := &cobra.Command{
Use: "retrieve",
Short: "retrieve a support bundle from a job in the cluster",
Long: `...`,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlag("collectors", cmd.Flags().Lookup("collectors"))
viper.BindPFlag("namespace", cmd.Flags().Lookup("namespace"))
viper.BindPFlag("kubecontext", cmd.Flags().Lookup("kubecontext"))
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
troubleshootClient, err := createTroubleshootK8sClient()
if err != nil {
return err
}
collectorJobs, err := troubleshootClient.CollectorJobs(v.GetString("namespace")).List(metav1.ListOptions{})
if err != nil {
return err
}
var collectorJob *troubleshootv1beta1.CollectorJob
if v.GetString("collectors") == "" && len(collectorJobs.Items) == 1 {
collectorJob = &collectorJobs.Items[0]
} else {
for _, foundCollectorJob := range collectorJobs.Items {
if foundCollectorJob.Spec.Collector.Name == v.GetString("collectors") {
collectorJob = &foundCollectorJob
break
}
}
}
if collectorJob == nil {
logger.Printf("unable to find collector job\n")
return errors.New("no collectors")
}
logger.Printf("connecting to collector job %s\n", collectorJob.Name)
stopChan, err := k8sutil.PortForward(v.GetString("kubecontext"), 8000, 8000, collectorJob.Status.ServerPodNamespace, collectorJob.Status.ServerPodName)
if err != nil {
return err
}
if err := receiveSupportBundle(collectorJob.Namespace, collectorJob.Name); err != nil {
return err
}
// write a zip
close(stopChan)
return nil
},
}
cmd.Flags().String("collectors", "", "name of the collectors to use")
cmd.Flags().String("namespace", "", "namespace the collectors can be found in")
cmd.Flags().String("kubecontext", filepath.Join(homeDir(), ".kube", "config"), "the kubecontext to use when connecting")
viper.BindPFlags(cmd.Flags())
return cmd
}
+31 -22
View File
@@ -1,12 +1,12 @@
package cli
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@@ -14,11 +14,12 @@ import (
func RootCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "troubleshoot [url]",
Use: "support-bundle [url]",
Args: cobra.MinimumNArgs(1),
Short: "Generate and manage support bundles",
Short: "Generate a support bundle",
Long: `A support bundle is an archive of files, output, metrics and state
from a server that can be used to assist when troubleshooting a server.`,
from a server that can be used to assist when troubleshooting a Kubernetes cluster.`,
SilenceUsage: true,
PreRun: func(cmd *cobra.Command, args []string) {
viper.BindPFlags(cmd.Flags())
},
@@ -26,38 +27,38 @@ from a server that can be used to assist when troubleshooting a server.`,
v := viper.GetViper()
logger.SetQuiet(v.GetBool("quiet"))
if len(args) == 0 {
return runTroubleshootCRD(v)
}
return runTroubleshootNoCRD(v, args[0])
return runTroubleshoot(v, args[0])
},
}
cobra.OnInitialize(initConfig)
cmd.AddCommand(Analyze())
cmd.AddCommand(VersionCmd())
cmd.Flags().String("collectors", "", "name of the collectors to use")
cmd.Flags().String("namespace", "default", "namespace the collectors can be found in")
cmd.Flags().String("kubecontext", filepath.Join(homeDir(), ".kube", "config"), "the kubecontext to use when connecting")
cmd.Flags().String("image", "", "the full name of the collector image to use")
cmd.Flags().String("pullpolicy", "", "the pull policy of the collector image")
cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
cmd.Flags().Bool("redact", true, "enable/disable default redactions")
cmd.Flags().Bool("interactive", true, "enable/disable interactive mode")
cmd.Flags().Bool("collect-without-permissions", true, "always generate a support bundle, even if it some require additional permissions")
cmd.Flags().String("since-time", "", "force pod logs collectors to return logs after a specific date (RFC3339)")
cmd.Flags().String("since", "", "force pod logs collectors to return logs newer than a relative duration like 5s, 2m, or 3h.")
cmd.Flags().StringP("output", "o", "", "specify the output file path for the support bundle")
// hidden in favor of the `insecure-skip-tls-verify` flag
cmd.Flags().Bool("allow-insecure-connections", false, "when set, do not verify TLS certs when retrieving spec and reporting results")
cmd.Flags().MarkHidden("allow-insecure-connections")
cmd.Flags().String("serviceaccount", "", "name of the service account to use. if not provided, one will be created")
viper.BindPFlags(cmd.Flags())
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
k8sutil.AddFlags(cmd.Flags())
return cmd
}
func InitAndExecute() {
if err := RootCmd().Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
@@ -67,7 +68,7 @@ func initConfig() {
viper.AutomaticEnv()
}
func ensureCollectorInList(list []*troubleshootv1beta1.Collect, collector troubleshootv1beta1.Collect) []*troubleshootv1beta1.Collect {
func ensureCollectorInList(list []*troubleshootv1beta2.Collect, collector troubleshootv1beta2.Collect) []*troubleshootv1beta2.Collect {
for _, inList := range list {
if collector.ClusterResources != nil && inList.ClusterResources != nil {
return list
@@ -79,3 +80,11 @@ func ensureCollectorInList(list []*troubleshootv1beta1.Collect, collector troubl
return append(list, &collector)
}
func writeFile(filename string, contents []byte) error {
if err := ioutil.WriteFile(filename, contents, 0644); err != nil {
return err
}
return nil
}
+327
View File
@@ -0,0 +1,327 @@
package cli
import (
"crypto/tls"
"encoding/json"
"fmt"
"net/http"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"time"
cursor "github.com/ahmetalpbalkan/go-cursor"
"github.com/fatih/color"
"github.com/manifoldco/promptui"
"github.com/mattn/go-isatty"
"github.com/pkg/errors"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
troubleshootclientsetscheme "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/scheme"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/replicatedhq/troubleshoot/pkg/docrewrite"
"github.com/replicatedhq/troubleshoot/pkg/httputil"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/supportbundle"
"github.com/spf13/viper"
spin "github.com/tj/go-spin"
"k8s.io/client-go/rest"
)
func runTroubleshoot(v *viper.Viper, arg string) error {
interactive := v.GetBool("interactive") && isatty.IsTerminal(os.Stdout.Fd())
if interactive {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
}
go func() {
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt)
<-signalChan
if interactive {
fmt.Print(cursor.Show())
}
os.Exit(0)
}()
restConfig, err := k8sutil.GetRESTConfig()
if err != nil {
return errors.Wrap(err, "failed to convert kube flags to rest config")
}
var sinceTime *time.Time
if v.GetString("since-time") != "" || v.GetString("since") != "" {
sinceTime, err = parseTimeFlags(v)
if err != nil {
return errors.Wrap(err, "failed parse since time")
}
}
if v.GetBool("allow-insecure-connections") || v.GetBool("insecure-skip-tls-verify") {
httputil.AddTransport(&http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
})
}
collectorContent, err := supportbundle.LoadSupportBundleSpec(arg)
if err != nil {
return errors.Wrap(err, "failed to load collector spec")
}
multidocs := strings.Split(string(collectorContent), "\n---\n")
// we support both raw collector kinds and supportbundle kinds here
supportBundle, err := supportbundle.ParseSupportBundleFromDoc([]byte(multidocs[0]))
if err != nil {
return errors.Wrap(err, "failed to parse collector")
}
troubleshootclientsetscheme.AddToScheme(scheme.Scheme)
decode := scheme.Codecs.UniversalDeserializer().Decode
additionalRedactors := &troubleshootv1beta2.Redactor{}
for idx, redactor := range v.GetStringSlice("redactors") {
redactorObj, err := supportbundle.GetRedactorFromURI(redactor)
if err != nil {
return errors.Wrapf(err, "failed to get redactor spec %s, #%d", redactor, idx)
}
if redactorObj != nil {
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, redactorObj.Spec.Redactors...)
}
}
for i, additionalDoc := range multidocs {
if i == 0 {
continue
}
additionalDoc, err := docrewrite.ConvertToV1Beta2([]byte(additionalDoc))
if err != nil {
return errors.Wrap(err, "failed to convert to v1beta2")
}
obj, _, err := decode(additionalDoc, nil, nil)
if err != nil {
return errors.Wrapf(err, "failed to parse additional doc %d", i)
}
multidocRedactors, ok := obj.(*troubleshootv1beta2.Redactor)
if !ok {
continue
}
additionalRedactors.Spec.Redactors = append(additionalRedactors.Spec.Redactors, multidocRedactors.Spec.Redactors...)
}
var collectorCB func(chan interface{}, string)
progressChan := make(chan interface{}) // non-zero buffer can result in missed messages
finishedCh := make(chan bool, 1)
isFinishedChClosed := false
if !interactive {
// TODO (dans): custom warning handler to capture warning in `analysisOutput`
restConfig.WarningHandler = rest.NoWarnings{}
collectorCB = func(ch chan interface{}, name string) {
return
}
// TODO (dans): maybe log to file
go func() {
for {
select {
case _ = <-progressChan:
// do nothing
}
}
}()
} else {
s := spin.New()
go func() {
currentDir := ""
for {
select {
case msg := <-progressChan:
switch msg := msg.(type) {
case error:
c := color.New(color.FgHiRed)
c.Println(fmt.Sprintf("%s\r * %v", cursor.ClearEntireLine(), msg))
case string:
currentDir = filepath.Base(msg)
}
case <-finishedCh:
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
return
case <-time.After(time.Millisecond * 100):
if currentDir == "" {
fmt.Printf("\r%s \033[36mCollecting support bundle\033[m %s", cursor.ClearEntireLine(), s.Next())
} else {
fmt.Printf("\r%s \033[36mCollecting support bundle\033[m %s %s", cursor.ClearEntireLine(), s.Next(), currentDir)
}
}
}
}()
defer func() {
if !isFinishedChClosed {
close(finishedCh)
}
}()
collectorCB = func(c chan interface{}, msg string) {
c <- fmt.Sprintf("%s", msg)
}
}
createOpts := supportbundle.SupportBundleCreateOpts{
CollectorProgressCallback: collectorCB,
CollectWithoutPermissions: v.GetBool("collect-without-permissions"),
KubernetesRestConfig: restConfig,
Namespace: v.GetString("namespace"),
ProgressChan: progressChan,
SinceTime: sinceTime,
OutputPath: v.GetString("output"),
Redact: v.GetBool("redact"),
FromCLI: true,
}
nonInteractiveOutput := analysisOutput{}
if interactive {
c := color.New()
c.Println(fmt.Sprintf("\r%s\r", cursor.ClearEntireLine()))
}
response, err := supportbundle.CollectSupportBundleFromSpec(&supportBundle.Spec, additionalRedactors, createOpts)
if err != nil {
return errors.Wrap(err, "failed to run collect and analyze process")
}
if len(response.AnalyzerResults) > 0 {
if interactive {
close(finishedCh) // this removes the spinner
isFinishedChClosed = true
if err := showInteractiveResults(supportBundle.Name, response.AnalyzerResults); err != nil {
interactive = false
}
} else {
nonInteractiveOutput.Analysis = response.AnalyzerResults
}
}
if !response.FileUploaded {
if appName := supportBundle.Labels["applicationName"]; appName != "" {
f := `A support bundle for %s has been created in this directory
named %s. Please upload it on the Troubleshoot page of
the %s Admin Console to begin analysis.`
fmt.Printf(f, appName, response.ArchivePath, appName)
return nil
}
if !interactive {
nonInteractiveOutput.ArchivePath = response.ArchivePath
output, err := nonInteractiveOutput.FormattedAnalysisOutput()
if err != nil {
return errors.Wrap(err, "failed to format non-interactive output")
}
fmt.Println(output)
return nil
}
fmt.Printf("%s\n", response.ArchivePath)
return nil
}
if interactive {
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
}
if response.FileUploaded {
fmt.Printf("A support bundle has been created and uploaded to your cluster for analysis. Please visit the Troubleshoot page to continue.\n")
fmt.Printf("A copy of this support bundle was written to the current directory, named %q\n", response.ArchivePath)
} else {
fmt.Printf("A support bundle has been created in the current directory named %q\n", response.ArchivePath)
}
return nil
}
func getExpectedContentType(uploadURL string) string {
parsedURL, err := url.Parse(uploadURL)
if err != nil {
return ""
}
return parsedURL.Query().Get("Content-Type")
}
func parseTimeFlags(v *viper.Viper) (*time.Time, error) {
var (
sinceTime time.Time
err error
)
if v.GetString("since-time") != "" {
if v.GetString("since") != "" {
return nil, errors.Errorf("at most one of `sinceTime` or `since` may be specified")
}
sinceTime, err = time.Parse(time.RFC3339, v.GetString("since-time"))
if err != nil {
return nil, errors.Wrap(err, "unable to parse --since-time flag")
}
} else {
parsedDuration, err := time.ParseDuration(v.GetString("since"))
if err != nil {
return nil, errors.Wrap(err, "unable to parse --since flag")
}
now := time.Now()
sinceTime = now.Add(0 - parsedDuration)
}
return &sinceTime, nil
}
func shouldRetryRequest(err error) bool {
if strings.Contains(err.Error(), "x509") && canTryInsecure() {
httputil.AddTransport(&http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
})
return true
}
return false
}
func canTryInsecure() bool {
if !isatty.IsTerminal(os.Stdout.Fd()) {
return false
}
prompt := promptui.Prompt{
Label: "Connection appears to be insecure. Would you like to attempt to create a support bundle anyway?",
IsConfirm: true,
}
_, err := prompt.Run()
return err == nil
}
type analysisOutput struct {
Analysis []*analyzer.AnalyzeResult
ArchivePath string
}
func (a *analysisOutput) FormattedAnalysisOutput() (outputJson string, err error) {
type convertedOutput struct {
ConvertedAnalysis []*convert.Result `json:"analyzerResults"`
ArchivePath string `json:"archivePath"`
}
converted := convert.FromAnalyzerResult(a.Analysis)
o := convertedOutput{
ConvertedAnalysis: converted,
ArchivePath: a.ArchivePath,
}
formatted, err := json.MarshalIndent(o, "", " ")
if err != nil {
return "", fmt.Errorf("\r * Failed to format analysis: %v\n", err)
}
return string(formatted), nil
}
-102
View File
@@ -1,102 +0,0 @@
package cli
import (
"errors"
"fmt"
"time"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/spf13/viper"
kuberneteserrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func runTroubleshootCRD(v *viper.Viper) error {
troubleshootClient, err := createTroubleshootK8sClient()
if err != nil {
return err
}
collectorName := v.GetString("collectors")
if collectorName == "" {
collectors, err := troubleshootClient.Collectors(v.GetString("namespace")).List(metav1.ListOptions{})
if err != nil {
return err
}
if len(collectors.Items) == 1 {
collectorName = collectors.Items[0].Name
}
}
if collectorName == "" {
return errors.New("unknown collectors, try using the --collectors flags")
}
// generate a unique name
now := time.Now()
suffix := fmt.Sprintf("%d", now.Unix())
collectorJobName := fmt.Sprintf("%s-job-%s", collectorName, suffix[len(suffix)-4:])
collectorJob := troubleshootv1beta1.CollectorJob{
ObjectMeta: metav1.ObjectMeta{
Name: collectorJobName,
Namespace: v.GetString("namespace"),
},
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "collectorjob.troubleshoot.replicated.com",
},
Spec: troubleshootv1beta1.CollectorJobSpec{
Collector: troubleshootv1beta1.CollectorRef{
Name: collectorName,
Namespace: v.GetString("namespace"),
},
Image: v.GetString("image"),
ImagePullPolicy: v.GetString("pullpolicy"),
Redact: v.GetBool("redact"),
},
}
if _, err := troubleshootClient.CollectorJobs(v.GetString("namespace")).Create(&collectorJob); err != nil {
return err
}
// Poll the status of the Custom Resource for it to include a callback
var found *troubleshootv1beta1.CollectorJob
start := time.Now()
for {
current, err := troubleshootClient.CollectorJobs(v.GetString("namespace")).Get(collectorJobName, metav1.GetOptions{})
if err != nil && kuberneteserrors.IsNotFound(err) {
continue
} else if err != nil {
return err
}
if current.Status.IsServerReady {
found = current
break
}
if time.Now().Sub(start) > time.Duration(time.Second*10) {
return errors.New("collectorjob failed to start")
}
time.Sleep(time.Millisecond * 200)
}
// Connect to the callback
stopChan, err := k8sutil.PortForward(v.GetString("kubecontext"), 8000, 8000, found.Status.ServerPodNamespace, found.Status.ServerPodName)
if err != nil {
return err
}
if err := receiveSupportBundle(found.Namespace, found.Name); err != nil {
return err
}
// Write
close(stopChan)
return nil
}
-314
View File
@@ -1,314 +0,0 @@
package cli
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"path/filepath"
"time"
"github.com/ahmetalpbalkan/go-cursor"
"github.com/fatih/color"
"github.com/mholt/archiver"
"github.com/pkg/errors"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"github.com/spf13/viper"
"github.com/tj/go-spin"
"gopkg.in/yaml.v2"
)
func runTroubleshootNoCRD(v *viper.Viper, arg string) error {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
collectorContent := ""
if !isURL(arg) {
if _, err := os.Stat(arg); os.IsNotExist(err) {
return fmt.Errorf("%s was not found", arg)
}
b, err := ioutil.ReadFile(arg)
if err != nil {
return errors.Wrap(err, "read spec file")
}
collectorContent = string(b)
} else {
req, err := http.NewRequest("GET", arg, nil)
if err != nil {
return errors.Wrap(err, "make request")
}
req.Header.Set("User-Agent", "Replicated_Troubleshoot/v1beta1")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "execute request")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
return errors.Wrap(err, "read responce body")
}
collectorContent = string(body)
}
collector := troubleshootv1beta1.Collector{}
if err := yaml.Unmarshal([]byte(collectorContent), &collector); err != nil {
return fmt.Errorf("unable to parse %s collectors", arg)
}
s := spin.New()
finishedCh := make(chan bool, 1)
progressChan := make(chan interface{}, 1)
go func() {
currentDir := ""
for {
select {
case msg := <-progressChan:
switch msg := msg.(type) {
case error:
c := color.New(color.FgHiRed)
c.Println(fmt.Sprintf("%s * %v", cursor.ClearEntireLine(), msg))
case string:
currentDir = filepath.Base(msg)
}
case <-finishedCh:
fmt.Printf("\r")
return
case <-time.After(time.Millisecond * 100):
if currentDir == "" {
fmt.Printf("\r%s \033[36mCollecting support bundle\033[m %s", cursor.ClearEntireLine(), s.Next())
} else {
fmt.Printf("\r%s \033[36mCollecting support bundle\033[m %s %s", cursor.ClearEntireLine(), s.Next(), currentDir)
}
}
}
}()
defer func() {
finishedCh <- true
}()
archivePath, err := runCollectors(v, collector, progressChan)
if err != nil {
return errors.Wrap(err, "run collectors")
}
fmt.Printf("\r%s", cursor.ClearEntireLine())
if len(collector.Spec.AfterCollection) == 0 {
msg := archivePath
if appName := collector.Labels["applicationName"]; appName != "" {
f := `A support bundle for %s has been created in this directory
named %s. Please upload it on the Troubleshoot page of
the %s Admin Console to begin analysis.`
msg = fmt.Sprintf(f, appName, archivePath, appName)
}
fmt.Printf("%s\n", msg)
return nil
}
for _, ac := range collector.Spec.AfterCollection {
if ac.UploadResultsTo != nil {
if err := uploadSupportBundle(ac.UploadResultsTo, archivePath); err != nil {
return errors.Wrap(err, "upload support bundle")
}
} else if ac.Callback != nil {
if err := callbackSupportBundleAPI(ac.Callback, archivePath); err != nil {
return errors.Wrap(err, "execute callback")
}
}
}
fmt.Printf("A support bundle has been created in the current directory named %q\n", archivePath)
return nil
}
func runCollectors(v *viper.Viper, collector troubleshootv1beta1.Collector, progressChan chan interface{}) (string, error) {
bundlePath, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
return "", errors.Wrap(err, "create temp dir")
}
defer os.RemoveAll(bundlePath)
versionFilename, err := writeVersionFile(bundlePath)
if err != nil {
return "", errors.Wrap(err, "write version file")
}
desiredCollectors := make([]*troubleshootv1beta1.Collect, 0, 0)
for _, definedCollector := range collector.Spec.Collectors {
desiredCollectors = append(desiredCollectors, definedCollector)
}
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterInfo: &troubleshootv1beta1.ClusterInfo{}})
desiredCollectors = ensureCollectorInList(desiredCollectors, troubleshootv1beta1.Collect{ClusterResources: &troubleshootv1beta1.ClusterResources{}})
collectorDirs := []string{}
// Run preflights collectors synchronously
for _, desiredCollector := range desiredCollectors {
collector := collect.Collector{
Redact: true,
Collect: desiredCollector,
}
result, err := collector.RunCollectorSync()
if err != nil {
progressChan <- fmt.Errorf("failed to run collector %q: %v", collector.GetDisplayName(), err)
continue
}
collectorDir, err := parseAndSaveCollectorOutput(string(result), bundlePath)
if err != nil {
progressChan <- fmt.Errorf("failed to parse collector spec %q: %v", collector.GetDisplayName(), err)
continue
}
if collectorDir == "" {
continue
}
progressChan <- collectorDir
collectorDirs = append(collectorDirs, collectorDir)
}
tarGz := archiver.TarGz{
Tar: &archiver.Tar{
ImplicitTopLevelFolder: false,
},
}
// version file should be first in tar archive for quick extraction
paths := []string{
versionFilename,
}
for _, collectorDir := range collectorDirs {
paths = append(paths, collectorDir)
}
if err := tarGz.Archive(paths, "support-bundle.tar.gz"); err != nil {
return "", errors.Wrap(err, "create archive")
}
return "support-bundle.tar.gz", nil
}
func parseAndSaveCollectorOutput(output string, bundlePath string) (string, error) {
dir := ""
input := make(map[string]interface{})
if err := json.Unmarshal([]byte(output), &input); err != nil {
return "", errors.Wrap(err, "unmarshal output")
}
for filename, maybeContents := range input {
fileDir, fileName := filepath.Split(filename)
outPath := filepath.Join(bundlePath, fileDir)
dir = outPath
if err := os.MkdirAll(outPath, 0777); err != nil {
return "", errors.Wrap(err, "create output file")
}
switch maybeContents.(type) {
case string:
decoded, err := base64.StdEncoding.DecodeString(maybeContents.(string))
if err != nil {
return "", errors.Wrap(err, "decode collector output")
}
if err := writeFile(filepath.Join(outPath, fileName), decoded); err != nil {
return "", errors.Wrap(err, "write collector output")
}
case map[string]interface{}:
for k, v := range maybeContents.(map[string]interface{}) {
s, _ := filepath.Split(filepath.Join(outPath, fileName, k))
if err := os.MkdirAll(s, 0777); err != nil {
return "", errors.Wrap(err, "write output directories")
}
decoded, err := base64.StdEncoding.DecodeString(v.(string))
if err != nil {
return "", errors.Wrap(err, "decode output")
}
if err := writeFile(filepath.Join(outPath, fileName, k), decoded); err != nil {
return "", errors.Wrap(err, "write output")
}
}
}
}
return dir, nil
}
func uploadSupportBundle(r *troubleshootv1beta1.ResultRequest, archivePath string) error {
contentType := getExpectedContentType(r.URI)
if contentType != "" && contentType != "application/tar+gzip" {
return fmt.Errorf("cannot upload content type %s", contentType)
}
f, err := os.Open(archivePath)
if err != nil {
return errors.Wrap(err, "open file")
}
defer f.Close()
fileStat, err := f.Stat()
if err != nil {
return errors.Wrap(err, "stat file")
}
req, err := http.NewRequest(r.Method, r.URI, f)
if err != nil {
return errors.Wrap(err, "create request")
}
req.ContentLength = fileStat.Size()
if contentType != "" {
req.Header.Set("Content-Type", contentType)
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "execute request")
}
if resp.StatusCode >= 300 {
return fmt.Errorf("unexpected status code %d", resp.StatusCode)
}
return nil
}
func getExpectedContentType(uploadURL string) string {
parsedURL, err := url.Parse(uploadURL)
if err != nil {
return ""
}
return parsedURL.Query().Get("Content-Type")
}
func callbackSupportBundleAPI(r *troubleshootv1beta1.ResultRequest, archivePath string) error {
req, err := http.NewRequest(r.Method, r.URI, nil)
if err != nil {
return errors.Wrap(err, "create request")
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return errors.Wrap(err, "execute request")
}
if resp.StatusCode >= 300 {
return fmt.Errorf("unexpected status code %d", resp.StatusCode)
}
return nil
}
-122
View File
@@ -1,122 +0,0 @@
package cli
import (
"fmt"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
func createServiceAccount(collector troubleshootv1beta1.Collector, namespace string, clientset *kubernetes.Clientset) (string, error) {
name := fmt.Sprintf("troubleshoot-%s", collector.Name)
serviceAccount := corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}
_, err := clientset.CoreV1().ServiceAccounts(namespace).Create(&serviceAccount)
if err != nil {
return "", err
}
role := rbacv1.ClusterRole{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ClusterRole",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Rules: []rbacv1.PolicyRule{
{
APIGroups: []string{""},
Resources: []string{
"namespaces",
"pods",
"services",
"secrets",
},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"apps"},
Resources: []string{"deployments"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"extensions"},
Resources: []string{"ingresses"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"storage.k8s.io"},
Resources: []string{"storageclasses"},
Verbs: metav1.Verbs{"list"},
},
{
APIGroups: []string{"apiextensions.k8s.io"},
Resources: []string{"customresourcedefinitions"},
Verbs: metav1.Verbs{"list"},
},
},
}
_, err = clientset.RbacV1().ClusterRoles().Create(&role)
if err != nil {
return "", err
}
roleBinding := rbacv1.ClusterRoleBinding{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ClusterRoleBinding",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Subjects: []rbacv1.Subject{
{
Kind: "ServiceAccount",
Name: name,
Namespace: namespace,
},
},
RoleRef: rbacv1.RoleRef{
APIGroup: "rbac.authorization.k8s.io",
Kind: "ClusterRole",
Name: name,
},
}
_, err = clientset.RbacV1().ClusterRoleBindings().Create(&roleBinding)
if err != nil {
return "", err
}
return name, nil
}
func removeServiceAccount(name string, namespace string, clientset *kubernetes.Clientset) error {
if err := clientset.RbacV1().ClusterRoleBindings().Delete(name, &metav1.DeleteOptions{}); err != nil {
return err
}
if err := clientset.RbacV1().ClusterRoles().Delete(name, &metav1.DeleteOptions{}); err != nil {
return err
}
if err := clientset.CoreV1().ServiceAccounts(namespace).Delete(name, &metav1.DeleteOptions{}); err != nil {
return err
}
return nil
}
+15 -32
View File
@@ -1,41 +1,24 @@
package cli
import (
"net/url"
"fmt"
"os"
troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1"
"github.com/spf13/viper"
"k8s.io/client-go/tools/clientcmd"
"github.com/pkg/errors"
)
func homeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
func findFileName(basename, extension string) (string, error) {
n := 1
name := basename
for {
filename := name + "." + extension
if _, err := os.Stat(filename); os.IsNotExist(err) {
return filename, nil
} else if err != nil {
return "", errors.Wrap(err, "check file exists")
}
name = fmt.Sprintf("%s (%d)", basename, n)
n = n + 1
}
return os.Getenv("USERPROFILE") // windows
}
func isURL(str string) bool {
_, err := url.ParseRequestURI(str)
if err != nil {
return false
}
return true
}
func createTroubleshootK8sClient() (*troubleshootclientv1beta1.TroubleshootV1beta1Client, error) {
v := viper.GetViper()
config, err := clientcmd.BuildConfigFromFlags("", v.GetString("kubecontext"))
if err != nil {
return nil, err
}
troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(config)
if err != nil {
return nil, err
}
return troubleshootClient, nil
}
+33 -9
View File
@@ -1,27 +1,51 @@
package cli
import (
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"gopkg.in/yaml.v2"
"fmt"
"io/ioutil"
"path/filepath"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/version"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
)
func writeVersionFile(path string) (string, error) {
version := troubleshootv1beta1.SupportBundleVersion{
ApiVersion: "troubleshoot.replicated.com/v1beta1",
func VersionCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Print the current version and exit",
Long: `Print the current version and exit`,
RunE: func(cmd *cobra.Command, args []string) error {
fmt.Printf("Replicated Troubleshoot %s\n", version.Version())
return nil
},
}
return cmd
}
const VersionFilename = "version.yaml"
func writeVersionFile(path string) error {
version := troubleshootv1beta2.SupportBundleVersion{
ApiVersion: "troubleshoot.sh/v1beta2",
Kind: "SupportBundle",
Spec: troubleshootv1beta2.SupportBundleVersionSpec{
VersionNumber: version.Version(),
},
}
b, err := yaml.Marshal(version)
if err != nil {
return "", err
return err
}
filename := filepath.Join(path, "version.yaml")
filename := filepath.Join(path, VersionFilename)
err = ioutil.WriteFile(filename, b, 0644)
if err != nil {
return "", err
return err
}
return filename, nil
return nil
}
+1 -1
View File
@@ -2,7 +2,7 @@ package main
import (
"github.com/replicatedhq/troubleshoot/cmd/troubleshoot/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
func main() {
+39
View File
@@ -0,0 +1,39 @@
package util
import (
"net/url"
"os"
"strings"
)
func HomeDir() string {
if h := os.Getenv("HOME"); h != "" {
return h
}
return os.Getenv("USERPROFILE") // windows
}
func IsURL(str string) bool {
parsed, err := url.ParseRequestURI(str)
if err != nil {
return false
}
return parsed.Scheme != ""
}
func AppName(name string) string {
words := strings.Split(strings.Title(strings.Replace(name, "-", " ", -1)), " ")
casedWords := []string{}
for i, word := range words {
if strings.ToLower(word) == "ai" {
casedWords = append(casedWords, "AI")
} else if strings.ToLower(word) == "io" && i > 0 {
casedWords[i-1] += ".io"
} else {
casedWords = append(casedWords, word)
}
}
return strings.Join(casedWords, " ")
}
+9
View File
@@ -0,0 +1,9 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: modules
spec:
collectors:
- cpu: {}
- memory: {}
# - kernelModules: {}
+9
View File
@@ -0,0 +1,9 @@
apiVersion: troubleshoot.sh/v1beta2
kind: RemoteCollector
metadata:
name: modules
spec:
collectors:
- cpu: {}
- memory: {}
# - kernelModules: {}
View File
@@ -3,397 +3,44 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: analyzerjobs.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: AnalyzerJob
listKind: AnalyzerJobList
plural: analyzerjobs
scope: ""
singular: analyzerjob
scope: Namespaced
validation:
openAPIV3Schema:
description: AnalyzerJob is the Schema for the analyzerjobs 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'
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'
type: string
metadata:
type: object
spec:
description: AnalyzerJobSpec defines the desired state of AnalyzerJob
type: object
status:
description: AnalyzerJobStatus defines the observed state of AnalyzerJob
type: object
type: object
version: v1beta1
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: AnalyzerJob is the Schema for the analyzerjobs 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/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/api-conventions.md#types-kinds'
type: string
metadata:
properties:
annotations:
additionalProperties:
type: string
description: 'Annotations is an unstructured key value map stored
with a resource that may be set by external tools to store and retrieve
arbitrary metadata. They are not queryable and should be preserved
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
type: object
clusterName:
description: The name of the cluster which the object belongs to.
This is used to distinguish resources with same name and namespace
in different clusters. This field is not set anywhere right now
and apiserver is going to ignore it if set in create or update request.
type: string
creationTimestamp:
description: "CreationTimestamp is a timestamp representing the server
time when this object was created. It is not guaranteed to be set
in happens-before order across separate operations. Clients may
not set this value. It is represented in RFC3339 form and is in
UTC. \n Populated by the system. Read-only. Null for lists. More
info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
deletionGracePeriodSeconds:
description: Number of seconds allowed for this object to gracefully
terminate before it will be removed from the system. Only set when
deletionTimestamp is also set. May only be shortened. Read-only.
format: int64
type: integer
deletionTimestamp:
description: "DeletionTimestamp is RFC 3339 date and time at which
this resource will be deleted. This field is set by the server when
a graceful deletion is requested by the user, and is not directly
settable by a client. The resource is expected to be deleted (no
longer visible from resource lists, and not reachable by name) after
the time in this field, once the finalizers list is empty. As long
as the finalizers list contains items, deletion is blocked. Once
the deletionTimestamp is set, this value may not be unset or be
set further into the future, although it may be shortened or the
resource may be deleted prior to this time. For example, a user
may request that a pod is deleted in 30 seconds. The Kubelet will
react by sending a graceful termination signal to the containers
in the pod. After that 30 seconds, the Kubelet will send a hard
termination signal (SIGKILL) to the container and after cleanup,
remove the pod from the API. In the presence of network partitions,
this object may still exist after this timestamp, until an administrator
or automated process can determine the resource is fully terminated.
If not set, graceful deletion of the object has not been requested.
\n Populated by the system when a graceful deletion is requested.
Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
finalizers:
description: Must be empty before the object is deleted from the registry.
Each entry is an identifier for the responsible component that will
remove the entry from the list. If the deletionTimestamp of the
object is non-nil, entries in this list can only be removed.
items:
type: string
type: array
generateName:
description: "GenerateName is an optional prefix, used by the server,
to generate a unique name ONLY IF the Name field has not been provided.
If this field is used, the name returned to the client will be different
than the name passed. This value will also be combined with a unique
suffix. The provided value has the same validation rules as the
Name field, and may be truncated by the length of the suffix required
to make the value unique on the server. \n If this field is specified
and the generated name exists, the server will NOT return a 409
- instead, it will either return 201 Created or 500 with Reason
ServerTimeout indicating a unique name could not be found in the
time allotted, and the client should retry (optionally after the
time indicated in the Retry-After header). \n Applied only if Name
is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency"
type: string
generation:
description: A sequence number representing a specific generation
of the desired state. Populated by the system. Read-only.
format: int64
type: integer
initializers:
description: "An initializer is a controller which enforces some system
invariant at object creation time. This field is a list of initializers
that have not yet acted on this object. If nil or empty, this object
has been completely initialized. Otherwise, the object is considered
uninitialized and is hidden (in list/watch and get calls) from clients
that haven't explicitly asked to observe uninitialized objects.
\n When an object is created, the system will populate this list
with the current set of initializers. Only privileged users may
set or modify this list. Once it is empty, it may not be modified
further by any user. \n DEPRECATED - initializers are an alpha field
and will be removed in v1.15."
properties:
pending:
description: Pending is a list of initializers that must execute
in order before this object is visible. When the last pending
initializer is removed, and no failing result is set, the initializers
struct will be set to nil and the object is considered as initialized
and visible to all clients.
items:
properties:
name:
description: name of the process that is responsible for
initializing this object.
type: string
required:
- name
type: object
type: array
result:
description: If result is set with the Failure field, the object
will be persisted to storage and then deleted, ensuring that
other clients can observe the deletion.
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/api-conventions.md#resources'
type: string
code:
description: Suggested HTTP return code for this status, 0
if not set.
format: int32
type: integer
details:
description: Extended data associated with the reason. Each
reason may define its own extended details. This field is
optional and the data returned is not guaranteed to conform
to any schema except that defined by the reason type.
properties:
causes:
description: The Causes array includes more details associated
with the StatusReason failure. Not all StatusReasons
may provide detailed causes.
items:
properties:
field:
description: "The field of the resource that has
caused this error, as named by its JSON serialization.
May include dot and postfix notation for nested
attributes. Arrays are zero-indexed. Fields may
appear more than once in an array of causes due
to fields having multiple errors. Optional. \n
Examples: \"name\" - the field \"name\" on the
current resource \"items[0].name\" - the field
\"name\" on the first array entry in \"items\""
type: string
message:
description: A human-readable description of the
cause of the error. This field may be presented
as-is to a reader.
type: string
reason:
description: A machine-readable description of the
cause of the error. If this value is empty there
is no information available.
type: string
type: object
type: array
group:
description: The group attribute of the resource associated
with the status StatusReason.
type: string
kind:
description: 'The kind attribute of the resource associated
with the status StatusReason. On some operations may
differ from the requested resource Kind. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: The name attribute of the resource associated
with the status StatusReason (when there is a single
name which can be described).
type: string
retryAfterSeconds:
description: If specified, the time in seconds before
the operation should be retried. Some errors may indicate
the client must take an alternate action - for those
errors this field may indicate how long to wait before
taking the alternate action.
format: int32
type: integer
uid:
description: 'UID of the resource. (when there is a single
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
type: object
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/api-conventions.md#types-kinds'
type: string
message:
description: A human-readable description of the status of
this operation.
type: string
metadata:
description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
properties:
continue:
description: continue may be set if the user set a limit
on the number of items returned, and indicates that
the server has more data available. The value is opaque
and may be used to issue another request to the endpoint
that served this list to retrieve the next set of available
objects. Continuing a consistent list may not be possible
if the server configuration has changed or more than
a few minutes have passed. The resourceVersion field
returned when using this continue value will be identical
to the value in the first response, unless you have
received this token from an error message.
type: string
resourceVersion:
description: 'String that identifies the server''s internal
version of this object that can be used by clients to
determine when objects have changed. Value must be treated
as opaque by clients and passed unmodified back to the
server. Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
type: string
selfLink:
description: selfLink is a URL representing this object.
Populated by the system. Read-only.
type: string
type: object
reason:
description: A machine-readable description of why this operation
is in the "Failure" status. If this value is empty there
is no information available. A Reason clarifies an HTTP
status code but does not override it.
type: string
status:
description: 'Status of the operation. One of: "Success" or
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
type: string
type: object
required:
- pending
type: object
labels:
additionalProperties:
type: string
description: 'Map of string keys and values that can be used to organize
and categorize (scope and select) objects. May match selectors of
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
type: object
managedFields:
description: "ManagedFields maps workflow-id and version to the set
of fields that are managed by that workflow. This is mostly for
internal housekeeping, and users typically shouldn't need to set
or understand this field. A workflow can be the user's name, a controller's
name, or the name of a specific apply path like \"ci-cd\". The set
of fields is always in the version that the workflow used when modifying
the object. \n This field is alpha and can be changed or removed
without notice."
items:
properties:
apiVersion:
description: APIVersion defines the version of this resource
that this field set applies to. The format is "group/version"
just like the top-level APIVersion field. It is necessary
to track the version of a field set because it cannot be automatically
converted.
type: string
fields:
additionalProperties: true
description: Fields identifies a set of fields.
type: object
manager:
description: Manager is an identifier of the workflow managing
these fields.
type: string
operation:
description: Operation is the type of operation which lead to
this ManagedFieldsEntry being created. The only valid values
for this field are 'Apply' and 'Update'.
type: string
time:
description: Time is timestamp of when these fields were set.
It should always be empty if Operation is 'Apply'
format: date-time
type: string
type: object
type: array
name:
description: 'Name must be unique within a namespace. Is required
when creating resources, although some resources may allow a client
to request the generation of an appropriate name automatically.
Name is primarily intended for creation idempotence and configuration
definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
namespace:
description: "Namespace defines the space within each name must be
unique. An empty namespace is equivalent to the \"default\" namespace,
but \"default\" is the canonical representation. Not all objects
are required to be scoped to a namespace - the value of this field
for those objects will be empty. \n Must be a DNS_LABEL. Cannot
be updated. More info: http://kubernetes.io/docs/user-guide/namespaces"
type: string
ownerReferences:
description: List of objects depended by this object. If ALL objects
in the list have been deleted, this object will be garbage collected.
If this object is managed by a controller, then an entry in this
list will point to this controller, with the controller field set
to true. There cannot be more than one managing controller.
items:
properties:
apiVersion:
description: API version of the referent.
type: string
blockOwnerDeletion:
description: If true, AND if the owner has the "foregroundDeletion"
finalizer, then the owner cannot be deleted from the key-value
store until this reference is removed. Defaults to false.
To set this field, a user needs "delete" permission of the
owner, otherwise 422 (Unprocessable Entity) will be returned.
type: boolean
controller:
description: If true, this reference points to the managing
controller.
type: boolean
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
uid:
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
required:
- apiVersion
- kind
- name
- uid
type: object
type: array
resourceVersion:
description: "An opaque value that represents the internal version
of this object that can be used by clients to determine when objects
have changed. May be used for optimistic concurrency, change detection,
and the watch operation on a resource or set of resources. Clients
must treat these values as opaque and passed unmodified back to
the server. They may only be valid for a particular resource or
set of resources. \n Populated by the system. Read-only. Value must
be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency"
type: string
selfLink:
description: SelfLink is a URL representing this object. Populated
by the system. Read-only.
type: string
uid:
description: "UID is the unique in time and space value for this object.
It is typically generated by the server on successful creation of
a resource and is not allowed to change on PUT operations. \n Populated
by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids"
type: string
type: object
spec:
type: object
status:
type: object
type: object
served: true
storage: true
status:
File diff suppressed because it is too large Load Diff
@@ -3,448 +3,95 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: collectorjobs.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: CollectorJob
listKind: CollectorJobList
plural: collectorjobs
scope: ""
singular: collectorjob
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: CollectorJob is the Schema for the collectorjobs 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'
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'
type: string
metadata:
type: object
spec:
description: CollectorJobSpec defines the desired state of CollectorJob
properties:
collector:
properties:
name:
type: string
namespace:
type: string
required:
- name
type: object
image:
type: string
imagePullPolicy:
type: string
redact:
type: boolean
required:
- collector
type: object
status:
description: CollectorJobStatus defines the observed state of CollectorJob
properties:
failed:
items:
type: string
type: array
isServerReady:
type: boolean
running:
items:
type: string
type: array
serverPodName:
type: string
serverPodNamespace:
type: string
serverPodPort:
type: integer
successful:
items:
type: string
type: array
required:
- failed
- isServerReady
- running
- serverPodName
- serverPodNamespace
- serverPodPort
- successful
type: object
type: object
version: v1beta1
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: CollectorJob is the Schema for the collectorjobs 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/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/api-conventions.md#types-kinds'
type: string
metadata:
properties:
annotations:
additionalProperties:
type: string
description: 'Annotations is an unstructured key value map stored
with a resource that may be set by external tools to store and retrieve
arbitrary metadata. They are not queryable and should be preserved
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
type: object
clusterName:
description: The name of the cluster which the object belongs to.
This is used to distinguish resources with same name and namespace
in different clusters. This field is not set anywhere right now
and apiserver is going to ignore it if set in create or update request.
type: string
creationTimestamp:
description: "CreationTimestamp is a timestamp representing the server
time when this object was created. It is not guaranteed to be set
in happens-before order across separate operations. Clients may
not set this value. It is represented in RFC3339 form and is in
UTC. \n Populated by the system. Read-only. Null for lists. More
info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
deletionGracePeriodSeconds:
description: Number of seconds allowed for this object to gracefully
terminate before it will be removed from the system. Only set when
deletionTimestamp is also set. May only be shortened. Read-only.
format: int64
type: integer
deletionTimestamp:
description: "DeletionTimestamp is RFC 3339 date and time at which
this resource will be deleted. This field is set by the server when
a graceful deletion is requested by the user, and is not directly
settable by a client. The resource is expected to be deleted (no
longer visible from resource lists, and not reachable by name) after
the time in this field, once the finalizers list is empty. As long
as the finalizers list contains items, deletion is blocked. Once
the deletionTimestamp is set, this value may not be unset or be
set further into the future, although it may be shortened or the
resource may be deleted prior to this time. For example, a user
may request that a pod is deleted in 30 seconds. The Kubelet will
react by sending a graceful termination signal to the containers
in the pod. After that 30 seconds, the Kubelet will send a hard
termination signal (SIGKILL) to the container and after cleanup,
remove the pod from the API. In the presence of network partitions,
this object may still exist after this timestamp, until an administrator
or automated process can determine the resource is fully terminated.
If not set, graceful deletion of the object has not been requested.
\n Populated by the system when a graceful deletion is requested.
Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
finalizers:
description: Must be empty before the object is deleted from the registry.
Each entry is an identifier for the responsible component that will
remove the entry from the list. If the deletionTimestamp of the
object is non-nil, entries in this list can only be removed.
items:
type: string
type: array
generateName:
description: "GenerateName is an optional prefix, used by the server,
to generate a unique name ONLY IF the Name field has not been provided.
If this field is used, the name returned to the client will be different
than the name passed. This value will also be combined with a unique
suffix. The provided value has the same validation rules as the
Name field, and may be truncated by the length of the suffix required
to make the value unique on the server. \n If this field is specified
and the generated name exists, the server will NOT return a 409
- instead, it will either return 201 Created or 500 with Reason
ServerTimeout indicating a unique name could not be found in the
time allotted, and the client should retry (optionally after the
time indicated in the Retry-After header). \n Applied only if Name
is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency"
type: string
generation:
description: A sequence number representing a specific generation
of the desired state. Populated by the system. Read-only.
format: int64
type: integer
initializers:
description: "An initializer is a controller which enforces some system
invariant at object creation time. This field is a list of initializers
that have not yet acted on this object. If nil or empty, this object
has been completely initialized. Otherwise, the object is considered
uninitialized and is hidden (in list/watch and get calls) from clients
that haven't explicitly asked to observe uninitialized objects.
\n When an object is created, the system will populate this list
with the current set of initializers. Only privileged users may
set or modify this list. Once it is empty, it may not be modified
further by any user. \n DEPRECATED - initializers are an alpha field
and will be removed in v1.15."
properties:
pending:
description: Pending is a list of initializers that must execute
in order before this object is visible. When the last pending
initializer is removed, and no failing result is set, the initializers
struct will be set to nil and the object is considered as initialized
and visible to all clients.
items:
properties:
name:
description: name of the process that is responsible for
initializing this object.
type: string
required:
- name
type: object
type: array
result:
description: If result is set with the Failure field, the object
will be persisted to storage and then deleted, ensuring that
other clients can observe the deletion.
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/api-conventions.md#resources'
type: string
code:
description: Suggested HTTP return code for this status, 0
if not set.
format: int32
type: integer
details:
description: Extended data associated with the reason. Each
reason may define its own extended details. This field is
optional and the data returned is not guaranteed to conform
to any schema except that defined by the reason type.
properties:
causes:
description: The Causes array includes more details associated
with the StatusReason failure. Not all StatusReasons
may provide detailed causes.
items:
properties:
field:
description: "The field of the resource that has
caused this error, as named by its JSON serialization.
May include dot and postfix notation for nested
attributes. Arrays are zero-indexed. Fields may
appear more than once in an array of causes due
to fields having multiple errors. Optional. \n
Examples: \"name\" - the field \"name\" on the
current resource \"items[0].name\" - the field
\"name\" on the first array entry in \"items\""
type: string
message:
description: A human-readable description of the
cause of the error. This field may be presented
as-is to a reader.
type: string
reason:
description: A machine-readable description of the
cause of the error. If this value is empty there
is no information available.
type: string
type: object
type: array
group:
description: The group attribute of the resource associated
with the status StatusReason.
type: string
kind:
description: 'The kind attribute of the resource associated
with the status StatusReason. On some operations may
differ from the requested resource Kind. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: The name attribute of the resource associated
with the status StatusReason (when there is a single
name which can be described).
type: string
retryAfterSeconds:
description: If specified, the time in seconds before
the operation should be retried. Some errors may indicate
the client must take an alternate action - for those
errors this field may indicate how long to wait before
taking the alternate action.
format: int32
type: integer
uid:
description: 'UID of the resource. (when there is a single
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
type: object
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/api-conventions.md#types-kinds'
type: string
message:
description: A human-readable description of the status of
this operation.
type: string
metadata:
description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
properties:
continue:
description: continue may be set if the user set a limit
on the number of items returned, and indicates that
the server has more data available. The value is opaque
and may be used to issue another request to the endpoint
that served this list to retrieve the next set of available
objects. Continuing a consistent list may not be possible
if the server configuration has changed or more than
a few minutes have passed. The resourceVersion field
returned when using this continue value will be identical
to the value in the first response, unless you have
received this token from an error message.
type: string
resourceVersion:
description: 'String that identifies the server''s internal
version of this object that can be used by clients to
determine when objects have changed. Value must be treated
as opaque by clients and passed unmodified back to the
server. Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
type: string
selfLink:
description: selfLink is a URL representing this object.
Populated by the system. Read-only.
type: string
type: object
reason:
description: A machine-readable description of why this operation
is in the "Failure" status. If this value is empty there
is no information available. A Reason clarifies an HTTP
status code but does not override it.
type: string
status:
description: 'Status of the operation. One of: "Success" or
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
type: string
type: object
required:
- pending
type: object
labels:
additionalProperties:
type: string
description: 'Map of string keys and values that can be used to organize
and categorize (scope and select) objects. May match selectors of
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
type: object
managedFields:
description: "ManagedFields maps workflow-id and version to the set
of fields that are managed by that workflow. This is mostly for
internal housekeeping, and users typically shouldn't need to set
or understand this field. A workflow can be the user's name, a controller's
name, or the name of a specific apply path like \"ci-cd\". The set
of fields is always in the version that the workflow used when modifying
the object. \n This field is alpha and can be changed or removed
without notice."
items:
properties:
apiVersion:
description: APIVersion defines the version of this resource
that this field set applies to. The format is "group/version"
just like the top-level APIVersion field. It is necessary
to track the version of a field set because it cannot be automatically
converted.
type: string
fields:
additionalProperties: true
description: Fields identifies a set of fields.
type: object
manager:
description: Manager is an identifier of the workflow managing
these fields.
type: string
operation:
description: Operation is the type of operation which lead to
this ManagedFieldsEntry being created. The only valid values
for this field are 'Apply' and 'Update'.
type: string
time:
description: Time is timestamp of when these fields were set.
It should always be empty if Operation is 'Apply'
format: date-time
type: string
type: object
type: array
name:
description: 'Name must be unique within a namespace. Is required
when creating resources, although some resources may allow a client
to request the generation of an appropriate name automatically.
Name is primarily intended for creation idempotence and configuration
definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
namespace:
description: "Namespace defines the space within each name must be
unique. An empty namespace is equivalent to the \"default\" namespace,
but \"default\" is the canonical representation. Not all objects
are required to be scoped to a namespace - the value of this field
for those objects will be empty. \n Must be a DNS_LABEL. Cannot
be updated. More info: http://kubernetes.io/docs/user-guide/namespaces"
type: string
ownerReferences:
description: List of objects depended by this object. If ALL objects
in the list have been deleted, this object will be garbage collected.
If this object is managed by a controller, then an entry in this
list will point to this controller, with the controller field set
to true. There cannot be more than one managing controller.
items:
properties:
apiVersion:
description: API version of the referent.
type: string
blockOwnerDeletion:
description: If true, AND if the owner has the "foregroundDeletion"
finalizer, then the owner cannot be deleted from the key-value
store until this reference is removed. Defaults to false.
To set this field, a user needs "delete" permission of the
owner, otherwise 422 (Unprocessable Entity) will be returned.
type: boolean
controller:
description: If true, this reference points to the managing
controller.
type: boolean
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
uid:
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
required:
- apiVersion
- kind
- name
- uid
type: object
type: array
resourceVersion:
description: "An opaque value that represents the internal version
of this object that can be used by clients to determine when objects
have changed. May be used for optimistic concurrency, change detection,
and the watch operation on a resource or set of resources. Clients
must treat these values as opaque and passed unmodified back to
the server. They may only be valid for a particular resource or
set of resources. \n Populated by the system. Read-only. Value must
be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency"
type: string
selfLink:
description: SelfLink is a URL representing this object. Populated
by the system. Read-only.
type: string
uid:
description: "UID is the unique in time and space value for this object.
It is typically generated by the server on successful creation of
a resource and is not allowed to change on PUT operations. \n Populated
by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids"
type: string
type: object
spec:
properties:
collector:
properties:
name:
type: string
namespace:
type: string
required:
- name
type: object
image:
type: string
imagePullPolicy:
type: string
redact:
type: boolean
required:
- collector
type: object
status:
properties:
failed:
items:
type: string
type: array
isServerReady:
type: boolean
running:
items:
type: string
type: array
serverPodName:
type: string
serverPodNamespace:
type: string
serverPodPort:
type: integer
successful:
items:
type: string
type: array
required:
- isServerReady
- serverPodName
- serverPodNamespace
- serverPodPort
- running
- successful
- failed
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
@@ -1,16 +1,20 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: collectors.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: Collector
listKind: CollectorList
plural: collectors
scope: ""
singular: collector
scope: Namespaced
versions:
- name: v1beta1
schema:
@@ -20,376 +24,17 @@ spec:
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/api-conventions.md#resources'
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/api-conventions.md#types-kinds'
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:
properties:
annotations:
additionalProperties:
type: string
description: 'Annotations is an unstructured key value map stored
with a resource that may be set by external tools to store and retrieve
arbitrary metadata. They are not queryable and should be preserved
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
type: object
clusterName:
description: The name of the cluster which the object belongs to.
This is used to distinguish resources with same name and namespace
in different clusters. This field is not set anywhere right now
and apiserver is going to ignore it if set in create or update request.
type: string
creationTimestamp:
description: "CreationTimestamp is a timestamp representing the server
time when this object was created. It is not guaranteed to be set
in happens-before order across separate operations. Clients may
not set this value. It is represented in RFC3339 form and is in
UTC. \n Populated by the system. Read-only. Null for lists. More
info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
deletionGracePeriodSeconds:
description: Number of seconds allowed for this object to gracefully
terminate before it will be removed from the system. Only set when
deletionTimestamp is also set. May only be shortened. Read-only.
format: int64
type: integer
deletionTimestamp:
description: "DeletionTimestamp is RFC 3339 date and time at which
this resource will be deleted. This field is set by the server when
a graceful deletion is requested by the user, and is not directly
settable by a client. The resource is expected to be deleted (no
longer visible from resource lists, and not reachable by name) after
the time in this field, once the finalizers list is empty. As long
as the finalizers list contains items, deletion is blocked. Once
the deletionTimestamp is set, this value may not be unset or be
set further into the future, although it may be shortened or the
resource may be deleted prior to this time. For example, a user
may request that a pod is deleted in 30 seconds. The Kubelet will
react by sending a graceful termination signal to the containers
in the pod. After that 30 seconds, the Kubelet will send a hard
termination signal (SIGKILL) to the container and after cleanup,
remove the pod from the API. In the presence of network partitions,
this object may still exist after this timestamp, until an administrator
or automated process can determine the resource is fully terminated.
If not set, graceful deletion of the object has not been requested.
\n Populated by the system when a graceful deletion is requested.
Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
finalizers:
description: Must be empty before the object is deleted from the registry.
Each entry is an identifier for the responsible component that will
remove the entry from the list. If the deletionTimestamp of the
object is non-nil, entries in this list can only be removed.
items:
type: string
type: array
generateName:
description: "GenerateName is an optional prefix, used by the server,
to generate a unique name ONLY IF the Name field has not been provided.
If this field is used, the name returned to the client will be different
than the name passed. This value will also be combined with a unique
suffix. The provided value has the same validation rules as the
Name field, and may be truncated by the length of the suffix required
to make the value unique on the server. \n If this field is specified
and the generated name exists, the server will NOT return a 409
- instead, it will either return 201 Created or 500 with Reason
ServerTimeout indicating a unique name could not be found in the
time allotted, and the client should retry (optionally after the
time indicated in the Retry-After header). \n Applied only if Name
is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency"
type: string
generation:
description: A sequence number representing a specific generation
of the desired state. Populated by the system. Read-only.
format: int64
type: integer
initializers:
description: "An initializer is a controller which enforces some system
invariant at object creation time. This field is a list of initializers
that have not yet acted on this object. If nil or empty, this object
has been completely initialized. Otherwise, the object is considered
uninitialized and is hidden (in list/watch and get calls) from clients
that haven't explicitly asked to observe uninitialized objects.
\n When an object is created, the system will populate this list
with the current set of initializers. Only privileged users may
set or modify this list. Once it is empty, it may not be modified
further by any user. \n DEPRECATED - initializers are an alpha field
and will be removed in v1.15."
properties:
pending:
description: Pending is a list of initializers that must execute
in order before this object is visible. When the last pending
initializer is removed, and no failing result is set, the initializers
struct will be set to nil and the object is considered as initialized
and visible to all clients.
items:
properties:
name:
description: name of the process that is responsible for
initializing this object.
type: string
required:
- name
type: object
type: array
result:
description: If result is set with the Failure field, the object
will be persisted to storage and then deleted, ensuring that
other clients can observe the deletion.
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/api-conventions.md#resources'
type: string
code:
description: Suggested HTTP return code for this status, 0
if not set.
format: int32
type: integer
details:
description: Extended data associated with the reason. Each
reason may define its own extended details. This field is
optional and the data returned is not guaranteed to conform
to any schema except that defined by the reason type.
properties:
causes:
description: The Causes array includes more details associated
with the StatusReason failure. Not all StatusReasons
may provide detailed causes.
items:
properties:
field:
description: "The field of the resource that has
caused this error, as named by its JSON serialization.
May include dot and postfix notation for nested
attributes. Arrays are zero-indexed. Fields may
appear more than once in an array of causes due
to fields having multiple errors. Optional. \n
Examples: \"name\" - the field \"name\" on the
current resource \"items[0].name\" - the field
\"name\" on the first array entry in \"items\""
type: string
message:
description: A human-readable description of the
cause of the error. This field may be presented
as-is to a reader.
type: string
reason:
description: A machine-readable description of the
cause of the error. If this value is empty there
is no information available.
type: string
type: object
type: array
group:
description: The group attribute of the resource associated
with the status StatusReason.
type: string
kind:
description: 'The kind attribute of the resource associated
with the status StatusReason. On some operations may
differ from the requested resource Kind. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: The name attribute of the resource associated
with the status StatusReason (when there is a single
name which can be described).
type: string
retryAfterSeconds:
description: If specified, the time in seconds before
the operation should be retried. Some errors may indicate
the client must take an alternate action - for those
errors this field may indicate how long to wait before
taking the alternate action.
format: int32
type: integer
uid:
description: 'UID of the resource. (when there is a single
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
type: object
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/api-conventions.md#types-kinds'
type: string
message:
description: A human-readable description of the status of
this operation.
type: string
metadata:
description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
properties:
continue:
description: continue may be set if the user set a limit
on the number of items returned, and indicates that
the server has more data available. The value is opaque
and may be used to issue another request to the endpoint
that served this list to retrieve the next set of available
objects. Continuing a consistent list may not be possible
if the server configuration has changed or more than
a few minutes have passed. The resourceVersion field
returned when using this continue value will be identical
to the value in the first response, unless you have
received this token from an error message.
type: string
resourceVersion:
description: 'String that identifies the server''s internal
version of this object that can be used by clients to
determine when objects have changed. Value must be treated
as opaque by clients and passed unmodified back to the
server. Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
type: string
selfLink:
description: selfLink is a URL representing this object.
Populated by the system. Read-only.
type: string
type: object
reason:
description: A machine-readable description of why this operation
is in the "Failure" status. If this value is empty there
is no information available. A Reason clarifies an HTTP
status code but does not override it.
type: string
status:
description: 'Status of the operation. One of: "Success" or
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
type: string
type: object
required:
- pending
type: object
labels:
additionalProperties:
type: string
description: 'Map of string keys and values that can be used to organize
and categorize (scope and select) objects. May match selectors of
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
type: object
managedFields:
description: "ManagedFields maps workflow-id and version to the set
of fields that are managed by that workflow. This is mostly for
internal housekeeping, and users typically shouldn't need to set
or understand this field. A workflow can be the user's name, a controller's
name, or the name of a specific apply path like \"ci-cd\". The set
of fields is always in the version that the workflow used when modifying
the object. \n This field is alpha and can be changed or removed
without notice."
items:
properties:
apiVersion:
description: APIVersion defines the version of this resource
that this field set applies to. The format is "group/version"
just like the top-level APIVersion field. It is necessary
to track the version of a field set because it cannot be automatically
converted.
type: string
fields:
additionalProperties: true
description: Fields identifies a set of fields.
type: object
manager:
description: Manager is an identifier of the workflow managing
these fields.
type: string
operation:
description: Operation is the type of operation which lead to
this ManagedFieldsEntry being created. The only valid values
for this field are 'Apply' and 'Update'.
type: string
time:
description: Time is timestamp of when these fields were set.
It should always be empty if Operation is 'Apply'
format: date-time
type: string
type: object
type: array
name:
description: 'Name must be unique within a namespace. Is required
when creating resources, although some resources may allow a client
to request the generation of an appropriate name automatically.
Name is primarily intended for creation idempotence and configuration
definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
namespace:
description: "Namespace defines the space within each name must be
unique. An empty namespace is equivalent to the \"default\" namespace,
but \"default\" is the canonical representation. Not all objects
are required to be scoped to a namespace - the value of this field
for those objects will be empty. \n Must be a DNS_LABEL. Cannot
be updated. More info: http://kubernetes.io/docs/user-guide/namespaces"
type: string
ownerReferences:
description: List of objects depended by this object. If ALL objects
in the list have been deleted, this object will be garbage collected.
If this object is managed by a controller, then an entry in this
list will point to this controller, with the controller field set
to true. There cannot be more than one managing controller.
items:
properties:
apiVersion:
description: API version of the referent.
type: string
blockOwnerDeletion:
description: If true, AND if the owner has the "foregroundDeletion"
finalizer, then the owner cannot be deleted from the key-value
store until this reference is removed. Defaults to false.
To set this field, a user needs "delete" permission of the
owner, otherwise 422 (Unprocessable Entity) will be returned.
type: boolean
controller:
description: If true, this reference points to the managing
controller.
type: boolean
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
uid:
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
required:
- apiVersion
- kind
- name
- uid
type: object
type: array
resourceVersion:
description: "An opaque value that represents the internal version
of this object that can be used by clients to determine when objects
have changed. May be used for optimistic concurrency, change detection,
and the watch operation on a resource or set of resources. Clients
must treat these values as opaque and passed unmodified back to
the server. They may only be valid for a particular resource or
set of resources. \n Populated by the system. Read-only. Value must
be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency"
type: string
selfLink:
description: SelfLink is a URL representing this object. Populated
by the system. Read-only.
type: string
uid:
description: "UID is the unique in time and space value for this object.
It is typically generated by the server on successful creation of
a resource and is not allowed to change on PUT operations. \n Populated
by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids"
type: string
type: object
spec:
description: CollectorSpec defines the desired state of Collector
properties:
afterCollection:
items:
@@ -398,21 +43,27 @@ spec:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- uri
- method
- redactUri
- uri
type: object
uploadResultsTo:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- uri
- method
- redactUri
- uri
type: object
type: object
type: array
@@ -420,8 +71,18 @@ spec:
items:
properties:
clusterInfo:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
clusterResources:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
copy:
properties:
@@ -431,6 +92,10 @@ spec:
type: string
containerPath:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
selector:
@@ -438,9 +103,22 @@ spec:
type: string
type: array
required:
- selector
- namespace
- containerPath
- namespace
- selector
type: object
data:
properties:
collectorName:
type: string
data:
type: string
exclude:
type: BoolString
name:
type: string
required:
- data
type: object
exec:
properties:
@@ -456,6 +134,10 @@ spec:
type: array
containerName:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
selector:
@@ -465,13 +147,15 @@ spec:
timeout:
type: string
required:
- selector
- namespace
- selector
type: object
http:
properties:
collectorName:
type: string
exclude:
type: BoolString
get:
properties:
headers:
@@ -485,6 +169,8 @@ spec:
required:
- url
type: object
name:
type: string
post:
properties:
body:
@@ -520,6 +206,12 @@ spec:
properties:
collectorName:
type: string
containerNames:
items:
type: string
type: array
exclude:
type: BoolString
limits:
properties:
maxAge:
@@ -528,6 +220,8 @@ spec:
format: int64
type: integer
type: object
name:
type: string
namespace:
type: string
selector:
@@ -537,6 +231,39 @@ spec:
required:
- selector
type: object
mysql:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
postgres:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
redis:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
run:
properties:
args:
@@ -549,22 +276,39 @@ spec:
items:
type: string
type: array
exclude:
type: BoolString
image:
type: string
imagePullPolicy:
type: string
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
name:
type: string
namespace:
type: string
timeout:
type: string
required:
- namespace
- image
- namespace
type: object
secret:
properties:
collectorName:
type: string
exclude:
type: BoolString
includeValue:
type: boolean
key:
@@ -580,6 +324,7 @@ spec:
type: array
type: object
status:
description: CollectorStatus defines the observed state of Collector
type: object
type: object
served: true
@@ -3,468 +3,115 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: preflightjobs.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: PreflightJob
listKind: PreflightJobList
plural: preflightjobs
scope: ""
singular: preflightjob
scope: Namespaced
subresources:
status: {}
validation:
openAPIV3Schema:
description: PreflightJob is the Schema for the preflightjobs 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'
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'
type: string
metadata:
type: object
spec:
description: PreflightJobSpec defines the desired state of PreflightJob
properties:
collectorImage:
type: string
collectorImagePullPolicy:
type: string
imagePullPolicy:
type: string
preflight:
properties:
name:
type: string
namespace:
type: string
required:
- name
type: object
preflightImage:
type: string
required:
- preflight
type: object
status:
description: PreflightJobStatus defines the observed state of PreflightJob
properties:
analyzersFailed:
items:
type: string
type: array
analyzersRunning:
items:
type: string
type: array
analyzersSuccessful:
items:
type: string
type: array
collectorsFailed:
items:
type: string
type: array
collectorsRunning:
items:
type: string
type: array
collectorsSuccessful:
items:
type: string
type: array
isAnalyzersComplete:
type: boolean
isServerReady:
type: boolean
serverPodName:
type: string
serverPodNamespace:
type: string
serverPodPort:
type: integer
required:
- analyzersFailed
- analyzersRunning
- analyzersSuccessful
- collectorsFailed
- collectorsRunning
- collectorsSuccessful
- isAnalyzersComplete
- isServerReady
- serverPodName
- serverPodNamespace
- serverPodPort
type: object
type: object
version: v1beta1
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: PreflightJob is the Schema for the preflightjobs 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/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/api-conventions.md#types-kinds'
type: string
metadata:
properties:
annotations:
additionalProperties:
type: string
description: 'Annotations is an unstructured key value map stored
with a resource that may be set by external tools to store and retrieve
arbitrary metadata. They are not queryable and should be preserved
when modifying objects. More info: http://kubernetes.io/docs/user-guide/annotations'
type: object
clusterName:
description: The name of the cluster which the object belongs to.
This is used to distinguish resources with same name and namespace
in different clusters. This field is not set anywhere right now
and apiserver is going to ignore it if set in create or update request.
type: string
creationTimestamp:
description: "CreationTimestamp is a timestamp representing the server
time when this object was created. It is not guaranteed to be set
in happens-before order across separate operations. Clients may
not set this value. It is represented in RFC3339 form and is in
UTC. \n Populated by the system. Read-only. Null for lists. More
info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
deletionGracePeriodSeconds:
description: Number of seconds allowed for this object to gracefully
terminate before it will be removed from the system. Only set when
deletionTimestamp is also set. May only be shortened. Read-only.
format: int64
type: integer
deletionTimestamp:
description: "DeletionTimestamp is RFC 3339 date and time at which
this resource will be deleted. This field is set by the server when
a graceful deletion is requested by the user, and is not directly
settable by a client. The resource is expected to be deleted (no
longer visible from resource lists, and not reachable by name) after
the time in this field, once the finalizers list is empty. As long
as the finalizers list contains items, deletion is blocked. Once
the deletionTimestamp is set, this value may not be unset or be
set further into the future, although it may be shortened or the
resource may be deleted prior to this time. For example, a user
may request that a pod is deleted in 30 seconds. The Kubelet will
react by sending a graceful termination signal to the containers
in the pod. After that 30 seconds, the Kubelet will send a hard
termination signal (SIGKILL) to the container and after cleanup,
remove the pod from the API. In the presence of network partitions,
this object may still exist after this timestamp, until an administrator
or automated process can determine the resource is fully terminated.
If not set, graceful deletion of the object has not been requested.
\n Populated by the system when a graceful deletion is requested.
Read-only. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata"
format: date-time
type: string
finalizers:
description: Must be empty before the object is deleted from the registry.
Each entry is an identifier for the responsible component that will
remove the entry from the list. If the deletionTimestamp of the
object is non-nil, entries in this list can only be removed.
items:
type: string
type: array
generateName:
description: "GenerateName is an optional prefix, used by the server,
to generate a unique name ONLY IF the Name field has not been provided.
If this field is used, the name returned to the client will be different
than the name passed. This value will also be combined with a unique
suffix. The provided value has the same validation rules as the
Name field, and may be truncated by the length of the suffix required
to make the value unique on the server. \n If this field is specified
and the generated name exists, the server will NOT return a 409
- instead, it will either return 201 Created or 500 with Reason
ServerTimeout indicating a unique name could not be found in the
time allotted, and the client should retry (optionally after the
time indicated in the Retry-After header). \n Applied only if Name
is not specified. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#idempotency"
type: string
generation:
description: A sequence number representing a specific generation
of the desired state. Populated by the system. Read-only.
format: int64
type: integer
initializers:
description: "An initializer is a controller which enforces some system
invariant at object creation time. This field is a list of initializers
that have not yet acted on this object. If nil or empty, this object
has been completely initialized. Otherwise, the object is considered
uninitialized and is hidden (in list/watch and get calls) from clients
that haven't explicitly asked to observe uninitialized objects.
\n When an object is created, the system will populate this list
with the current set of initializers. Only privileged users may
set or modify this list. Once it is empty, it may not be modified
further by any user. \n DEPRECATED - initializers are an alpha field
and will be removed in v1.15."
properties:
pending:
description: Pending is a list of initializers that must execute
in order before this object is visible. When the last pending
initializer is removed, and no failing result is set, the initializers
struct will be set to nil and the object is considered as initialized
and visible to all clients.
items:
properties:
name:
description: name of the process that is responsible for
initializing this object.
type: string
required:
- name
type: object
type: array
result:
description: If result is set with the Failure field, the object
will be persisted to storage and then deleted, ensuring that
other clients can observe the deletion.
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/api-conventions.md#resources'
type: string
code:
description: Suggested HTTP return code for this status, 0
if not set.
format: int32
type: integer
details:
description: Extended data associated with the reason. Each
reason may define its own extended details. This field is
optional and the data returned is not guaranteed to conform
to any schema except that defined by the reason type.
properties:
causes:
description: The Causes array includes more details associated
with the StatusReason failure. Not all StatusReasons
may provide detailed causes.
items:
properties:
field:
description: "The field of the resource that has
caused this error, as named by its JSON serialization.
May include dot and postfix notation for nested
attributes. Arrays are zero-indexed. Fields may
appear more than once in an array of causes due
to fields having multiple errors. Optional. \n
Examples: \"name\" - the field \"name\" on the
current resource \"items[0].name\" - the field
\"name\" on the first array entry in \"items\""
type: string
message:
description: A human-readable description of the
cause of the error. This field may be presented
as-is to a reader.
type: string
reason:
description: A machine-readable description of the
cause of the error. If this value is empty there
is no information available.
type: string
type: object
type: array
group:
description: The group attribute of the resource associated
with the status StatusReason.
type: string
kind:
description: 'The kind attribute of the resource associated
with the status StatusReason. On some operations may
differ from the requested resource Kind. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: The name attribute of the resource associated
with the status StatusReason (when there is a single
name which can be described).
type: string
retryAfterSeconds:
description: If specified, the time in seconds before
the operation should be retried. Some errors may indicate
the client must take an alternate action - for those
errors this field may indicate how long to wait before
taking the alternate action.
format: int32
type: integer
uid:
description: 'UID of the resource. (when there is a single
resource which can be described). More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
type: object
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/api-conventions.md#types-kinds'
type: string
message:
description: A human-readable description of the status of
this operation.
type: string
metadata:
description: 'Standard list metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
properties:
continue:
description: continue may be set if the user set a limit
on the number of items returned, and indicates that
the server has more data available. The value is opaque
and may be used to issue another request to the endpoint
that served this list to retrieve the next set of available
objects. Continuing a consistent list may not be possible
if the server configuration has changed or more than
a few minutes have passed. The resourceVersion field
returned when using this continue value will be identical
to the value in the first response, unless you have
received this token from an error message.
type: string
resourceVersion:
description: 'String that identifies the server''s internal
version of this object that can be used by clients to
determine when objects have changed. Value must be treated
as opaque by clients and passed unmodified back to the
server. Populated by the system. Read-only. More info:
https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency'
type: string
selfLink:
description: selfLink is a URL representing this object.
Populated by the system. Read-only.
type: string
type: object
reason:
description: A machine-readable description of why this operation
is in the "Failure" status. If this value is empty there
is no information available. A Reason clarifies an HTTP
status code but does not override it.
type: string
status:
description: 'Status of the operation. One of: "Success" or
"Failure". More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#spec-and-status'
type: string
type: object
required:
- pending
type: object
labels:
additionalProperties:
type: string
description: 'Map of string keys and values that can be used to organize
and categorize (scope and select) objects. May match selectors of
replication controllers and services. More info: http://kubernetes.io/docs/user-guide/labels'
type: object
managedFields:
description: "ManagedFields maps workflow-id and version to the set
of fields that are managed by that workflow. This is mostly for
internal housekeeping, and users typically shouldn't need to set
or understand this field. A workflow can be the user's name, a controller's
name, or the name of a specific apply path like \"ci-cd\". The set
of fields is always in the version that the workflow used when modifying
the object. \n This field is alpha and can be changed or removed
without notice."
items:
properties:
apiVersion:
description: APIVersion defines the version of this resource
that this field set applies to. The format is "group/version"
just like the top-level APIVersion field. It is necessary
to track the version of a field set because it cannot be automatically
converted.
type: string
fields:
additionalProperties: true
description: Fields identifies a set of fields.
type: object
manager:
description: Manager is an identifier of the workflow managing
these fields.
type: string
operation:
description: Operation is the type of operation which lead to
this ManagedFieldsEntry being created. The only valid values
for this field are 'Apply' and 'Update'.
type: string
time:
description: Time is timestamp of when these fields were set.
It should always be empty if Operation is 'Apply'
format: date-time
type: string
type: object
type: array
name:
description: 'Name must be unique within a namespace. Is required
when creating resources, although some resources may allow a client
to request the generation of an appropriate name automatically.
Name is primarily intended for creation idempotence and configuration
definition. Cannot be updated. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
namespace:
description: "Namespace defines the space within each name must be
unique. An empty namespace is equivalent to the \"default\" namespace,
but \"default\" is the canonical representation. Not all objects
are required to be scoped to a namespace - the value of this field
for those objects will be empty. \n Must be a DNS_LABEL. Cannot
be updated. More info: http://kubernetes.io/docs/user-guide/namespaces"
type: string
ownerReferences:
description: List of objects depended by this object. If ALL objects
in the list have been deleted, this object will be garbage collected.
If this object is managed by a controller, then an entry in this
list will point to this controller, with the controller field set
to true. There cannot be more than one managing controller.
items:
properties:
apiVersion:
description: API version of the referent.
type: string
blockOwnerDeletion:
description: If true, AND if the owner has the "foregroundDeletion"
finalizer, then the owner cannot be deleted from the key-value
store until this reference is removed. Defaults to false.
To set this field, a user needs "delete" permission of the
owner, otherwise 422 (Unprocessable Entity) will be returned.
type: boolean
controller:
description: If true, this reference points to the managing
controller.
type: boolean
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#names'
type: string
uid:
description: 'UID of the referent. More info: http://kubernetes.io/docs/user-guide/identifiers#uids'
type: string
required:
- apiVersion
- kind
- name
- uid
type: object
type: array
resourceVersion:
description: "An opaque value that represents the internal version
of this object that can be used by clients to determine when objects
have changed. May be used for optimistic concurrency, change detection,
and the watch operation on a resource or set of resources. Clients
must treat these values as opaque and passed unmodified back to
the server. They may only be valid for a particular resource or
set of resources. \n Populated by the system. Read-only. Value must
be treated as opaque by clients and . More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency"
type: string
selfLink:
description: SelfLink is a URL representing this object. Populated
by the system. Read-only.
type: string
uid:
description: "UID is the unique in time and space value for this object.
It is typically generated by the server on successful creation of
a resource and is not allowed to change on PUT operations. \n Populated
by the system. Read-only. More info: http://kubernetes.io/docs/user-guide/identifiers#uids"
type: string
type: object
spec:
properties:
collectorImage:
type: string
collectorImagePullPolicy:
type: string
imagePullPolicy:
type: string
preflight:
properties:
name:
type: string
namespace:
type: string
required:
- name
type: object
preflightImage:
type: string
required:
- preflight
type: object
status:
properties:
analyzersFailed:
items:
type: string
type: array
analyzersRunning:
items:
type: string
type: array
analyzersSuccessful:
items:
type: string
type: array
collectorsFailed:
items:
type: string
type: array
collectorsRunning:
items:
type: string
type: array
collectorsSuccessful:
items:
type: string
type: array
isAnalyzersComplete:
type: boolean
isServerReady:
type: boolean
serverPodName:
type: string
serverPodNamespace:
type: string
serverPodPort:
type: integer
required:
- isServerReady
- serverPodName
- serverPodNamespace
- serverPodPort
- collectorsRunning
- collectorsSuccessful
- collectorsFailed
- isAnalyzersComplete
- analyzersRunning
- analyzersSuccessful
- analyzersFailed
type: object
type: object
served: true
storage: true
subresources:
status: {}
status:
acceptedNames:
kind: ""
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: redactors.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: Redactor
listKind: RedactorList
plural: redactors
singular: redactor
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
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'
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'
type: string
metadata:
type: object
spec:
description: RedactorSpec defines the desired state of Redactor
properties:
redactors:
items:
properties:
fileSelector:
properties:
file:
type: string
files:
items:
type: string
type: array
type: object
name:
type: string
removals:
properties:
regex:
items:
properties:
redactor:
type: string
selector:
type: string
type: object
type: array
values:
items:
type: string
type: array
yamlPath:
items:
type: string
type: array
type: object
type: object
type: array
type: object
status:
description: RedactorStatus defines the observed state of Redactor
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+521
View File
@@ -0,0 +1,521 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: collectors.troubleshoot.sh
spec:
group: troubleshoot.sh
names:
kind: Collector
listKind: CollectorList
plural: collectors
singular: collector
scope: Namespaced
versions:
- name: v1beta2
schema:
openAPIV3Schema:
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'
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'
type: string
metadata:
type: object
spec:
description: CollectorSpec defines the desired state of Collector
properties:
afterCollection:
items:
properties:
callback:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- method
- redactUri
- uri
type: object
uploadResultsTo:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- method
- redactUri
- uri
type: object
type: object
type: array
collectors:
items:
properties:
ceph:
properties:
collectorName:
type: string
exclude:
type: BoolString
namespace:
type: string
timeout:
type: string
required:
- namespace
type: object
clusterInfo:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
clusterResources:
properties:
collectorName:
type: string
exclude:
type: BoolString
namespaces:
items:
type: string
type: array
type: object
collectd:
properties:
collectorName:
type: string
exclude:
type: BoolString
hostPath:
type: string
image:
type: string
imagePullPolicy:
type: string
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
namespace:
type: string
timeout:
type: string
required:
- hostPath
- image
- namespace
type: object
configMap:
properties:
collectorName:
type: string
exclude:
type: BoolString
includeAllData:
type: boolean
includeValue:
type: boolean
key:
type: string
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
type: object
copy:
properties:
collectorName:
type: string
containerName:
type: string
containerPath:
type: string
exclude:
type: BoolString
extractArchive:
type: boolean
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
required:
- containerPath
- namespace
- selector
type: object
copyFromHost:
properties:
collectorName:
type: string
exclude:
type: BoolString
extractArchive:
type: boolean
hostPath:
type: string
image:
type: string
imagePullPolicy:
type: string
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
name:
type: string
namespace:
type: string
timeout:
type: string
required:
- hostPath
- image
- namespace
type: object
data:
properties:
collectorName:
type: string
data:
type: string
exclude:
type: BoolString
name:
type: string
required:
- data
type: object
exec:
properties:
args:
items:
type: string
type: array
collectorName:
type: string
command:
items:
type: string
type: array
containerName:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
timeout:
type: string
required:
- namespace
- selector
type: object
http:
properties:
collectorName:
type: string
exclude:
type: BoolString
get:
properties:
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
name:
type: string
post:
properties:
body:
type: string
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
put:
properties:
body:
type: string
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
type: object
logs:
properties:
collectorName:
type: string
containerNames:
items:
type: string
type: array
exclude:
type: BoolString
limits:
properties:
maxAge:
type: string
maxLines:
format: int64
type: integer
sinceTime:
format: date-time
type: string
type: object
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
required:
- selector
type: object
longhorn:
properties:
collectorName:
type: string
exclude:
type: BoolString
namespace:
type: string
timeout:
type: string
required:
- namespace
type: object
mysql:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
postgres:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
redis:
properties:
collectorName:
type: string
exclude:
type: BoolString
uri:
type: string
required:
- uri
type: object
registryImages:
properties:
collectorName:
type: string
exclude:
type: BoolString
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
images:
items:
type: string
type: array
namespace:
type: string
required:
- images
- namespace
type: object
run:
properties:
args:
items:
type: string
type: array
collectorName:
type: string
command:
items:
type: string
type: array
exclude:
type: BoolString
image:
type: string
imagePullPolicy:
type: string
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
name:
type: string
namespace:
type: string
timeout:
type: string
required:
- image
- namespace
type: object
secret:
properties:
collectorName:
type: string
exclude:
type: BoolString
includeValue:
type: boolean
key:
type: string
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
type: object
sysctl:
properties:
collectorName:
type: string
exclude:
type: BoolString
image:
type: string
imagePullPolicy:
type: string
imagePullSecret:
properties:
data:
additionalProperties:
type: string
type: object
name:
type: string
type:
type: string
type: object
name:
type: string
namespace:
type: string
timeout:
type: string
required:
- image
- namespace
type: object
type: object
type: array
type: object
status:
description: CollectorStatus defines the observed state of Collector
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,87 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: redactors.troubleshoot.sh
spec:
group: troubleshoot.sh
names:
kind: Redactor
listKind: RedactorList
plural: redactors
singular: redactor
scope: Namespaced
versions:
- name: v1beta2
schema:
openAPIV3Schema:
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'
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'
type: string
metadata:
type: object
spec:
description: RedactorSpec defines the desired state of Redactor
properties:
redactors:
items:
properties:
fileSelector:
properties:
file:
type: string
files:
items:
type: string
type: array
type: object
name:
type: string
removals:
properties:
regex:
items:
properties:
redactor:
type: string
selector:
type: string
type: object
type: array
values:
items:
type: string
type: array
yamlPath:
items:
type: string
type: array
type: object
type: object
type: array
type: object
status:
description: RedactorStatus defines the observed state of Redactor
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -0,0 +1,361 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: remotecollectors.troubleshoot.sh
spec:
group: troubleshoot.sh
names:
kind: RemoteCollector
listKind: RemoteCollectorList
plural: remotecollectors
singular: remotecollector
scope: Namespaced
versions:
- name: v1beta2
schema:
openAPIV3Schema:
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'
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'
type: string
metadata:
type: object
spec:
description: RemoteCollectorSpec defines the desired state of the RemoteCollector
properties:
afterCollection:
items:
properties:
callback:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- method
- redactUri
- uri
type: object
uploadResultsTo:
properties:
method:
type: string
redactUri:
type: string
uri:
type: string
required:
- method
- redactUri
- uri
type: object
type: object
type: array
collectors:
items:
properties:
blockDevices:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
certificate:
properties:
certificatePath:
type: string
collectorName:
type: string
exclude:
type: BoolString
keyPath:
type: string
required:
- certificatePath
- keyPath
type: object
cpu:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
diskUsage:
properties:
collectorName:
type: string
exclude:
type: BoolString
path:
type: string
required:
- 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.
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.
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.
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.
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.'
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.
type: boolean
directory:
description: The directory where the benchmark will create
files.
type: string
enableBackgroundIOPS:
description: Enable the background IOPS feature.
type: boolean
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.
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.
format: int64
type: integer
sync:
description: Whether to call sync on the file after each
write. Does not apply to background IOPS task.
type: boolean
timeout:
description: Total timeout, including background IOPS setup
and warmup if enabled.
type: string
required:
- backgroundIOPSWarmupSeconds
- backgroundReadIOPS
- backgroundReadIOPSJobs
- backgroundWriteIOPS
- backgroundWriteIOPSJobs
- enableBackgroundIOPS
type: object
hostServices:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
http:
properties:
collectorName:
type: string
exclude:
type: BoolString
get:
properties:
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
post:
properties:
body:
type: string
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
put:
properties:
body:
type: string
headers:
additionalProperties:
type: string
type: object
insecureSkipVerify:
type: boolean
url:
type: string
required:
- url
type: object
type: object
httpLoadBalancer:
properties:
address:
type: string
collectorName:
type: string
exclude:
type: BoolString
path:
type: string
port:
type: integer
timeout:
type: string
required:
- address
- path
- port
type: object
ipv4Interfaces:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
kernelModules:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
memory:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
systemPackages:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
tcpConnect:
properties:
address:
type: string
collectorName:
type: string
exclude:
type: BoolString
timeout:
type: string
required:
- address
type: object
tcpLoadBalancer:
properties:
address:
type: string
collectorName:
type: string
exclude:
type: BoolString
port:
type: integer
timeout:
type: string
required:
- address
- port
type: object
tcpPortStatus:
properties:
collectorName:
type: string
exclude:
type: BoolString
interface:
type: string
port:
type: integer
required:
- port
type: object
time:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
type: object
type: array
nodeSelector:
additionalProperties:
type: string
type: object
type: object
status:
description: CollectorStatus defines the observed state of Collector
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
-49
View File
@@ -1,49 +0,0 @@
# Adds namespace to all resources.
namespace: troubleshoot-system
# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
# "wordpress" becomes "alices-wordpress".
# Note that it should also match with the prefix (text before '-') of the namespace
# field above.
namePrefix: troubleshoot-
# Labels to add to all resources and selectors.
#commonLabels:
# someName: someValue
# Each entry in this list must resolve to an existing
# resource definition in YAML. These are the resource
# files that kustomize reads, modifies and emits as a
# YAML string, with resources separated by document
# markers ("---").
resources:
- ../rbac/rbac_role.yaml
- ../rbac/rbac_role_binding.yaml
- ../manager/manager.yaml
# Comment the following 3 lines if you want to disable
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
# which protects your /metrics endpoint.
- ../rbac/auth_proxy_service.yaml
- ../rbac/auth_proxy_role.yaml
- ../rbac/auth_proxy_role_binding.yaml
patches:
- manager_image_patch.yaml
# Protect the /metrics endpoint by putting it behind auth.
# Only one of manager_auth_proxy_patch.yaml and
# manager_prometheus_metrics_patch.yaml should be enabled.
- manager_auth_proxy_patch.yaml
# If you want your controller-manager to expose the /metrics
# endpoint w/o any authn/z, uncomment the following line and
# comment manager_auth_proxy_patch.yaml.
# Only one of manager_auth_proxy_patch.yaml and
# manager_prometheus_metrics_patch.yaml should be enabled.
#- manager_prometheus_metrics_patch.yaml
vars:
- name: WEBHOOK_SECRET_NAME
objref:
kind: Secret
name: webhook-server-secret
apiVersion: v1
@@ -1,24 +0,0 @@
# This patch inject a sidecar container which is a HTTP proxy for the controller manager,
# it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
- name: kube-rbac-proxy
image: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0
args:
- "--secure-listen-address=0.0.0.0:8443"
- "--upstream=http://127.0.0.1:8089/"
- "--logtostderr=true"
- "--v=10"
ports:
- containerPort: 8443
name: https
- name: manager
args:
- "--metrics-addr=127.0.0.1:8088"
-12
View File
@@ -1,12 +0,0 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: controller-manager
namespace: system
spec:
template:
spec:
containers:
# Change the value of image field below to your controller image URL
- image: IMAGE_URL
name: manager
@@ -1,19 +0,0 @@
# This patch enables Prometheus scraping for the manager pod.
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: controller-manager
namespace: system
spec:
template:
metadata:
annotations:
prometheus.io/scrape: 'true'
spec:
containers:
# Expose the prometheus metrics on default port
- name: manager
ports:
- containerPort: 8080
name: metrics
protocol: TCP
-83
View File
@@ -1,83 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
name: system
---
apiVersion: v1
kind: Service
metadata:
name: controller-manager-service
namespace: system
labels:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
spec:
selector:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
ports:
- port: 443
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: controller-manager
namespace: system
labels:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
spec:
selector:
matchLabels:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
serviceName: controller-manager-service
template:
metadata:
labels:
control-plane: controller-manager
controller-tools.k8s.io: "1.0"
spec:
containers:
- command:
- /manager
image: controller:latest
imagePullPolicy: Always
name: manager
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: SECRET_NAME
value: $(WEBHOOK_SECRET_NAME)
resources:
limits:
cpu: 100m
memory: 30Mi
requests:
cpu: 100m
memory: 20Mi
ports:
- containerPort: 9876
name: webhook-server
protocol: TCP
volumeMounts:
- mountPath: /tmp/cert
name: cert
readOnly: true
terminationGracePeriodSeconds: 10
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-secret
---
apiVersion: v1
kind: Secret
metadata:
name: webhook-server-secret
namespace: system
-13
View File
@@ -1,13 +0,0 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: proxy-role
rules:
- apiGroups: ["authentication.k8s.io"]
resources:
- tokenreviews
verbs: ["create"]
- apiGroups: ["authorization.k8s.io"]
resources:
- subjectaccessreviews
verbs: ["create"]

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