Compare commits

...
611 Commits
Author SHA1 Message Date
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
601 changed files with 101141 additions and 7241 deletions
-47
View File
@@ -1,47 +0,0 @@
steps:
- label: build
command: "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
environment:
- SCOPE_DSN
- BUILDKITE_REPO
- BUILDKITE_COMMIT
- BUILDKITE_BUILD_ID
- BUILDKITE_BUILD_NUMBER
- BUILDKITE_BUILD_URL
- BUILDKITE_BUILD_CHECKOUT_PATH
- BUILDKITE
- 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
-35
View File
@@ -1,35 +0,0 @@
name: "Run preflights on a cluster"
on: [push]
jobs:
compile-preflight:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v1
with:
go-version: '1.12.14'
- name: setup env
run: |
echo "::set-env name=GOPATH::$(go env GOPATH)"
echo "::add-path::$(go env GOPATH)/bin"
shell: bash
- uses: actions/checkout@master
- run: make preflight
- uses: actions/upload-artifact@v1
with:
name: preflight
path: bin/preflight
run-preflights:
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.2.0
- run: chmod +x bin/preflight
- run: bin/preflight --interactive=false --format=json https://preflight.replicated.com
+7 -3
View File
@@ -26,7 +26,11 @@ vendor
*.swo
*~
# scope test logs
scope-go-*.log
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.
+73 -22
View File
@@ -1,8 +1,6 @@
# Image URL to use all building/pushing image targets
IMG ?= controller:latest
export GO111MODULE=on
export GOPROXY=https://proxy.golang.org
SHELL := /bin/bash -o pipefail
VERSION_PACKAGE = github.com/replicatedhq/troubleshoot/pkg/version
@@ -28,33 +26,40 @@ 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 ${LDFLAGS} -o bin/troubleshoot.so -buildmode=c-shared ffi/main.go
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/troubleshoot.so -buildmode=c-shared ffi/main.go
# Run tests
test: generate fmt vet
go test ./pkg/... ./cmd/... -coverprofile cover.out
go test ${BUILDFLAGS} ./pkg/... ./cmd/... -coverprofile cover.out
.PHONY: support-bundle
support-bundle: generate fmt vet
go build ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/support-bundle github.com/replicatedhq/troubleshoot/cmd/troubleshoot
.PHONY: preflight
preflight: generate fmt vet
go build ${LDFLAGS} -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
go build ${BUILDFLAGS} ${LDFLAGS} -o bin/preflight github.com/replicatedhq/troubleshoot/cmd/preflight
.PHONY: analyze
analyze: generate fmt vet
go build ${LDFLAGS} -o bin/analyze github.com/replicatedhq/troubleshoot/cmd/analyze
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:
@@ -62,27 +67,38 @@ 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
$(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.4
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.16.4
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)
@@ -101,7 +117,7 @@ snapshot-release:
.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 push localhost:32000/troubleshoot:alpha
@@ -113,8 +129,43 @@ run-preflight: preflight
.PHONY: run-troubleshoot
run-troubleshoot: support-bundle
./bin/support-bundle ./examples/troubleshoot/sample-troubleshoot.yaml
./bin/support-bundle ./examples/support-bundle/sample-supportbundle.yaml
.PHONY: run-analyze
run-analyze: analyze
./bin/analyze --analyzers ./examples/troubleshoot/sample-analyzers.yaml ./support-bundle.tar.gz
./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
+18 -6
View File
@@ -1,8 +1,8 @@
# Replicated Troubleshoot
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.
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).
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.
@@ -18,11 +18,11 @@ curl https://krew.sh/preflight | bash
kubectl preflight https://preflight.replicated.com
```
For a details on creating the custom resource files that drive preflight checks, visit [creating preflight checks](https://troubleshoot.sh/docs/preflight/creating/).
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 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, [Kotsadm](https://github.com/replicatedhq/kotsadm), provides cluster operators with in-cluster UI for processing support bundles and viewing analyzers (as well as support bundle collection).
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:
@@ -32,11 +32,23 @@ curl https://krew.sh/support-bundle | bash
and run:
```shell
kubectl support-bundle https://troubleshoot.replicated.com
kubectl support-bundle https://support-bundle.replicated.com
```
For details on creating the custom resource files that drive support-bundle collection [creating collectors](https://troubleshoot.sh/reference/collectors/overview/) and for analyzers [creating analyzers](https://troubleshoot.sh/reference/analyzers/overview/).
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
```
+2 -7
View File
@@ -4,14 +4,10 @@ import (
"os"
"strings"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/replicatedhq/troubleshoot/pkg/logger"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
var (
KubernetesConfigFlags *genericclioptions.ConfigFlags
)
func RootCmd() *cobra.Command {
@@ -41,8 +37,7 @@ func RootCmd() *cobra.Command {
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
KubernetesConfigFlags = genericclioptions.NewConfigFlags(false)
KubernetesConfigFlags.AddFlags(cmd.Flags())
k8sutil.AddFlags(cmd.Flags())
return cmd
}
+7 -15
View File
@@ -4,10 +4,10 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"github.com/pkg/errors"
"github.com/replicatedhq/troubleshoot/cmd/util"
analyzer "github.com/replicatedhq/troubleshoot/pkg/analyze"
"github.com/spf13/viper"
)
@@ -16,11 +16,8 @@ func runAnalyzers(v *viper.Viper, bundlePath string) error {
specPath := v.GetString("analyzers")
specContent := ""
if !isURL(specPath) {
if _, err := os.Stat(specPath); os.IsNotExist(err) {
return fmt.Errorf("%s was not found", specPath)
}
var err error
if _, err = os.Stat(specPath); err == nil {
b, err := ioutil.ReadFile(specPath)
if err != nil {
return err
@@ -28,6 +25,10 @@ func runAnalyzers(v *viper.Viper, bundlePath string) error {
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
@@ -64,12 +65,3 @@ func runAnalyzers(v *viper.Viper, bundlePath string) error {
return nil
}
func isURL(str string) bool {
parsed, err := url.ParseRequestURI(str)
if err != nil {
return false
}
return parsed.Scheme != ""
}
+1 -1
View File
@@ -2,7 +2,7 @@ package main
import (
"github.com/replicatedhq/troubleshoot/cmd/analyze/cli"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
_ "k8s.io/client-go/plugin/pkg/client/auth"
)
func main() {
+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()
}
+11 -23
View File
@@ -5,17 +5,18 @@ import (
"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"
)
var (
selectedResult = 0
table = widgets.NewTable()
isShowingSaved = false
)
@@ -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
@@ -214,13 +218,13 @@ func estimateNumberOfLines(text string, width int) int {
}
func save(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) (string, error) {
filename := path.Join(homeDir(), fmt.Sprintf("%s-results.txt", preflightName))
filename := path.Join(util.HomeDir(), fmt.Sprintf("%s-results.txt", preflightName))
_, 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 := ""
@@ -269,19 +273,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(KubernetesConfigFlags)
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
}
}
}
+6 -27
View File
@@ -4,14 +4,9 @@ import (
"os"
"strings"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
var (
KubernetesConfigFlags *genericclioptions.ConfigFlags
)
func RootCmd() *cobra.Command {
@@ -37,19 +32,16 @@ that a cluster meets the requirements to run an application.`,
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("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().Bool("collect-without-permissions", false, "always run preflight checks even if some require permissions that preflight does not have")
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.")
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
KubernetesConfigFlags = genericclioptions.NewConfigFlags(false)
KubernetesConfigFlags.AddFlags(cmd.Flags())
k8sutil.AddFlags(cmd.Flags())
return cmd
}
@@ -64,16 +56,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)
}
+271 -180
View File
@@ -1,49 +1,79 @@
package cli
import (
"encoding/base64"
"encoding/json"
"context"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"os/signal"
"strings"
"time"
cursor "github.com/ahmetalpbalkan/go-cursor"
"github.com/fatih/color"
"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/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"
"gopkg.in/yaml.v2"
"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 {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
if v.GetBool("interactive") {
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)
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 = string(b)
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/v1beta1")
req.Header.Set("User-Agent", "Replicated_Preflight/v1beta2")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
@@ -55,208 +85,269 @@ func runPreflights(v *viper.Viper, arg string) error {
return err
}
preflightContent = string(body)
preflightContent = body
}
preflight := troubleshootv1beta1.Preflight{}
if err := yaml.Unmarshal([]byte(preflightContent), &preflight); err != nil {
return errors.Wrapf(err, "failed to parse %s as a preflight", arg)
}
s := spin.New()
finishedCh := make(chan bool, 1)
progressChan := make(chan interface{}, 0) // non-zero buffer will result in missed messages
go func() {
for {
select {
case msg, ok := <-progressChan:
if !ok {
continue
}
switch msg := msg.(type) {
case error:
c := color.New(color.FgHiRed)
c.Println(fmt.Sprintf("%s\r * %v", cursor.ClearEntireLine(), msg))
case string:
c := color.New(color.FgCyan)
c.Println(fmt.Sprintf("%s\r * %s", cursor.ClearEntireLine(), msg))
}
case <-time.After(time.Millisecond * 100):
fmt.Printf("\r \033[36mRunning Preflight checks\033[m %s ", s.Next())
case <-finishedCh:
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
return
}
}
}()
defer func() {
close(finishedCh)
}()
allCollectedData, err := runCollectors(v, preflight, progressChan)
preflightContent, err = docrewrite.ConvertToV1Beta2(preflightContent)
if err != nil {
return err
return errors.Wrap(err, "failed to convert to v1beta2")
}
getCollectedFileContents := func(fileName string) ([]byte, error) {
contents, ok := allCollectedData[fileName]
if !ok {
return nil, fmt.Errorf("file %s was not collected", fileName)
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")
}
return contents, nil
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
}
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
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
}
}
return matching, nil
}
analyzeResults := []*analyzerunner.AnalyzeResult{}
for _, analyzer := range preflight.Spec.Analyzers {
analyzeResult, err := analyzerunner.Analyze(analyzer, getCollectedFileContents, getChildCollectedFileContents)
if err != nil {
analyzeResult = &analyzerunner.AnalyzeResult{
IsFail: true,
Title: "Analyzer Failed",
Message: err.Error(),
}
}
if analyzeResult != nil {
analyzeResults = append(analyzeResults, analyzeResult)
}
}
if preflight.Spec.UploadResultsTo != "" {
err := uploadResults(preflight.Spec.UploadResultsTo, analyzeResults)
if err != nil {
progressChan <- err
}
}
finishedCh <- true
stopProgressCollection()
progressCollection.Wait()
if v.GetBool("interactive") {
if len(analyzeResults) == 0 {
return errors.New("no data has been collected")
}
return showInteractiveResults(preflight.Name, analyzeResults)
return showInteractiveResults(preflightSpecName, analyzeResults)
}
return showStdoutResults(v.GetString("format"), preflight.Name, analyzeResults)
return showStdoutResults(v.GetString("format"), preflightSpecName, analyzeResults)
}
func runCollectors(v *viper.Viper, preflight troubleshootv1beta1.Preflight, progressChan chan interface{}) (map[string][]byte, error) {
collectSpecs := make([]*troubleshootv1beta1.Collect, 0, 0)
collectSpecs = append(collectSpecs, preflight.Spec.Collectors...)
collectSpecs = ensureCollectorInList(collectSpecs, troubleshootv1beta1.Collect{ClusterInfo: &troubleshootv1beta1.ClusterInfo{}})
collectSpecs = ensureCollectorInList(collectSpecs, troubleshootv1beta1.Collect{ClusterResources: &troubleshootv1beta1.ClusterResources{}})
func collectInteractiveProgress(ctx context.Context, progressCh <-chan interface{}) func() error {
return func() error {
spinner := spin.New()
lastMsg := ""
allCollectedData := make(map[string][]byte)
errorTxt := color.New(color.FgHiRed)
infoTxt := color.New(color.FgCyan)
config, err := KubernetesConfigFlags.ToRESTConfig()
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")
}
var collectors collect.Collectors
for _, desiredCollector := range collectSpecs {
collector := collect.Collector{
Redact: true,
Collect: desiredCollector,
ClientConfig: config,
Namespace: v.GetString("namespace"),
}
collectors = append(collectors, &collector)
collectOpts := preflight.CollectOpts{
Namespace: v.GetString("namespace"),
IgnorePermissionErrors: v.GetBool("collect-without-permissions"),
ProgressChan: progressCh,
KubernetesRestConfig: restConfig,
}
if err := collectors.CheckRBAC(); err != nil {
return nil, errors.Wrap(err, "failed to check RBAC for collectors")
}
foundForbidden := false
for _, c := range collectors {
for _, e := range c.RBACErrors {
foundForbidden = true
progressChan <- e
}
}
if foundForbidden && !v.GetBool("collect-without-permissions") {
if preflight.Spec.UploadResultsTo != "" {
err := uploadErrors(preflight.Spec.UploadResultsTo, collectors)
if err != nil {
progressChan <- err
}
}
return nil, errors.New("insufficient permissions to run all collectors")
}
// Run preflights collectors synchronously
for _, collector := range collectors {
if len(collector.RBACErrors) > 0 {
// don't skip clusterResources collector due to RBAC issues
if collector.Collect.ClusterResources == nil {
progressChan <- fmt.Sprintf("skipping collector %s with insufficient RBAC permissions", collector.GetDisplayName())
continue
}
}
result, err := collector.RunCollectorSync()
if v.GetString("since") != "" || v.GetString("since-time") != "" {
err := parseTimeFlags(v, preflightSpec.Spec.Collectors)
if err != nil {
progressChan <- errors.Errorf("failed to run collector %s: %v\n", collector.GetDisplayName(), err)
continue
}
if result != nil {
output, err := parseCollectorOutput(string(result))
if err != nil {
progressChan <- errors.Errorf("failed to parse collector output %s: %v\n", collector.GetDisplayName(), err)
continue
}
for k, v := range output {
allCollectedData[k] = v
}
return nil, err
}
}
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 {
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
}
for filename, maybeContents := range input {
fileDir, fileName := filepath.Split(filename)
return &collectResults, nil
}
switch maybeContents.(type) {
case string:
decoded, err := base64.StdEncoding.DecodeString(maybeContents.(string))
if err != nil {
return nil, err
}
files[filepath.Join(fileDir, fileName)] = decoded
func collectRemote(preflightSpec *troubleshootv1beta2.HostPreflight, progressCh chan interface{}) (*preflight.CollectResult, error) {
v := viper.GetViper()
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
}
}
restConfig, err := k8sutil.GetRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to convert kube flags to rest config")
}
return files, nil
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
}
-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
}
+1
View File
@@ -19,6 +19,7 @@ func showStdoutResults(format string, preflightName string, analyzeResults []*an
}
func showStdoutResultsHuman(preflightName string, analyzeResults []*analyzerunner.AnalyzeResult) error {
fmt.Println("")
var failed bool
for _, analyzeResult := range analyzeResults {
testResultfailed := outputResult(analyzeResult)
+8 -26
View File
@@ -8,33 +8,15 @@ import (
"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 UploadPreflightError struct {
Error string `json:"error"`
}
type UploadPreflightResults struct {
Results []*UploadPreflightResult `json:"results,omitempty"`
Errors []*UploadPreflightError `json:"errors,omitempty"`
}
func uploadResults(uri string, analyzeResults []*analyzerunner.AnalyzeResult) error {
uploadPreflightResults := &UploadPreflightResults{
Results: []*UploadPreflightResult{},
uploadPreflightResults := &preflight.UploadPreflightResults{
Results: []*preflight.UploadPreflightResult{},
}
for _, analyzeResult := range analyzeResults {
uploadPreflightResult := &UploadPreflightResult{
uploadPreflightResult := &preflight.UploadPreflightResult{
IsFail: analyzeResult.IsFail,
IsWarn: analyzeResult.IsWarn,
IsPass: analyzeResult.IsPass,
@@ -50,23 +32,23 @@ func uploadResults(uri string, analyzeResults []*analyzerunner.AnalyzeResult) er
}
func uploadErrors(uri string, collectors collect.Collectors) error {
errors := []*UploadPreflightError{}
errors := []*preflight.UploadPreflightError{}
for _, collector := range collectors {
for _, e := range collector.RBACErrors {
errors = append(errors, &UploadPreflightError{
errors = append(errors, &preflight.UploadPreflightError{
Error: e.Error(),
})
}
}
results := &UploadPreflightResults{
results := &preflight.UploadPreflightResults{
Errors: errors,
}
return upload(uri, results)
}
func upload(uri string, payload *UploadPreflightResults) error {
func upload(uri string, payload *preflight.UploadPreflightResults) error {
b, err := json.Marshal(payload)
if err != nil {
return errors.Wrap(err, "failed to marshal payload")
-40
View File
@@ -1,40 +0,0 @@
package cli
import (
"net/url"
"os"
"github.com/pkg/errors"
troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
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 createTroubleshootK8sClient(configFlags *genericclioptions.ConfigFlags) (*troubleshootclientv1beta1.TroubleshootV1beta1Client, error) {
config, err := configFlags.ToRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to convert kube flags to rest config")
}
troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(config)
if err != nil {
return nil, errors.Wrap(err, "failed to create troubleshoot client")
}
return troubleshootClient, nil
}
+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 -6
View File
@@ -3,7 +3,11 @@ package cli
import (
"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"
@@ -14,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"))
},
@@ -27,7 +32,13 @@ func Analyze() *cobra.Command {
logger.SetQuiet(v.GetBool("quiet"))
result, err := analyzer.DownloadAndAnalyze(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
}
@@ -59,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")
@@ -70,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
}
-138
View File
@@ -1,138 +0,0 @@
package cli
import (
"encoding/base64"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"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(KubernetesConfigFlags)
if err != nil {
return err
}
bundlePath, err := ioutil.TempDir("", "troubleshoot")
if err != nil {
return err
}
defer os.RemoveAll(bundlePath)
if err = writeVersionFile(bundlePath); 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 {
filename, err := findFileName("support-bundle", "tar.gz")
if err != nil {
return err
}
if err := tarSupportBundleDir(bundlePath, filename); 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
}
-78
View File
@@ -1,78 +0,0 @@
package cli
import (
"github.com/pkg/errors"
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"))
},
RunE: func(cmd *cobra.Command, args []string) error {
v := viper.GetViper()
troubleshootClient, err := createTroubleshootK8sClient(KubernetesConfigFlags)
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)
config, err := KubernetesConfigFlags.ToRESTConfig()
if err != nil {
return errors.Wrap(err, "failed to convert kube flags to rest config")
}
stopChan, err := k8sutil.PortForward(config, 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")
viper.BindPFlags(cmd.Flags())
return cmd
}
+25 -17
View File
@@ -1,27 +1,24 @@
package cli
import (
"io/ioutil"
"os"
"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"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
var (
KubernetesConfigFlags *genericclioptions.ConfigFlags
)
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())
@@ -39,19 +36,22 @@ from a server that can be used to assist when troubleshooting a server.`,
cmd.AddCommand(Analyze())
cmd.AddCommand(VersionCmd())
cmd.Flags().String("collectors", "", "name of the collectors to use")
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("collect-without-permissions", false, "always run troubleshoot collectors even if some require permissions that troubleshoot does not have")
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.")
// 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("-", "_"))
KubernetesConfigFlags = genericclioptions.NewConfigFlags(false)
KubernetesConfigFlags.AddFlags(cmd.Flags())
k8sutil.AddFlags(cmd.Flags())
return cmd
}
@@ -67,7 +67,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 +79,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
}
+264 -310
View File
@@ -1,316 +1,249 @@
package cli
import (
"encoding/base64"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"os"
"os/signal"
"path/filepath"
"strings"
"time"
cursor "github.com/ahmetalpbalkan/go-cursor"
"github.com/fatih/color"
"github.com/mholt/archiver"
"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"
"gopkg.in/yaml.v2"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
"github.com/replicatedhq/troubleshoot/pkg/collect"
"k8s.io/client-go/rest"
)
func runTroubleshoot(v *viper.Viper, arg string) error {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
interactive := v.GetBool("interactive") && isatty.IsTerminal(os.Stdout.Fd())
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)
if interactive {
fmt.Print(cursor.Hide())
defer fmt.Print(cursor.Show())
}
collector := troubleshootv1beta1.Collector{}
if err := yaml.Unmarshal([]byte(collectorContent), &collector); err != nil {
return errors.Wrapf(err, "failed to parse %s collectors", arg)
}
s := spin.New()
finishedCh := make(chan bool, 1)
progressChan := make(chan interface{}, 0) // non-zero buffer can result in missed messages
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)
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)
}
}()
defer func() {
close(finishedCh)
}()
archivePath, err := runCollectors(v, collector, progressChan)
if err != nil {
return errors.Wrap(err, "run collectors")
}
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
createOpts := supportbundle.SupportBundleCreateOpts{
CollectorProgressCallback: collectorCB,
CollectWithoutPermissions: v.GetBool("collect-without-permissions"),
KubernetesRestConfig: restConfig,
Namespace: v.GetString("namespace"),
ProgressChan: progressChan,
SinceTime: sinceTime,
Redact: v.GetBool("redact"),
FromCLI: true,
}
if len(collector.Spec.AfterCollection) == 0 {
msg := archivePath
if appName := collector.Labels["applicationName"]; appName != "" {
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.`
msg = fmt.Sprintf(f, appName, archivePath, appName)
fmt.Printf(f, appName, response.ArchivePath, appName)
return nil
}
fmt.Printf("%s\n", msg)
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
}
fileUploaded := false
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")
}
fileUploaded = true
} else if ac.Callback != nil {
if err := callbackSupportBundleAPI(ac.Callback, archivePath); err != nil {
return errors.Wrap(err, "execute callback")
}
}
if interactive {
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
}
fmt.Printf("\r%s\r", cursor.ClearEntireLine())
if fileUploaded {
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", archivePath)
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", archivePath)
fmt.Printf("A support bundle has been created in the current directory named %q\n", response.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)
if err = writeVersionFile(bundlePath); err != nil {
return "", errors.Wrap(err, "write version file")
}
collectSpecs := make([]*troubleshootv1beta1.Collect, 0, 0)
collectSpecs = append(collectSpecs, collector.Spec.Collectors...)
collectSpecs = ensureCollectorInList(collectSpecs, troubleshootv1beta1.Collect{ClusterInfo: &troubleshootv1beta1.ClusterInfo{}})
collectSpecs = ensureCollectorInList(collectSpecs, troubleshootv1beta1.Collect{ClusterResources: &troubleshootv1beta1.ClusterResources{}})
config, err := KubernetesConfigFlags.ToRESTConfig()
if err != nil {
return "", errors.Wrap(err, "failed to convert kube flags to rest config")
}
var collectors collect.Collectors
for _, desiredCollector := range collectSpecs {
collector := collect.Collector{
Redact: true,
Collect: desiredCollector,
ClientConfig: config,
Namespace: v.GetString("namespace"),
}
collectors = append(collectors, &collector)
}
if err := collectors.CheckRBAC(); err != nil {
return "", errors.Wrap(err, "failed to check RBAC for collectors")
}
foundForbidden := false
for _, c := range collectors {
for _, e := range c.RBACErrors {
foundForbidden = true
progressChan <- e
}
}
if foundForbidden && !v.GetBool("collect-without-permissions") {
return "", errors.New("insufficient permissions to run all collectors")
}
// Run preflights collectors synchronously
for _, collector := range collectors {
if len(collector.RBACErrors) > 0 {
// don't skip clusterResources collector due to RBAC issues
if collector.Collect.ClusterResources == nil {
progressChan <- fmt.Sprintf("skipping collector %s with insufficient RBAC permissions", collector.GetDisplayName())
continue
}
}
progressChan <- collector.GetDisplayName()
result, err := collector.RunCollectorSync()
if err != nil {
progressChan <- fmt.Errorf("failed to run collector %q: %v", collector.GetDisplayName(), err)
continue
}
if result != nil {
err = parseAndSaveCollectorOutput(string(result), bundlePath)
if err != nil {
progressChan <- fmt.Errorf("failed to parse collector spec %q: %v", collector.GetDisplayName(), err)
continue
}
}
}
filename, err := findFileName("support-bundle", "tar.gz")
if err != nil {
return "", errors.Wrap(err, "find file name")
}
if err := tarSupportBundleDir(bundlePath, filename); err != nil {
return "", errors.Wrap(err, "create bundle file")
}
return filename, nil
}
func parseAndSaveCollectorOutput(output string, bundlePath string) error {
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)
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 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 {
@@ -319,54 +252,75 @@ func getExpectedContentType(uploadURL string) string {
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
}
func tarSupportBundleDir(inputDir, outputFilename string) error {
tarGz := archiver.TarGz{
Tar: &archiver.Tar{
ImplicitTopLevelFolder: false,
},
}
paths := []string{
filepath.Join(inputDir, VersionFilename), // version file should be first in tar archive for quick extraction
}
topLevelFiles, err := ioutil.ReadDir(inputDir)
if err != nil {
return errors.Wrap(err, "list bundle directory contents")
}
for _, f := range topLevelFiles {
if f.Name() == VersionFilename {
continue
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")
}
paths = append(paths, filepath.Join(inputDir, f.Name()))
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)
}
if err := tarGz.Archive(paths, outputFilename); err != nil {
return errors.Wrap(err, "create archive")
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,
}
return nil
_, err := prompt.Run()
return err == nil
}
type CollectorFailure struct {
Collector *troubleshootv1beta1.Collect
Failure string
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
}
-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
}
-33
View File
@@ -2,44 +2,11 @@ package cli
import (
"fmt"
"net/url"
"os"
"github.com/pkg/errors"
troubleshootclientv1beta1 "github.com/replicatedhq/troubleshoot/pkg/client/troubleshootclientset/typed/troubleshoot/v1beta1"
"k8s.io/cli-runtime/pkg/genericclioptions"
)
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 createTroubleshootK8sClient(configFlags *genericclioptions.ConfigFlags) (*troubleshootclientv1beta1.TroubleshootV1beta1Client, error) {
config, err := configFlags.ToRESTConfig()
if err != nil {
return nil, errors.Wrap(err, "failed to convert kube flags to rest config")
}
troubleshootClient, err := troubleshootclientv1beta1.NewForConfig(config)
if err != nil {
return nil, errors.Wrap(err, "failed to create troubleshoot client")
}
return troubleshootClient, nil
}
func findFileName(basename, extension string) (string, error) {
n := 1
name := basename
+4 -4
View File
@@ -6,7 +6,7 @@ import (
"io/ioutil"
"path/filepath"
troubleshootv1beta1 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta1"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/replicatedhq/troubleshoot/pkg/version"
"github.com/spf13/cobra"
"gopkg.in/yaml.v2"
@@ -29,10 +29,10 @@ func VersionCmd() *cobra.Command {
const VersionFilename = "version.yaml"
func writeVersionFile(path string) error {
version := troubleshootv1beta1.SupportBundleVersion{
ApiVersion: "troubleshoot.replicated.com/v1beta1",
version := troubleshootv1beta2.SupportBundleVersion{
ApiVersion: "troubleshoot.sh/v1beta2",
Kind: "SupportBundle",
Spec: troubleshootv1beta1.SupportBundleVersionSpec{
Spec: troubleshootv1beta2.SupportBundleVersionSpec{
VersionNumber: version.Version(),
},
}
+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: {}
@@ -0,0 +1,51 @@
---
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
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
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -0,0 +1,755 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.7.0
creationTimestamp: null
name: analyzers.troubleshoot.replicated.com
spec:
group: troubleshoot.replicated.com
names:
kind: Analyzer
listKind: AnalyzerList
plural: analyzers
singular: analyzer
scope: Namespaced
versions:
- name: v1beta1
schema:
openAPIV3Schema:
description: Analyzer is the Schema for the analyzers API
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
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: AnalyzerSpec defines the desired state of Analyzer
properties:
analyzers:
items:
properties:
clusterVersion:
properties:
checkName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- outcomes
type: object
containerRuntime:
properties:
checkName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- outcomes
type: object
customResourceDefinition:
properties:
checkName:
type: string
customResourceDefinitionName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- customResourceDefinitionName
- outcomes
type: object
deploymentStatus:
properties:
checkName:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- name
- namespace
- outcomes
type: object
distribution:
properties:
checkName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- outcomes
type: object
imagePullSecret:
properties:
checkName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
registryName:
type: string
required:
- outcomes
- registryName
type: object
ingress:
properties:
checkName:
type: string
exclude:
type: BoolString
ingressName:
type: string
namespace:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- ingressName
- namespace
- outcomes
type: object
mysql:
properties:
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
fileName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- collectorName
- outcomes
type: object
nodeResources:
properties:
checkName:
type: string
exclude:
type: BoolString
filters:
properties:
cpuAllocatable:
type: string
cpuCapacity:
type: string
ephemeralStorageAllocatable:
type: string
ephemeralStorageCapacity:
type: string
memoryAllocatable:
type: string
memoryCapacity:
type: string
podAllocatable:
type: string
podCapacity:
type: string
selector:
properties:
matchLabel:
additionalProperties:
type: string
type: object
type: object
type: object
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- outcomes
type: object
postgres:
properties:
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
fileName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- collectorName
- outcomes
type: object
redis:
properties:
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
fileName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- collectorName
- outcomes
type: object
secret:
properties:
checkName:
type: string
exclude:
type: BoolString
key:
type: string
namespace:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
secretName:
type: string
required:
- namespace
- outcomes
- secretName
type: object
statefulsetStatus:
properties:
checkName:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
required:
- name
- namespace
- outcomes
type: object
storageClass:
properties:
checkName:
type: string
exclude:
type: BoolString
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
storageClassName:
type: string
required:
- outcomes
- storageClassName
type: object
textAnalyze:
properties:
checkName:
type: string
collectorName:
type: string
exclude:
type: BoolString
fileName:
type: string
outcomes:
items:
properties:
fail:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
pass:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
warn:
properties:
message:
type: string
uri:
type: string
when:
type: string
type: object
type: object
type: array
regex:
type: string
regexGroups:
type: string
required:
- outcomes
type: object
type: object
type: array
type: object
status:
description: AnalyzerStatus defines the observed state of Analyzer
type: object
type: object
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -0,0 +1,100 @@
---
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
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
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
@@ -0,0 +1,337 @@
---
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
singular: collector
scope: Namespaced
versions:
- name: v1beta1
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:
clusterInfo:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
clusterResources:
properties:
collectorName:
type: string
exclude:
type: BoolString
type: object
copy:
properties:
collectorName:
type: string
containerName:
type: string
containerPath:
type: string
exclude:
type: BoolString
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
required:
- 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:
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
type: object
name:
type: string
namespace:
type: string
selector:
items:
type: string
type: array
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:
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
required:
- name
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: []
@@ -0,0 +1,120 @@
---
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
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
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []
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
@@ -1,9 +0,0 @@
apiVersion: troubleshoot.replicated.com/v1beta1
kind: AnalyzerJob
metadata:
labels:
controller-tools.k8s.io: "1.0"
name: analyzerjob-sample
spec:
# Add fields here
foo: bar
@@ -1,10 +0,0 @@
apiVersion: troubleshoot.replicated.com/v1beta1
kind: CollectorJob
metadata:
name: collectorjob-sample
spec:
image: localhost:32000/troubleshoot:alpha
imagePullPolicy: Always
collector:
name: collector-sample
namespace: default
@@ -1,10 +0,0 @@
apiVersion: troubleshoot.replicated.com/v1beta1
kind: PreflightJob
metadata:
name: preflightjob-sample
spec:
image: localhost:32000/troubleshoot:alpha
imagePullPolicy: Always
preflight:
name: preflight-sample
namespace: default
@@ -1,4 +1,4 @@
apiVersion: troubleshoot.replicated.com/v1beta1
apiVersion: troubleshoot.sh/v1beta2
kind: Analyzer
metadata:
labels:
@@ -1,4 +1,4 @@
apiVersion: troubleshoot.replicated.com/v1beta1
apiVersion: troubleshoot.sh/v1beta2
kind: Collector
metadata:
name: collector-sample
@@ -15,7 +15,7 @@ spec:
# - name=nginx-ingress-microk8s
# namespace: default
# limits:
# maxAge: 30d
# maxAge: 720h # 30*24
# maxLines: 10000
# - run:
# collectorName: ping-google
@@ -1,4 +1,4 @@
apiVersion: troubleshoot.replicated.com/v1beta1
apiVersion: troubleshoot.sh/v1beta2
kind: Preflight
metadata:
name: support-io
-66
View File
@@ -1,66 +0,0 @@
project_name: troubleshoot
release:
github:
owner: replicatedhq
name: troubleshoot
builds:
- id: preflight
goos:
- linux
goarch:
- amd64
env:
- CGO_ENABLED=0
main: cmd/preflight/main.go
ldflags: -s -w
-X github.com/replicatedhq/troubleshoot/pkg/version.version={{.Version}}
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
binary: preflight
hooks: {}
- id: support-bundle
goos:
- linux
goarch:
- amd64
env:
- CGO_ENABLED=0
main: cmd/troubleshoot/main.go
ldflags: -s -w
-X github.com/replicatedhq/troubleshoot/pkg/version.version={{.Version}}
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
binary: support-bundle
hooks: {}
archives:
- id: tar
format: tar.gz
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}-alpha'
files:
- licence*
- LICENCE*
- license*
- LICENSE*
- readme*
- README*
- changelog*
- CHANGELOG*
dockers:
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
- "replicated/troubleshoot:alpha"
binaries:
- support-bundle
- preflight
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
- "replicated/preflight:alpha"
binaries:
- support-bundle
- preflight
snapshot:
name_template: SNAPSHOT-{{ .Commit }}
-86
View File
@@ -1,86 +0,0 @@
project_name: troubleshoot
release:
github:
owner: replicatedhq
name: troubleshoot
builds:
- id: so
goos:
- linux
goarch:
- amd64
env:
- CGO_ENABLED=1
- GO111MODULE=on
main: ffi/main.go
flags: -buildmode=c-shared
binary: troubleshoot.so
hooks: {}
- id: preflight
goos:
- linux
- windows
- darwin
goarch:
- amd64
env:
- CGO_ENABLED=0
main: cmd/preflight/main.go
ldflags: -s -w
-X github.com/replicatedhq/troubleshoot/pkg/version.version={{.Version}}
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
binary: preflight
hooks: {}
- id: support-bundle
goos:
- linux
- windows
- darwin
goarch:
- amd64
env:
- CGO_ENABLED=0
main: cmd/troubleshoot/main.go
ldflags: -s -w
-X github.com/replicatedhq/troubleshoot/pkg/version.version={{.Version}}
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
binary: support-bundle
hooks: {}
archives:
- id: so
builds:
- so
format: tar.gz
- id: tar
format: tar.gz
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}-alpha'
files:
- licence*
- LICENCE*
- license*
- LICENSE*
- readme*
- README*
- changelog*
- CHANGELOG*
dockers:
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
- "replicated/troubleshoot:alpha"
binaries:
- support-bundle
- preflight
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
- "replicated/preflight:alpha"
binaries:
- support-bundle
- preflight
snapshot:
name_template: SNAPSHOT-{{ .Commit }}
@@ -4,18 +4,6 @@ release:
owner: replicatedhq
name: troubleshoot
builds:
- id: so
goos:
- linux
goarch:
- amd64
env:
- CGO_ENABLED=1
- GO111MODULE=on
main: ffi/main.go
flags: -buildmode=c-shared
binary: troubleshoot.so
hooks: {}
- id: preflight
goos:
- linux
@@ -23,6 +11,7 @@ builds:
- windows
goarch:
- amd64
- arm64
env:
- CGO_ENABLED=0
main: cmd/preflight/main.go
@@ -31,7 +20,7 @@ builds:
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
flags: -tags netgo -tags containers_image_ostree_stub -tags exclude_graphdriver_devicemapper -tags exclude_graphdriver_btrfs -tags containers_image_openpgp -installsuffix netgo
binary: preflight
hooks: {}
- id: support-bundle
@@ -41,6 +30,7 @@ builds:
- windows
goarch:
- amd64
- arm64
env:
- CGO_ENABLED=0
main: cmd/troubleshoot/main.go
@@ -49,15 +39,29 @@ builds:
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -installsuffix netgo
flags: -tags netgo -tags containers_image_ostree_stub -tags exclude_graphdriver_devicemapper -tags exclude_graphdriver_btrfs -tags containers_image_openpgp -installsuffix netgo
binary: support-bundle
hooks: {}
- id: collect
goos:
- linux
- darwin
- windows
goarch:
- amd64
- arm64
env:
- CGO_ENABLED=0
main: cmd/collect/main.go
ldflags: -s -w
-X github.com/replicatedhq/troubleshoot/pkg/version.version={{.Version}}
-X github.com/replicatedhq/troubleshoot/pkg/version.gitSHA={{.Commit}}
-X github.com/replicatedhq/troubleshoot/pkg/version.buildTime={{.Date}}
-extldflags "-static"
flags: -tags netgo -tags containers_image_ostree_stub -tags exclude_graphdriver_devicemapper -tags exclude_graphdriver_btrfs -tags containers_image_openpgp -installsuffix netgo
binary: collect
hooks: {}
archives:
- id: so
builds:
- so
format: tar.gz
name_template: 'troubleshoot.so_{{ .Os }}_{{ .Arch }}'
- id: preflight
builds:
- preflight
@@ -65,7 +69,7 @@ archives:
format_overrides:
- goos: windows
format: zip
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}'
name_template: 'preflight_{{ .Os }}_{{ .Arch }}'
files:
- licence*
- LICENCE*
@@ -75,6 +79,9 @@ archives:
- README*
- changelog*
- CHANGELOG*
- src: 'sbom/assets/*'
dst: .
strip_parent: true # this is needed to make up for the way unzips work in krew v0.4.1
- id: support-bundle
builds:
- support-bundle
@@ -82,7 +89,7 @@ archives:
format_overrides:
- goos: windows
format: zip
name_template: '{{ .Binary }}_{{ .Os }}_{{ .Arch }}'
name_template: 'support-bundle_{{ .Os }}_{{ .Arch }}'
files:
- licence*
- LICENCE*
@@ -92,6 +99,29 @@ archives:
- README*
- changelog*
- CHANGELOG*
- src: 'sbom/assets/*'
dst: .
strip_parent: true # this is needed to make up for the way unzips work in krew v0.4.1
- id: collect
builds:
- collect
format: tar.gz
format_overrides:
- goos: windows
format: zip
name_template: 'collect_{{ .Os }}_{{ .Arch }}'
files:
- licence*
- LICENCE*
- license*
- LICENSE*
- readme*
- README*
- changelog*
- CHANGELOG*
- src: 'sbom/assets/*'
dst: .
strip_parent: true # this is needed to make up for the way unzips work in krew v0.4.1
dockers:
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
@@ -99,15 +129,17 @@ dockers:
- "replicated/troubleshoot:{{ .Major }}"
- "replicated/troubleshoot:{{ .Major }}.{{ .Minor }}"
- "replicated/troubleshoot:{{ .Major }}.{{ .Minor }}.{{ .Patch }}"
binaries:
ids:
- support-bundle
- preflight
- collect
- dockerfile: ./deploy/Dockerfile.troubleshoot
image_templates:
- "replicated/preflight:latest"
- "replicated/preflight:{{ .Major }}"
- "replicated/preflight:{{ .Major }}.{{ .Minor }}"
- "replicated/preflight:{{ .Major }}.{{ .Minor }}.{{ .Patch }}"
binaries:
ids:
- support-bundle
- preflight
- collect
+2 -1
View File
@@ -3,10 +3,11 @@ WORKDIR /
RUN apt-get -qq update \
&& apt-get -qq -y install \
ca-certificates
ca-certificates kmod
COPY support-bundle /troubleshoot/support-bundle
COPY preflight /troubleshoot/preflight
COPY collect /troubleshoot/collect
ENV PATH="/troubleshoot:${PATH}"
+32 -25
View File
@@ -3,14 +3,13 @@ kind: Plugin
metadata:
name: preflight
spec:
version: "v0.9.14"
version: {{ .TagName }}
platforms:
- selector:
matchLabels:
os: linux
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/preflight_linux_amd64.tar.gz
sha256: "25b062760a23e546d22f1687fd460095d61f9fd4a210eec5cc4bacb648b043da"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/preflight_linux_amd64.tar.gz" .TagName }}
files:
- from: preflight
to: .
@@ -21,20 +20,29 @@ spec:
matchLabels:
os: darwin
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/preflight_darwin_amd64.tar.gz
sha256: "00e21d1fe38fd8373136a064e15586b3d4eab49a4d3617167680eea27ebbcc65"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/preflight_darwin_amd64.tar.gz" .TagName }}
files:
- from: preflight
to: .
- from: LICENSE
to: .
bin: preflight
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/preflight_darwin_arm64.tar.gz" .TagName }}
files:
- from: preflight
to: .
- from: LICENSE
to: .
bin: preflight
- selector:
matchLabels:
os: windows
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/preflight_windows_amd64.zip
sha256: "1b10f6a7ca73722c458a44afb9e3a91af2d41681d0e0ea16483413691e363460"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/preflight_windows_amd64.zip" .TagName }}
files:
- from: preflight.exe
to: .
@@ -43,7 +51,23 @@ spec:
bin: preflight.exe
shortDescription: Executes application preflight tests in a cluster
homepage: https://github.com/replicatedhq/troubleshoot
caveats: |
description: |
This plugin executes application-specific preflight checks and conformance
tests against a cluster, prior to installation of an application.
Application developers can create and host a Preflight manifest that
defines the minimum and desired Kubernetes environment for an application.
Before installing the application, a cluster admin can use this plugin to
execute the application preflight checksto identify any missing
components, configuration or incompatibilities between the cluster and the
desired environment.
When executing Preflight tests, the test results will be displayed in a
terminal-based UI on the workstation that executed the command.
For information on creating a Preflight manifest, view the documentation
at https://help.replicated.com/docs/troubleshoot/kubernetes/analysis/
Usage:
$ kubectl preflight <uri/path>
@@ -62,20 +86,3 @@ spec:
For application developers writing collectors and analyzers:
https://help.replicated.com/docs/troubleshoot/kubernetes/collectors/defining-collectors/
description: |
This plugin executes application-specific preflight checks and conformance
tests against a cluster, prior to installation of an application.
Application developers can create and host a Preflight manifest that
defines the minimum and desired Kubernetes environment for an application.
Before installing the application, a cluster admin can use this plugin to
execute the application preflight checksto identify any missing
components, configuration or incompatibilities between the cluster and the
desired environment.
When executing Preflight tests, the test results will be displayed in a
terminal-based UI on the workstation that executed the command.
For information on creating a Preflight manifest, view the documentation
at https://help.replicated.com/docs/troubleshoot/kubernetes/analysis/
+29 -22
View File
@@ -3,14 +3,13 @@ kind: Plugin
metadata:
name: support-bundle
spec:
version: "v0.9.14"
version: {{ .TagName }}
platforms:
- selector:
matchLabels:
os: linux
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/support-bundle_linux_amd64.tar.gz
sha256: "81ed16f3e423535f026909df2823f5da9909ec5762a150c76fde94d985d101c7"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/support-bundle_linux_amd64.tar.gz" .TagName }}
files:
- from: support-bundle
to: .
@@ -21,20 +20,29 @@ spec:
matchLabels:
os: darwin
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/support-bundle_darwin_amd64.tar.gz
sha256: "84d2cd6b3d77ed2e8e83cda6f79b553e443acb2cc7cb0099be2a73934dac46f4"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/support-bundle_darwin_amd64.tar.gz" .TagName }}
files:
- from: support-bundle
to: .
- from: LICENSE
to: .
bin: support-bundle
- selector:
matchLabels:
os: darwin
arch: arm64
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/support-bundle_darwin_arm64.tar.gz" .TagName }}
files:
- from: support-bundle
to: .
- from: LICENSE
to: .
bin: support-bundle
- selector:
matchLabels:
os: windows
arch: amd64
uri: https://github.com/replicatedhq/troubleshoot/releases/download/v0.9.14/support-bundle_windows_amd64.zip
sha256: "b968d9168ce97c7dc43cb4e043a8d6762c1e231d68f90826a019571f8d450719"
{{addURIAndSha "https://github.com/replicatedhq/troubleshoot/releases/download/{{ .TagName }}/support-bundle_windows_amd64.zip" .TagName }}
files:
- from: support-bundle.exe
to: .
@@ -43,7 +51,20 @@ spec:
bin: support-bundle.exe
shortDescription: Creates support bundles for off-cluster analysis
homepage: https://github.com/replicatedhq/troubleshoot
caveats: |
description: |
This plugin collects information about the cluster, and automatically
redacts sensitive data from being collected. This can optionally include
application-specific data. The plugin writes the collected files into a
single archive named support-bundle.tar.gz. This archive can be manually
inspected or uploaded to https://vendor.replicated.com for automated
analysis.
Application developers can create and host a Collector manifest that
defines information to be collected.
For information on creating a Collector manifest, view the documentation
at https://help.replicated.com/docs/troubleshoot/kubernetes/collectors/defining-collectors/
Usage:
$ kubectl support-bundle <uri>
@@ -62,17 +83,3 @@ spec:
For application developers writing collectors and analyzers:
https://help.replicated.com/docs/troubleshoot/kubernetes/collectors/defining-collectors/
description: |
This plugin collects information about the cluster, and automatically
redacts sensitive data from being collected. This can optionally include
application-specific data. The plugin writes the collected files into a
single archive named support-bundle.tar.gz. This archive can be manually
inspected or uploaded to https://vendor.replicated.com for automated
analysis.
Application developers can create and host a Collector manifest that
defines information to be collected.
For information on creating a Collector manifest, view the documentation
at https://help.replicated.com/docs/troubleshoot/kubernetes/collectors/defining-collectors/
+8
View File
@@ -0,0 +1,8 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: block
spec:
collectors:
- blockDevices: {}
+9
View File
@@ -0,0 +1,9 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: certificate
spec:
collectors:
- certificate:
certificatePath: /etc/ssl/corp.crt
keyPath: /etc/ssl/corp.key
+7
View File
@@ -0,0 +1,7 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: cpu
spec:
collectors:
- cpu: {}
+9
View File
@@ -0,0 +1,9 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: diskUsage
spec:
collectors:
- diskUsage:
collectorName: ephemeral
path: /var/lib/kubelet
@@ -0,0 +1,19 @@
apiVersion: troubleshoot.sh/v1beta2
kind: HostCollector
metadata:
name: fsperf
spec:
collectors:
- filesystemPerformance:
collectorName: etcd-perf
timeout: 2m
directory: /var/lib/etcd
fileSize: 22Mi
operationSizeBytes: 2300
datasync: true
enableBackgroundIOPS: true
backgroundIOPSWarmupSeconds: 10
backgroundWriteIOPS: 300
backgroundWriteIOPSJobs: 6
backgroundReadIOPS: 50
backgroundReadIOPSJobs: 1

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