├── .github ├── dependabot.yml └── workflows │ ├── automated-prs-manager.yaml │ ├── build-checks.yaml │ └── release.yaml ├── .gitignore ├── .golangci.yaml ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── cli ├── download.go ├── root.go ├── serve.go └── shell.go ├── deploy └── .goreleaser.yaml ├── go.mod ├── go.sum ├── pkg ├── api │ ├── client.go │ ├── logs.go │ ├── middleware.go │ └── server.go ├── k8s │ └── objects.go ├── sbctl │ ├── compatibility.go │ └── support-bundle.go └── util │ └── support-bundle.go ├── sbctl.go └── tests ├── configmaps_test.go ├── pods_test.go ├── results ├── configmaps_all_namespaces.json ├── configmaps_kube_public_namespace.json ├── pods_all_namespaces.json ├── pods_restic_only.json └── pods_velero_namespace.json ├── suite_test.go ├── support-bundle ├── cluster-info │ └── cluster_version.json └── cluster-resources │ ├── auth-cani-list │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── configmaps │ ├── default.json │ ├── kube-node-lease.json │ └── kube-public.json │ ├── cronjobs │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── custom-resource-definitions.json │ ├── custom-resources │ ├── backupstoragelocations.velero.io │ │ └── velero.yaml │ ├── backuptargets.longhorn.io │ │ └── longhorn-system.yaml │ ├── engineimages.longhorn.io │ │ └── longhorn-system.yaml │ ├── engines.longhorn.io │ │ └── longhorn-system.yaml │ ├── installers.cluster.kurl.sh │ │ └── default.yaml │ ├── instancemanagers.longhorn.io │ │ └── longhorn-system.yaml │ ├── nodes.longhorn.io │ │ └── longhorn-system.yaml │ ├── replicas.longhorn.io │ │ └── longhorn-system.yaml │ ├── settings.longhorn.io │ │ └── longhorn-system.yaml │ └── volumes.longhorn.io │ │ └── longhorn-system.yaml │ ├── deployments │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── events │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── groups.json │ ├── image-pull-secrets │ └── default │ │ └── registry-creds.json │ ├── ingress │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── jobs │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── limitranges │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── namespaces.json │ ├── nodes.json │ ├── pods │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── logs │ │ └── velero │ │ │ └── velero-6996dd565b-xl44t │ │ │ ├── replicated-kurl-util.log │ │ │ ├── replicated-local-volume-provider.log │ │ │ ├── velero-previous.log │ │ │ ├── velero-velero-plugin-for-aws.log │ │ │ ├── velero-velero-plugin-for-gcp.log │ │ │ ├── velero-velero-plugin-for-microsoft-azure.log │ │ │ └── velero.log │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── pvcs │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── pvs.json │ ├── replicasets │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── resources.json │ ├── services │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ ├── statefulsets │ ├── default.json │ ├── kube-node-lease.json │ ├── kube-public.json │ ├── kube-system.json │ ├── kurl.json │ ├── longhorn-system.json │ ├── minio.json │ ├── projectcontour.json │ └── velero.json │ └── storage-classes.json └── tests.go /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | version: 2 6 | updates: 7 | - package-ecosystem: "gomod" # See documentation for possible values 8 | directory: "/" # Location of package manifests 9 | labels: 10 | - "dependencies" 11 | - "go" 12 | - "type::security" 13 | schedule: 14 | interval: "daily" 15 | open-pull-requests-limit: 20 16 | groups: 17 | security: 18 | update-types: 19 | - "patch" 20 | - "minor" 21 | 22 | # Maintain dependencies for GitHub Actions 23 | - package-ecosystem: "github-actions" 24 | # Workflow files stored in the 25 | # default location of `.github/workflows` 26 | directory: "/" 27 | labels: 28 | - "dependencies" 29 | - "github-actions" 30 | - "type::security" 31 | schedule: 32 | interval: "weekly" 33 | -------------------------------------------------------------------------------- /.github/workflows/automated-prs-manager.yaml: -------------------------------------------------------------------------------- 1 | name: Automated PRs Manager 2 | 3 | on: 4 | schedule: 5 | - cron: "0 */6 * * *" # every 6 hours 6 | workflow_dispatch: {} 7 | 8 | jobs: 9 | list-prs: 10 | runs-on: ubuntu-latest 11 | outputs: 12 | prs: ${{ steps.list-prs.outputs.prs }} 13 | env: 14 | GH_TOKEN: ${{ secrets.REPLICATED_GH_PAT }} 15 | steps: 16 | - name: Checkout 17 | uses: actions/checkout@v4 18 | 19 | - name: List PRs 20 | id: list-prs 21 | run: | 22 | set -euo pipefail 23 | 24 | # list prs that are less than 24h old and exclude prs from forks 25 | 26 | dependabot_prs=$( 27 | gh pr list \ 28 | --author 'dependabot[bot]' \ 29 | --json url,createdAt,headRefName,headRepository,headRepositoryOwner \ 30 | -q '.[] | select((.createdAt | fromdateiso8601 > now - 24*60*60) and .headRepositoryOwner.login == "replicatedhq" and .headRepository.name == "sbctl")' 31 | ) 32 | 33 | prs=$(echo "$dependabot_prs" | jq -sc '. | unique') 34 | echo "prs=$prs" >> "$GITHUB_OUTPUT" 35 | 36 | process-prs: 37 | needs: list-prs 38 | runs-on: ubuntu-latest 39 | if: needs.list-prs.outputs.prs != '[]' 40 | strategy: 41 | matrix: 42 | pr: ${{ fromJson(needs.list-prs.outputs.prs) }} 43 | fail-fast: false 44 | max-parallel: 1 45 | env: 46 | GH_TOKEN: ${{ secrets.REPLICATED_GH_PAT }} 47 | steps: 48 | - name: Checkout 49 | uses: actions/checkout@v4 50 | with: 51 | ref: ${{ matrix.pr.headRefName }} 52 | 53 | - name: Process PR 54 | run: | 55 | set -euo pipefail 56 | 57 | echo "Ensuring required labels..." 58 | gh pr edit "${{ matrix.pr.url }}" --add-label "type::security" 59 | 60 | echo "Checking status of tests..." 61 | run_id=$(gh run list --branch "${{ matrix.pr.headRefName }}" --workflow build-checks --limit 1 --json databaseId -q '.[0].databaseId') 62 | 63 | # If there are still pending jobs, skip. 64 | 65 | num_of_pending_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[] | select(.conclusion == "") | .name' | wc -l) 66 | if [ "$num_of_pending_jobs" -gt 0 ]; then 67 | echo "There are still pending jobs. Skipping." 68 | exit 0 69 | fi 70 | 71 | # If all checks passed, approve and merge. 72 | if gh run view "$run_id" --json jobs -q '.jobs[] | select(.name == "validate-success") | .conclusion' | grep -q "success"; then 73 | if gh pr checks "${{ matrix.pr.url }}"; then 74 | echo "All tests passed. Approving and merging." 75 | echo -e "LGTM :thumbsup: \n\nThis PR was automatically approved and merged by the [automated-prs-manager](https://github.com/replicatedhq/sbctl/blob/main/.github/workflows/automated-prs-manager.yaml) GitHub action" > body.txt 76 | gh pr review --approve "${{ matrix.pr.url }}" --body-file body.txt 77 | sleep 10 78 | gh pr merge --auto --squash "${{ matrix.pr.url }}" 79 | exit 0 80 | else 81 | echo "Some checks did not pass. Skipping." 82 | exit 0 83 | fi 84 | fi 85 | 86 | # If more than half of the jobs are successful, re-run the failed jobs. 87 | 88 | num_of_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[].name ' | wc -l) 89 | num_of_successful_jobs=$(gh run view "$run_id" --json jobs -q '.jobs[] | select(.conclusion == "success") | .name' | wc -l) 90 | 91 | if [ "$num_of_successful_jobs" -gt $((num_of_jobs / 2)) ]; then 92 | echo "More than half of the jobs are successful. Re-running failed jobs." 93 | gh run rerun "$run_id" --failed 94 | exit 0 95 | fi 96 | 97 | echo "Less than half of the jobs are successful. Skipping." 98 | -------------------------------------------------------------------------------- /.github/workflows/build-checks.yaml: -------------------------------------------------------------------------------- 1 | name: build-checks 2 | 3 | on: 4 | pull_request: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/setup-go@v5 13 | with: 14 | go-version: "1.23" 15 | 16 | - name: setup env 17 | run: | 18 | echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV 19 | echo "$(go env GOPATH)/bin" >> $GITHUB_PATH 20 | shell: bash 21 | 22 | - uses: actions/checkout@v4 23 | - run: | 24 | make install-golangci-lint 25 | echo "golangci-lint path: $(which golangci-lint)" 26 | make lint build 27 | 28 | test: 29 | runs-on: ubuntu-22.04 30 | steps: 31 | - uses: actions/setup-go@v5 32 | with: 33 | go-version: "1.23" 34 | 35 | - name: setup env 36 | run: | 37 | echo "GOPATH=$(go env GOPATH)" >> $GITHUB_ENV 38 | echo "$(go env GOPATH)/bin" >> $GITHUB_PATH 39 | shell: bash 40 | 41 | - uses: actions/checkout@v4 42 | 43 | - run: make ginkgo test 44 | 45 | scan: 46 | runs-on: ubuntu-22.04 47 | steps: 48 | - uses: actions/checkout@v4 49 | - name: Run Trivy vulnerability scanner in repo mode 50 | uses: aquasecurity/trivy-action@master 51 | with: 52 | scan-type: 'fs' 53 | ignore-unfixed: true 54 | format: 'sarif' 55 | exit-code: '1' 56 | scanners: 'vuln' 57 | output: 'trivy-results.sarif' 58 | severity: 'HIGH,CRITICAL' 59 | - name: Upload Trivy scan results to GitHub Security tab 60 | uses: github/codeql-action/upload-sarif@v3 61 | with: 62 | sarif_file: 'trivy-results.sarif' 63 | 64 | # summary jobs, these jobs will only run if all the other jobs have succeeded 65 | validate-pr-tests: 66 | runs-on: ubuntu-latest 67 | needs: 68 | - build 69 | - test 70 | - scan 71 | steps: 72 | - run: echo "All PR tests passed" 73 | 74 | # this job will validate that the validation did not fail and that all pr-tests succeed 75 | # it is used for the github branch protection rule 76 | validate-success: 77 | runs-on: ubuntu-latest 78 | needs: 79 | - validate-pr-tests 80 | if: always() 81 | steps: 82 | # https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context 83 | # if the validate-pr-tests job was not successful, this job will fail 84 | - name: fail if validate-pr-tests job was not successful 85 | if: needs.validate-pr-tests.result != 'success' 86 | run: exit 1 87 | # if the validate-pr-tests job was successful, this job will succeed 88 | - name: succeed if validate-pr-tests job succeeded 89 | if: needs.validate-pr-tests.result == 'success' 90 | run: echo "Validation succeeded" 91 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: deploy 2 | on: 3 | push: 4 | tags: 5 | - "v*.*.*" 6 | 7 | jobs: 8 | goreleaser: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: Checkout 12 | uses: actions/checkout@v4 13 | 14 | - name: Unshallow 15 | run: git fetch --prune --unshallow 16 | 17 | - uses: actions/setup-go@v5 18 | with: 19 | go-version: "1.23" 20 | 21 | - name: Run GoReleaser 22 | uses: goreleaser/goreleaser-action@v6.3.0 23 | with: 24 | version: latest 25 | args: release --clean --config deploy/.goreleaser.yaml 26 | env: 27 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | vendor 3 | dist 4 | 5 | # IDE files 6 | .vscode 7 | .idea 8 | __debug_bin 9 | 10 | # Ignore local pre-commit config 11 | .pre-commit-config.yaml 12 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | # https://golangci-lint.run/usage/configuration/#config-file 2 | 3 | run: 4 | allow-parallel-runners: true 5 | timeout: 300s 6 | 7 | linters: 8 | enable: 9 | - gocritic 10 | - gofmt 11 | - gosec 12 | - govet 13 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | oss@replicated.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Troubleshoot 2 | 3 | Thank you for your interest in sbctl, a supplementary plugin for [troubleshoot.sh](https://github.com/replicatedhq/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 the Troubleshoot.sh project as outlined below: 4 | 5 | 6 | ## Community Meetings 7 | 8 | Community meetings for troubleshoot.sh happen every first Thursday of the month at 11:00 AM Pacific/ 2:00 PM Eastern. Subscribe to the [Replicated Community Calendar](https://calendar.google.com/calendar/u/0?cid=Y19mMGx1aGhiZGtscGllOGo5dWpicXMwNnN1a0Bncm91cC5jYWxlbmRhci5nb29nbGUuY29t) for updates on all events & meetings centered around Replicated Open Source. 9 | 10 | ## Issues 11 | - Create an issue to add functionality that addresses a problem or adds an enhancement. 12 | - [Request a New Feature](https://github.com/replicatedhq/sbctl/issues/new) 13 | - Report a problem or unexpected behaviour with Troubleshoot. 14 | - [Report a Bug](https://github.com/replicatedhq/sbctl/issues) 15 | 16 | ## Pull Requests 17 | 18 | If you are interested in contributing a change to the code or documentation please open a [pull request](https://github.com/replicatedhq/sbctl/pulls) with your set of changes. The pull request will be reviewed in a timely manner. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | BUILDTAGS = "netgo containers_image_ostree_stub exclude_graphdriver_devicemapper exclude_graphdriver_btrfs containers_image_openpgp" 2 | BUILDFLAGS = -tags ${BUILDTAGS} -installsuffix netgo 3 | BUILDPATHS = ./pkg/... ./cli/... ./tests/... 4 | 5 | .PHONY: build 6 | build: mod-tidy fmt vet 7 | go build -o bin/sbctl sbctl.go 8 | 9 | .PHONY: mod-tidy 10 | mod-tidy: 11 | go mod tidy 12 | 13 | # Install/upgrade ginkgo. This version must be the same as 14 | # the one on go.mod. We'll rely on dependabot to upgrade go.mod 15 | .PHONY: ginkgo 16 | ginkgo: 17 | go install github.com/onsi/ginkgo/v2/ginkgo 18 | 19 | .PHONY: test 20 | test: fmt vet 21 | ginkgo -v ./tests/... 22 | go test -v ${BUILDFLAGS} ./pkg/... ./cli/... 23 | 24 | .PHONY: fmt 25 | fmt: 26 | go fmt ${BUILDPATHS} 27 | 28 | .PHONY: vet 29 | vet: 30 | go vet ${BUILDFLAGS} ${BUILDPATHS} 31 | 32 | # Compile and install sbctl locally in you GOBIN path 33 | .PHONY: install 34 | install: build 35 | go install ${BUILDFLAGS} sbctl.go 36 | 37 | .PHONY: lint 38 | lint: 39 | ifeq (, $(shell which golangci-lint)) 40 | $(error "Install golangci-lint by either running 'make install-golangci-lint' or by other means") 41 | endif 42 | golangci-lint run --new -c .golangci.yaml --build-tags ${BUILDTAGS} ${BUILDPATHS} 43 | 44 | .PHONY: lint-and-fix 45 | lint-and-fix: 46 | ifeq (, $(shell which golangci-lint)) 47 | $(error "Install golangci-lint by either running 'make install-golangci-lint' or by other means") 48 | endif 49 | golangci-lint run --new --fix -c .golangci.yaml --build-tags ${BUILDTAGS} ${BUILDPATHS} 50 | 51 | # Not pinning to a particular version so as not to forget updating it 52 | # If unrelated warnings arise due to linter updates or newly introduced linters 53 | # we'll consider pinning. 54 | .PHONY: install-golangci-lint 55 | install-golangci-lint: 56 | go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest 57 | 58 | .PHONY: scan 59 | scan: 60 | trivy fs \ 61 | --scanners vuln \ 62 | --exit-code=1 \ 63 | --severity="HIGH,CRITICAL" \ 64 | --ignore-unfixed \ 65 | ./ 66 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Command line tool for examining K8s resources in Troubleshoot's support bundles 2 | 3 | ### How to install (Mac): 4 | 5 | Download the release binary and untar it to a directory in your `PATH` (you'll need to enter your `sudo` password for the last `mv`): 6 | 7 | #### Intel CPU / `amd64` 8 | 9 | ``` 10 | curl -LO https://github.com/replicatedhq/sbctl/releases/latest/download/sbctl_darwin_amd64.tar.gz 11 | tar -xzf sbctl_darwin_amd64.tar.gz -C /tmp sbctl 12 | rm -f sbctl_darwin_amd64.tar.gz 13 | sudo mv /tmp/sbctl /usr/local/bin/ 14 | ``` 15 | 16 | #### Apple M1 CPU / `arm64` 17 | 18 | ``` 19 | curl -LO https://github.com/replicatedhq/sbctl/releases/latest/download/sbctl_darwin_arm64.tar.gz 20 | tar -xzf sbctl_darwin_arm64.tar.gz -C /tmp sbctl 21 | rm -f sbctl_darwin_arm64.tar.gz 22 | sudo mv /tmp/sbctl /usr/local/bin/ 23 | ``` 24 | 25 | Restart your shell and proceed to "How to Use". 26 | 27 | ### How to Use: 28 | 29 | #### Start server in foreground 30 | Start the local API server using a support bundle and then run the `export` command that comes up to make kubectl target your support bundles API server 31 | 32 | ``` 33 | sbctl serve /Users/username/Downloads/support-bundle-XXXX-XX-XX 34 | 35 | Server is running 36 | 37 | export KUBECONFIG=/var/folders/g2/XXXXXXXXXXX/T/local-kubeconfig-XXXXX 38 | ``` 39 | 40 | #### Start sbctl shell 41 | Start the local API server and create a shell that has `KUBECONFIG` set. With this you can use `kubectl` commands immediately without the need to run `export`. In this example we also show how to download the support bundle from a remote location. We can choose to use `--token=` cli option to pass in an auth token or export `SBCTL_TOKEN=`. In this example I have `SBCTL_TOKEN` in the environment 42 | 43 | ``` 44 | export SBCTL_TOKEN= 45 | ``` 46 | 47 | Now launch the shell 48 | ``` 49 | sbctl shell https://vendor.replicated.com/troubleshoot/analyze/2024-08-02@00:01 50 | API server logs will be written to /var/folders/19/bp6c9chj0sgcpcxmxxl69s040000gn/T/sbctl-server-logs-1413638036 51 | Downloading bundle 52 | Bundle extracted to /var/folders/19/bp6c9chj0sgcpcxmxxl69s040000gn/T/sbctl-2353785059 53 | Starting new shell with KUBECONFIG. Press Ctl-D when done to end the shell and the sbctl server 54 | ``` 55 | 56 | Using `kubectl` should now auth using the generated kubeconfig file. When done, CTRL^C to shut down the API server. 57 | 58 | ``` 59 | $ kubectl get ns 60 | 61 | NAME STATUS AGE 62 | kube-system Active 204d 63 | default Active 204d 64 | kube-public Active 204d 65 | kube-node-lease Active 204d 66 | docker-registry Active 204d 67 | schemahero-system Active 199d 68 | velero Active 135d 69 | postgres-test Active 22d 70 | redis-test Active 22d 71 | nginx-test Active 22d 72 | test Active 10d 73 | ``` 74 | 75 | ``` 76 | $ kubectl get pods -n kube-system 77 | NAME READY STATUS RESTARTS AGE 78 | helm-install-traefik-crd-jk29f 0/1 Completed 0 204d 79 | helm-install-traefik-nf68z 0/1 Completed 1 (204d ago) 204d 80 | svclb-traefik-clk94 2/2 Running 2 (165d ago) 204d 81 | metrics-server-86cbb8457f-g9kdc 1/1 Running 1 (165d ago) 204d 82 | local-path-provisioner-5ff76fc89d-cgpdv 1/1 Running 2 (86d ago) 204d 83 | coredns-7448499f4d-x8fw9 1/1 Running 1 (165d ago) 204d 84 | traefik-97b44b794-mhvsh 1/1 Running 1 (165d ago) 204d 85 | ``` 86 | 87 | ``` 88 | $ kubectl describe pod kotsadm-75d9ff6f44-ssrx6 89 | Name: kotsadm-75d9ff6f44-ssrx6 90 | Namespace: default 91 | Priority: 0 92 | Node: my-node/***HIDDEN*** 93 | Start Time: Tue, 01 Feb 2022 18:31:36 -0800 94 | Labels: app=kotsadm 95 | app.kubernetes.io/name=kotsadm 96 | kots.io/backup=velero 97 | kots.io/kotsadm=true 98 | pod-template-hash=75d9ff6f44 99 | skaffold.dev/run-id=ca77ed45-8a57-44af-ac0f-ec1931c57841 100 | Annotations: backup.velero.io/backup-volumes: backup 101 | pre.hook.backup.velero.io/command: 102 | ["/bin/bash", "-c", "PGPASSWORD=password pg_dump -U kotsadm -h kotsadm-postgres > /backup/kotsadm-postgres.sql"] 103 | pre.hook.backup.velero.io/timeout: 3m 104 | Status: Running 105 | IP: ***HIDDEN*** 106 | IPs: 107 | IP: ***HIDDEN*** 108 | Controlled By: ReplicaSet/kotsadm-75d9ff6f44 109 | Containers: 110 | kotsadm: 111 | Container ID: containerd://84288b23eaf84112248eea8ec2f94a0f8f231036a46715c936c741154173271d 112 | Image: localhost:32000/kotsadm:v1.60.0-26-g4e016d2ff-dirty@sha256:6c2f016f1e99a1f8b2129eb6b93ba59526118bdcada8c8e73f051db4123ff683 113 | Image ID: localhost:32000/kotsadm@sha256:6c2f016f1e99a1f8b2129eb6b93ba59526118bdcada8c8e73f051db4123ff683 114 | Ports: 40000/TCP, 3000/TCP, 9229/TCP 115 | Host Ports: 0/TCP, 0/TCP, 0/TCP 116 | State: Running 117 | Started: Tue, 01 Feb 2022 18:31:39 -0800 118 | Ready: True 119 | Restart Count: 0 120 | Limits: 121 | cpu: 1 122 | memory: 2Gi 123 | Requests: 124 | cpu: 100m 125 | memory: 100Mi 126 | Environment: 127 | POSTGRES_URI: Optional: false 128 | S3_BUCKET_NAME: shipbucket 129 | S3_ENDPOINT: http://kotsadm-s3:4569/ 130 | S3_ACCESS_KEY_ID: ***HIDDEN*** 131 | S3_SECRET_ACCESS_KEY: ***HIDDEN*** 132 | S3_BUCKET_ENDPOINT: true 133 | DEX_PGPASSWORD: Optional: false 134 | KOTSADM_LOG_LEVEL: debug 135 | DISABLE_SPA_SERVING: 1 136 | KOTSADM_TARGET_NAMESPACE: test 137 | AUTO_CREATE_CLUSTER: 1 138 | AUTO_CREATE_CLUSTER_NAME: microk8s 139 | AUTO_CREATE_CLUSTER_TOKEN: ***HIDDEN*** 140 | POD_NAMESPACE: default (v1:metadata.namespace) 141 | SHARED_PASSWORD_BCRYPT: ***HIDDEN*** 142 | SESSION_KEY: this-is-not-too-secret 143 | API_ENCRYPTION_KEY: IvWItkB8+ezMisPjSMBknT1PdKjBx7Xc/txZqOP8Y2Oe7+Jy 144 | REPLICATED_API_ENDPOINT: http://replicated-app:3000 145 | API_ENDPOINT: http://kotsadm:3000 146 | API_ADVERTISE_ENDPOINT: http://***HIDDEN***:30000 147 | KOTSADM_ENV: dev 148 | ENABLE_WEB_PROXY: 1 149 | KURL_PROXY_TLS_CERT_PATH: /etc/kurl-proxy/ca/tls.crt 150 | KOTS_INSTALL_ID: dev-1pu4oeY162e2pbLpK4JubK6hxrX 151 | AIRGAP_UPLOAD_PARALLELISM: 3 152 | POD_OWNER_KIND: deployment 153 | DEBUG: false 154 | Mounts: 155 | /backup from backup (rw) 156 | /etc/kubernetes/pki/kubelet from kubelet-client-cert (rw) 157 | /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-zfw8v (ro) 158 | Conditions: 159 | Type Status 160 | Initialized True 161 | Ready True 162 | ContainersReady True 163 | PodScheduled True 164 | Volumes: 165 | backup: 166 | Type: EmptyDir (a temporary directory that shares a pod's lifetime) 167 | Medium: Memory 168 | SizeLimit: 1Gi 169 | kubelet-client-cert: 170 | Type: Secret (a volume populated by a Secret) 171 | SecretName: kubelet-client-cert 172 | Optional: true 173 | init-dex-db: 174 | Type: ConfigMap (a volume populated by a ConfigMap) 175 | Name: init-dex-db 176 | Optional: false 177 | kube-api-access-zfw8v: 178 | Type: Projected (a volume that contains injected data from multiple sources) 179 | TokenExpirationSeconds: 3607 180 | ConfigMapName: kube-root-ca.crt 181 | ConfigMapOptional: 182 | DownwardAPI: true 183 | QoS Class: Burstable 184 | Node-Selectors: 185 | Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s 186 | node.kubernetes.io/unreachable:NoExecute op=Exists for 300s 187 | ``` 188 | 189 | 190 | ### Interactive: 191 | 192 | Start the interactive shell 193 | ``` 194 | $ sbctl shell -s ~/Downloads/support-bundle-2022-02-03T23_22_37 195 | bash-5.0$ 196 | ``` 197 | 198 | Run `kubectl` commands at the prompt. When done, type `exit`. 199 | 200 | ``` 201 | bash-5.0$ kubectl get nodes 202 | NAME STATUS ROLES AGE VERSION 203 | troubleshoot-demo-001 Ready control-plane,master 2d22h v1.23.5 204 | troubleshoot-demo-002 Ready 2d21h v1.23.5 205 | troubleshoot-demo-003 Ready 2d21h v1.23.5 206 | bash-5.0$ exit 207 | exit 208 | ``` 209 | -------------------------------------------------------------------------------- /cli/download.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "io" 7 | "net/http" 8 | "net/url" 9 | "os" 10 | "path" 11 | 12 | "github.com/pkg/errors" 13 | "github.com/spf13/cobra" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | func DownloadCmd() *cobra.Command { 18 | cmd := &cobra.Command{ 19 | Use: "download", 20 | Short: "Download bundle from Vendor Portal url", 21 | Long: "Download bundle from Vendor Portal url", 22 | Args: cobra.MaximumNArgs(1), 23 | PreRunE: func(cmd *cobra.Command, args []string) error { 24 | return viper.BindPFlags(cmd.Flags()) 25 | }, 26 | RunE: func(cmd *cobra.Command, args []string) error { 27 | v := viper.GetViper() 28 | 29 | // This only works with generated config, so let's make sure we don't mess up user's real files. 30 | bundleLocation := v.GetString("support-bundle-location") 31 | if len(args) > 0 && args[0] != "" { 32 | bundleLocation = args[0] 33 | } 34 | if bundleLocation == "" { 35 | return errors.New("support-bundle-location is required") 36 | } 37 | 38 | token := v.GetString("token") 39 | if token == "" { 40 | return errors.New("token is required when downloading bundle") 41 | } 42 | 43 | fmt.Println("Downloading bundle...") 44 | file, err := downloadBundleToDisk(bundleLocation, token) 45 | if err != nil { 46 | return err 47 | } 48 | fmt.Println(file) 49 | return nil 50 | }, 51 | } 52 | 53 | return cmd 54 | } 55 | 56 | func downloadBundleToDisk(bundleUrl string, token string) (string, error) { 57 | body, err := downloadBundleFromVendorPortal(bundleUrl, token) 58 | if err != nil { 59 | return "", errors.Wrap(err, "failed to download bundle") 60 | } 61 | defer body.Close() 62 | 63 | sbFile, err := os.Create("support-bundle.tgz") 64 | if err != nil { 65 | return "", errors.Wrap(err, "failed to create file") 66 | } 67 | defer sbFile.Close() 68 | 69 | _, err = io.Copy(sbFile, body) 70 | if err != nil { 71 | return "", errors.Wrap(err, "failed to copy bundle to file") 72 | } 73 | 74 | return sbFile.Name(), nil 75 | } 76 | 77 | func downloadBundleFromVendorPortal(bundleUrl, token string) (io.ReadCloser, error) { 78 | parsedUrl, err := url.Parse(bundleUrl) 79 | if err != nil { 80 | return nil, errors.Wrap(err, "failed to parse url") 81 | } 82 | 83 | _, slug := path.Split(parsedUrl.Path) 84 | if slug == "" { 85 | return nil, errors.New("failed to extract slug from URL") 86 | } 87 | sbEndpoint := fmt.Sprintf("https://api.replicated.com/vendor/v3/supportbundle/%s", slug) 88 | req, err := http.NewRequest("GET", sbEndpoint, nil) 89 | if err != nil { 90 | return nil, errors.Wrap(err, "failed to create HTTP request") 91 | } 92 | 93 | req.Header.Add("Authorization", token) 94 | req.Header.Add("Content-Type", "application/json") 95 | 96 | resp, err := http.DefaultClient.Do(req) 97 | if err != nil { 98 | return nil, errors.Wrap(err, "failed to execute request") 99 | } 100 | defer resp.Body.Close() 101 | 102 | body, err := io.ReadAll(resp.Body) 103 | if err != nil { 104 | return nil, errors.Wrap(err, "failed to read GQL response") 105 | } 106 | 107 | if resp.StatusCode != http.StatusOK { 108 | return nil, errors.Errorf("unexpected status code: %v", resp.StatusCode) 109 | } 110 | 111 | bundleObj := struct { 112 | Bundle struct { 113 | SignedUri string `json:"signedUri"` 114 | } `json:"bundle"` 115 | }{} 116 | err = json.Unmarshal(body, &bundleObj) 117 | if err != nil { 118 | return nil, errors.Wrapf(err, "failed to unmarshal response: %s", body) 119 | } 120 | 121 | resp, err = http.Get(bundleObj.Bundle.SignedUri) 122 | if err != nil { 123 | return nil, errors.Wrap(err, "failed to execute signed URL request") 124 | } 125 | 126 | if resp.StatusCode != http.StatusOK { 127 | return nil, errors.Errorf("unexpected status code: %v", resp.StatusCode) 128 | } 129 | 130 | return resp.Body, nil 131 | } 132 | -------------------------------------------------------------------------------- /cli/root.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "os" 5 | "strings" 6 | 7 | "github.com/spf13/cobra" 8 | "github.com/spf13/viper" 9 | ) 10 | 11 | func RootCmd() *cobra.Command { 12 | cmd := &cobra.Command{ 13 | Use: "sbctl", 14 | Short: "Run commands against a support bundle", 15 | Long: `Run commands against a support bundle`, 16 | SilenceUsage: true, 17 | PreRunE: func(cmd *cobra.Command, args []string) error { 18 | return viper.BindPFlags(cmd.Flags()) 19 | }, 20 | } 21 | 22 | cobra.OnInitialize(func() { 23 | viper.SetEnvPrefix("SBCTL") 24 | viper.AutomaticEnv() 25 | }) 26 | 27 | cmd.AddCommand(ServeCmd()) 28 | cmd.AddCommand(ShellCmd()) 29 | cmd.AddCommand(DownloadCmd()) 30 | 31 | viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_")) 32 | 33 | return cmd 34 | } 35 | 36 | func InitAndExecute() { 37 | if err := RootCmd().Execute(); err != nil { 38 | os.Exit(1) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /cli/serve.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "os/signal" 8 | "strings" 9 | 10 | "github.com/pkg/errors" 11 | "github.com/replicatedhq/sbctl/pkg/api" 12 | "github.com/replicatedhq/sbctl/pkg/sbctl" 13 | "github.com/spf13/cobra" 14 | "github.com/spf13/viper" 15 | ) 16 | 17 | func ServeCmd() *cobra.Command { 18 | cmd := &cobra.Command{ 19 | Use: "serve", 20 | Short: "Start API server", 21 | Long: `Start API server`, 22 | Args: cobra.MaximumNArgs(1), 23 | SilenceUsage: true, 24 | SilenceErrors: false, 25 | PreRunE: func(cmd *cobra.Command, args []string) error { 26 | viper.SetEnvPrefix("sbctl") 27 | return viper.BindPFlags(cmd.Flags()) 28 | }, 29 | RunE: func(cmd *cobra.Command, args []string) error { 30 | var kubeConfig string 31 | var bundleDir string 32 | deleteBundleDir := false 33 | 34 | go func() { 35 | signalChan := make(chan os.Signal, 1) 36 | signal.Notify(signalChan, os.Interrupt) 37 | <-signalChan 38 | if kubeConfig != "" { 39 | _ = os.RemoveAll(kubeConfig) 40 | } 41 | if deleteBundleDir && bundleDir != "" { 42 | os.RemoveAll(bundleDir) 43 | } 44 | os.Exit(0) 45 | }() 46 | 47 | v := viper.GetViper() 48 | 49 | // This only works with generated config, so let's make sure we don't mess up user's real files. 50 | bundleLocation := v.GetString("support-bundle-location") 51 | if len(args) > 0 && args[0] != "" { 52 | bundleLocation = args[0] 53 | } 54 | if bundleLocation == "" { 55 | return errors.New("support-bundle-location is required") 56 | } 57 | 58 | if strings.HasPrefix(bundleLocation, "http") { 59 | token := v.GetString("token") 60 | if token == "" { 61 | return errors.New("token is required when downloading bundle") 62 | } 63 | 64 | fmt.Printf("Downloading bundle\n") 65 | 66 | dir, err := downloadAndExtractBundle(bundleLocation, token) 67 | if err != nil { 68 | return errors.Wrap(err, "failed to stat input path") 69 | } 70 | fmt.Printf("Bundle extracted to %s\n", dir) 71 | bundleDir = dir 72 | deleteBundleDir = true 73 | } else { 74 | fileInfo, err := os.Stat(bundleLocation) 75 | if err != nil { 76 | return errors.Wrap(err, "failed to stat input path") 77 | } 78 | 79 | bundleDir = bundleLocation 80 | if !fileInfo.IsDir() { 81 | deleteBundleDir = true 82 | bundleDir, err = os.MkdirTemp("", "sbctl-") 83 | if err != nil { 84 | return errors.Wrap(err, "failed to create temp dir") 85 | } 86 | 87 | err = sbctl.ExtractBundle(bundleLocation, bundleDir) 88 | if err != nil { 89 | return errors.Wrap(err, "failed to extract bundle") 90 | } 91 | } 92 | } 93 | 94 | clusterData, err := sbctl.FindClusterData(bundleDir) 95 | if err != nil { 96 | return errors.Wrap(err, "failed to find cluster data") 97 | } 98 | 99 | // If we did not find cluster data, just don't start the API server 100 | if clusterData.ClusterResourcesDir == "" { 101 | fmt.Println("No cluster resources found in bundle") 102 | return nil 103 | } 104 | 105 | kubeConfig, err = api.StartAPIServer(clusterData, os.Stderr) 106 | if err != nil { 107 | return errors.Wrap(err, "failed to create api server") 108 | 109 | } 110 | defer os.RemoveAll(kubeConfig) 111 | 112 | fmt.Printf("Server is running\n\n") 113 | fmt.Printf("export KUBECONFIG=%s\n\n", kubeConfig) 114 | 115 | <-make(chan struct{}) 116 | 117 | return nil 118 | }, 119 | } 120 | 121 | cmd.Flags().StringP("support-bundle-location", "s", "", "path to support bundle archive, directory, or URL") 122 | cmd.Flags().StringP("token", "t", "", "API token for authentication when fetching on-line bundles") 123 | cmd.Flags().Bool("debug", false, "enable debug logging. This will include HTTP response bodies in logs.") 124 | return cmd 125 | } 126 | 127 | func downloadAndExtractBundle(bundleUrl string, token string) (string, error) { 128 | body, err := downloadBundleFromVendorPortal(bundleUrl, token) 129 | if err != nil { 130 | return "", errors.Wrap(err, "failed to download bundle") 131 | } 132 | defer body.Close() 133 | 134 | tmpFile, err := os.CreateTemp("", "sbctl-bundle-") 135 | if err != nil { 136 | return "", errors.Wrap(err, "failed to create temp file") 137 | } 138 | defer tmpFile.Close() 139 | 140 | _, err = io.Copy(tmpFile, body) 141 | if err != nil { 142 | return "", errors.Wrap(err, "failed to copy bundle to tmp file") 143 | } 144 | 145 | _ = tmpFile.Close() 146 | 147 | bundleDir, err := os.MkdirTemp("", "sbctl-") 148 | if err != nil { 149 | return "", errors.Wrap(err, "failed to create temp dir") 150 | } 151 | 152 | err = sbctl.ExtractBundle(tmpFile.Name(), bundleDir) 153 | if err != nil { 154 | return "", errors.Wrap(err, "failed to extract bundle") 155 | } 156 | 157 | return bundleDir, nil 158 | } 159 | -------------------------------------------------------------------------------- /cli/shell.go: -------------------------------------------------------------------------------- 1 | package cli 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | "os/exec" 8 | "os/signal" 9 | "strings" 10 | "syscall" 11 | 12 | "github.com/creack/pty" 13 | "github.com/pkg/errors" 14 | "github.com/replicatedhq/sbctl/pkg/api" 15 | "github.com/replicatedhq/sbctl/pkg/sbctl" 16 | log "github.com/sirupsen/logrus" 17 | "github.com/spf13/cobra" 18 | "github.com/spf13/viper" 19 | "golang.org/x/term" 20 | ) 21 | 22 | func ShellCmd() *cobra.Command { 23 | cmd := &cobra.Command{ 24 | Use: "shell", 25 | Short: "Start interractive shell", 26 | Long: `Start interractive shell`, 27 | Args: cobra.MaximumNArgs(1), 28 | SilenceUsage: true, 29 | SilenceErrors: false, 30 | PreRunE: func(cmd *cobra.Command, args []string) error { 31 | viper.SetEnvPrefix("sbctl") 32 | return viper.BindPFlags(cmd.Flags()) 33 | }, 34 | RunE: func(cmd *cobra.Command, args []string) error { 35 | var kubeConfig string 36 | var bundleDir string 37 | deleteBundleDir := false 38 | 39 | logOutput := os.Stderr 40 | logFile, err := os.CreateTemp("", "sbctl-server-*.log") 41 | if err == nil { 42 | defer logFile.Close() 43 | defer os.RemoveAll(logFile.Name()) 44 | fmt.Printf("SBCTL logs will be written to %s\n", logFile.Name()) 45 | log.SetOutput(logFile) 46 | logOutput = logFile 47 | } 48 | 49 | cleanup := func() { 50 | if kubeConfig != "" { 51 | _ = os.RemoveAll(kubeConfig) 52 | } 53 | if deleteBundleDir && bundleDir != "" { 54 | _ = os.RemoveAll(bundleDir) 55 | } 56 | } 57 | 58 | go func() { 59 | signalChan := make(chan os.Signal, 1) 60 | // Handle Ctl-D to exit from shell 61 | signal.Notify(signalChan, os.Interrupt) 62 | <-signalChan 63 | cleanup() 64 | os.Exit(0) 65 | }() 66 | 67 | defer func() { 68 | // exit from shell using "exit" command 69 | cleanup() 70 | }() 71 | 72 | v := viper.GetViper() 73 | 74 | // This only works with generated config, so let's make sure we don't mess up user's real files. 75 | bundleLocation := v.GetString("support-bundle-location") 76 | if len(args) > 0 && args[0] != "" { 77 | bundleLocation = args[0] 78 | } 79 | if bundleLocation == "" { 80 | return errors.New("support-bundle-location is required") 81 | } 82 | 83 | if strings.HasPrefix(bundleLocation, "http") { 84 | token := v.GetString("token") 85 | if token == "" { 86 | return errors.New("token is required when downloading bundle") 87 | } 88 | 89 | fmt.Printf("Downloading bundle\n") 90 | 91 | dir, err := downloadAndExtractBundle(bundleLocation, token) 92 | if err != nil { 93 | return errors.Wrap(err, "failed to stat input path") 94 | } 95 | fmt.Printf("Bundle extracted to %s\n", dir) 96 | bundleDir = dir 97 | deleteBundleDir = true 98 | } else { 99 | fileInfo, err := os.Stat(bundleLocation) 100 | if err != nil { 101 | return errors.Wrap(err, "failed to stat input path") 102 | } 103 | 104 | bundleDir = bundleLocation 105 | if !fileInfo.IsDir() { 106 | deleteBundleDir = true 107 | bundleDir, err = os.MkdirTemp("", "sbctl-") 108 | if err != nil { 109 | return errors.Wrap(err, "failed to create temp dir") 110 | } 111 | 112 | err = sbctl.ExtractBundle(bundleLocation, bundleDir) 113 | if err != nil { 114 | return errors.Wrap(err, "failed to extract bundle") 115 | } 116 | } 117 | } 118 | 119 | clusterData, err := sbctl.FindClusterData(bundleDir) 120 | if err != nil { 121 | return errors.Wrap(err, "failed to find cluster data") 122 | } 123 | 124 | // If we did not find cluster data, just don't start the API server 125 | if clusterData.ClusterResourcesDir == "" { 126 | fmt.Println("No cluster resources found in bundle") 127 | fmt.Println("Starting new shell in downloaded bundle. Press Ctl-D when done to exit from the shell") 128 | return startShellAndWait(fmt.Sprintf("cd %s", bundleDir)) 129 | } 130 | 131 | kubeConfig, err = api.StartAPIServer(clusterData, logOutput) 132 | if err != nil { 133 | return errors.Wrap(err, "failed to create api server") 134 | } 135 | defer os.RemoveAll(kubeConfig) 136 | 137 | cmds := []string{ 138 | fmt.Sprintf("export KUBECONFIG=%s", kubeConfig), 139 | } 140 | if v.GetBool("cd-bundle") { 141 | cmds = append(cmds, fmt.Sprintf("cd %s", bundleDir)) 142 | } 143 | fmt.Printf("Starting new shell with KUBECONFIG. Press Ctl-D when done to exit from the shell and stop sbctl server\n") 144 | return startShellAndWait(cmds...) 145 | }, 146 | } 147 | 148 | cmd.Flags().StringP("support-bundle-location", "s", "", "path to support bundle archive, directory, or URL") 149 | cmd.Flags().StringP("token", "t", "", "API token for authentication when fetching on-line bundles") 150 | cmd.Flags().Bool("cd-bundle", false, "Change directory to the support bundle path after starting the shell") 151 | cmd.Flags().Bool("debug", false, "enable debug logging. This will include HTTP response bodies in logs.") 152 | return cmd 153 | } 154 | 155 | func startShellAndWait(cmds ...string) error { 156 | shellCmd := os.Getenv("SHELL") 157 | if shellCmd == "" { 158 | return errors.New("SHELL environment is required for shell command") 159 | } 160 | 161 | shellExec := exec.Command(shellCmd) 162 | shellExec.Env = os.Environ() 163 | shellPty, err := pty.Start(shellExec) 164 | if err != nil { 165 | return errors.Wrap(err, "failed to start shell") 166 | } 167 | 168 | // Handle pty size. 169 | ch := make(chan os.Signal, 1) 170 | signal.Notify(ch, syscall.SIGWINCH) 171 | go func() { 172 | for range ch { 173 | if err := pty.InheritSize(os.Stdin, shellPty); err != nil { 174 | log.Printf("error resizing pty: %s", err) 175 | } 176 | } 177 | }() 178 | ch <- syscall.SIGWINCH // Initial resize. 179 | defer func() { signal.Stop(ch); close(ch) }() 180 | 181 | // Set stdin to raw mode. 182 | oldState, err := term.MakeRaw(syscall.Stdin) 183 | if err != nil { 184 | panic(err) 185 | } 186 | defer func() { 187 | _ = term.Restore(syscall.Stdin, oldState) 188 | fmt.Printf("sbctl shell exited\n") 189 | }() 190 | 191 | // Setup the shell 192 | setupCmd := strings.Join(cmds, "\n") + "\n" 193 | _, _ = io.WriteString(shellPty, setupCmd) 194 | _, _ = io.CopyN(io.Discard, shellPty, 2*int64(len(setupCmd))) // Don't print to screen, terminal will echo anyway 195 | 196 | // Copy stdin to the pty and the pty to stdout. 197 | go func() { _, _ = io.Copy(shellPty, os.Stdin) }() 198 | go func() { _, _ = io.Copy(os.Stdout, shellPty) }() 199 | 200 | return shellExec.Wait() 201 | } 202 | -------------------------------------------------------------------------------- /deploy/.goreleaser.yaml: -------------------------------------------------------------------------------- 1 | project_name: sbctl 2 | release: 3 | github: 4 | owner: replicatedhq 5 | name: sbctl 6 | builds: 7 | - id: sbctl 8 | goos: 9 | - linux 10 | - darwin 11 | goarch: 12 | - amd64 13 | - arm64 14 | env: 15 | - CGO_ENABLED=0 16 | - GO111MODULE=on 17 | main: sbctl.go 18 | ldflags: -s -w 19 | binary: sbctl 20 | hooks: {} 21 | 22 | archives: 23 | - id: sbctl 24 | builds: 25 | - sbctl 26 | format: tar.gz 27 | name_template: "{{ .Binary }}_{{ .Os }}_{{ .Arch }}" 28 | files: 29 | - licence* 30 | - LICENCE* 31 | - license* 32 | - LICENSE* 33 | - readme* 34 | - README* 35 | - changelog* 36 | - CHANGELOG* 37 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/replicatedhq/sbctl 2 | 3 | go 1.23.4 4 | 5 | require ( 6 | github.com/antzucaro/matchr v0.0.0-20210222213004-b04723ef80f0 7 | github.com/creack/pty v1.1.24 8 | github.com/golang/gddo v0.0.0-20210115222349-20d68f94ee1f 9 | github.com/gorilla/handlers v1.5.2 10 | github.com/gorilla/mux v1.8.1 11 | github.com/onsi/ginkgo/v2 v2.23.4 12 | github.com/onsi/gomega v1.37.0 13 | github.com/pkg/errors v0.9.1 14 | github.com/sirupsen/logrus v1.9.3 15 | github.com/spf13/cobra v1.9.1 16 | github.com/spf13/viper v1.20.1 17 | golang.org/x/term v0.31.0 18 | gopkg.in/yaml.v2 v2.4.0 19 | k8s.io/api v0.32.3 20 | k8s.io/apiextensions-apiserver v0.32.3 21 | k8s.io/apimachinery v0.32.3 22 | k8s.io/apiserver v0.32.3 23 | k8s.io/client-go v0.32.3 24 | k8s.io/kubectl v0.32.3 25 | k8s.io/kubernetes v1.32.4 26 | ) 27 | 28 | require ( 29 | cel.dev/expr v0.18.0 // indirect 30 | github.com/NYTimes/gziphandler v1.1.1 // indirect 31 | github.com/antlr4-go/antlr/v4 v4.13.0 // indirect 32 | github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect 33 | github.com/beorn7/perks v1.0.1 // indirect 34 | github.com/blang/semver/v4 v4.0.0 // indirect 35 | github.com/cenkalti/backoff/v4 v4.3.0 // indirect 36 | github.com/cespare/xxhash/v2 v2.3.0 // indirect 37 | github.com/coreos/go-semver v0.3.1 // indirect 38 | github.com/coreos/go-systemd/v22 v22.5.0 // indirect 39 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect 40 | github.com/distribution/reference v0.6.0 // indirect 41 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 42 | github.com/felixge/httpsnoop v1.0.4 // indirect 43 | github.com/fsnotify/fsnotify v1.8.0 // indirect 44 | github.com/fxamacker/cbor/v2 v2.7.0 // indirect 45 | github.com/go-logr/logr v1.4.2 // indirect 46 | github.com/go-logr/stdr v1.2.2 // indirect 47 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 48 | github.com/go-openapi/jsonreference v0.20.2 // indirect 49 | github.com/go-openapi/swag v0.23.0 // indirect 50 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect 51 | github.com/go-viper/mapstructure/v2 v2.2.1 // indirect 52 | github.com/gogo/protobuf v1.3.2 // indirect 53 | github.com/golang/protobuf v1.5.4 // indirect 54 | github.com/google/btree v1.0.1 // indirect 55 | github.com/google/cel-go v0.22.0 // indirect 56 | github.com/google/gnostic-models v0.6.8 // indirect 57 | github.com/google/go-cmp v0.7.0 // indirect 58 | github.com/google/gofuzz v1.2.0 // indirect 59 | github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 // indirect 60 | github.com/google/uuid v1.6.0 // indirect 61 | github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect 62 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect 63 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 64 | github.com/josharian/intern v1.0.0 // indirect 65 | github.com/json-iterator/go v1.1.12 // indirect 66 | github.com/mailru/easyjson v0.7.7 // indirect 67 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 68 | github.com/modern-go/reflect2 v1.0.2 // indirect 69 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 70 | github.com/opencontainers/go-digest v1.0.0 // indirect 71 | github.com/pelletier/go-toml/v2 v2.2.3 // indirect 72 | github.com/prometheus/client_golang v1.19.1 // indirect 73 | github.com/prometheus/client_model v0.6.1 // indirect 74 | github.com/prometheus/common v0.55.0 // indirect 75 | github.com/prometheus/procfs v0.15.1 // indirect 76 | github.com/sagikazarmark/locafero v0.7.0 // indirect 77 | github.com/sourcegraph/conc v0.3.0 // indirect 78 | github.com/spf13/afero v1.12.0 // indirect 79 | github.com/spf13/cast v1.7.1 // indirect 80 | github.com/spf13/pflag v1.0.6 // indirect 81 | github.com/stoewer/go-strcase v1.3.0 // indirect 82 | github.com/subosito/gotenv v1.6.0 // indirect 83 | github.com/x448/float16 v0.8.4 // indirect 84 | go.etcd.io/etcd/api/v3 v3.5.16 // indirect 85 | go.etcd.io/etcd/client/pkg/v3 v3.5.16 // indirect 86 | go.etcd.io/etcd/client/v3 v3.5.16 // indirect 87 | go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.54.0 // indirect 88 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect 89 | go.opentelemetry.io/otel v1.29.0 // indirect 90 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect 91 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect 92 | go.opentelemetry.io/otel/metric v1.29.0 // indirect 93 | go.opentelemetry.io/otel/sdk v1.29.0 // indirect 94 | go.opentelemetry.io/otel/trace v1.29.0 // indirect 95 | go.opentelemetry.io/proto/otlp v1.3.1 // indirect 96 | go.uber.org/automaxprocs v1.6.0 // indirect 97 | go.uber.org/multierr v1.11.0 // indirect 98 | go.uber.org/zap v1.27.0 // indirect 99 | golang.org/x/crypto v0.36.0 // indirect 100 | golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect 101 | golang.org/x/net v0.38.0 // indirect 102 | golang.org/x/oauth2 v0.25.0 // indirect 103 | golang.org/x/sync v0.12.0 // indirect 104 | golang.org/x/sys v0.32.0 // indirect 105 | golang.org/x/text v0.23.0 // indirect 106 | golang.org/x/time v0.8.0 // indirect 107 | golang.org/x/tools v0.31.0 // indirect 108 | google.golang.org/genproto/googleapis/api v0.0.0-20241209162323-e6fa225c2576 // indirect 109 | google.golang.org/genproto/googleapis/rpc v0.0.0-20241223144023-3abc09e42ca8 // indirect 110 | google.golang.org/grpc v1.67.3 // indirect 111 | google.golang.org/protobuf v1.36.5 // indirect 112 | gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect 113 | gopkg.in/inf.v0 v0.9.1 // indirect 114 | gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect 115 | gopkg.in/yaml.v3 v3.0.1 // indirect 116 | k8s.io/cloud-provider v0.32.0 // indirect 117 | k8s.io/component-base v0.32.3 // indirect 118 | k8s.io/component-helpers v0.32.3 // indirect 119 | k8s.io/controller-manager v0.32.0 // indirect 120 | k8s.io/klog/v2 v2.130.1 // indirect 121 | k8s.io/kms v0.32.3 // indirect 122 | k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect 123 | k8s.io/kubelet v0.32.0 // indirect 124 | k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect 125 | sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect 126 | sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect 127 | sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect 128 | sigs.k8s.io/yaml v1.4.0 // indirect 129 | ) 130 | -------------------------------------------------------------------------------- /pkg/api/client.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "io" 6 | "os" 7 | 8 | "github.com/pkg/errors" 9 | ) 10 | 11 | func createConfigFile(endPoint string) (string, error) { 12 | ctxTemplate := ` 13 | apiVersion: v1 14 | kind: Config 15 | preferences: {} 16 | current-context: default 17 | clusters: 18 | - name: default 19 | cluster: 20 | server: %s 21 | contexts: 22 | - name: default 23 | context: 24 | cluster: default 25 | user: default 26 | users: 27 | - name: default 28 | user: {} 29 | ` 30 | 31 | configString := fmt.Sprintf(ctxTemplate, endPoint) 32 | kubeconfigFile, err := os.CreateTemp("", "local-kubeconfig-") 33 | if err != nil { 34 | return "", errors.Wrap(err, "failed to create config file") 35 | } 36 | defer kubeconfigFile.Close() 37 | 38 | if _, err := io.WriteString(kubeconfigFile, configString); err != nil { 39 | return "", errors.Wrap(err, "failed to write config file") 40 | } 41 | 42 | return kubeconfigFile.Name(), nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/api/logs.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | "path/filepath" 8 | "strconv" 9 | 10 | "github.com/gorilla/mux" 11 | log "github.com/sirupsen/logrus" 12 | ) 13 | 14 | func (h handler) getAPIV1NamespaceResourceLog(w http.ResponseWriter, r *http.Request) { 15 | log.Println("called getAPIV1NamespaceResourceLog") 16 | 17 | namespace := mux.Vars(r)["namespace"] 18 | resource := mux.Vars(r)["resource"] 19 | name := mux.Vars(r)["name"] 20 | container := r.URL.Query().Get("container") 21 | previous, _ := strconv.ParseBool(r.URL.Query().Get("previous")) 22 | 23 | logFileName := fmt.Sprintf("%s.log", container) 24 | if previous { 25 | logFileName = fmt.Sprintf("%s-previous.log", container) 26 | } 27 | 28 | fileName := filepath.Join(h.clusterData.ClusterResourcesDir, resource, "logs", namespace, name, logFileName) 29 | data, err := readFileAndLog(fileName) 30 | if err != nil { 31 | log.Error("failed to load file :", err) 32 | if os.IsNotExist(err) { 33 | // try reading from -logs-errors.log file 34 | errFileName := filepath.Join(h.clusterData.ClusterResourcesDir, resource, "logs", namespace, name, fmt.Sprintf("%s-logs-errors.log", container)) 35 | data, err = readFileAndLog(errFileName) 36 | if err != nil { 37 | if os.IsNotExist(err) { 38 | PlainText(w, http.StatusNotFound, []byte(fmt.Sprintf("log files not found in support-bundle.\n%v\n%v", fileName, errFileName))) 39 | return 40 | } 41 | w.WriteHeader(http.StatusInternalServerError) 42 | return 43 | } 44 | } else { 45 | w.WriteHeader(http.StatusInternalServerError) 46 | return 47 | } 48 | } 49 | PlainText(w, http.StatusOK, data) 50 | } 51 | 52 | func PlainText(w http.ResponseWriter, responseCode int, responseBody []byte) { 53 | w.Header().Set("Content-Type", "text/plain") 54 | w.WriteHeader(responseCode) 55 | _, err := w.Write(responseBody) 56 | if err != nil { 57 | log.Error("Failed to write response: ", err) 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /pkg/api/middleware.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "bufio" 5 | "bytes" 6 | "encoding/json" 7 | "io" 8 | "net" 9 | "net/http" 10 | 11 | log "github.com/sirupsen/logrus" 12 | "github.com/spf13/viper" 13 | ) 14 | 15 | type requestResponseDumper struct { 16 | io.Writer 17 | http.ResponseWriter 18 | } 19 | 20 | // dumpRequestResponse is a middleware that logs the request and response if the 21 | // --debug flag is set. It tries to format the requests and responses as indented JSON 22 | func dumpRequestResponse(next http.Handler) http.Handler { 23 | return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 24 | if viper.GetBool("debug") { 25 | // Request header 26 | logObject("Request headers", r.Header) 27 | // Request 28 | reqBody := []byte{} 29 | if r.Body != nil { // Read 30 | reqBody, _ = io.ReadAll(r.Body) 31 | } 32 | r.Body = io.NopCloser(bytes.NewBuffer(reqBody)) // Reset 33 | if len(reqBody) > 0 { 34 | logObject("Request", reqBody) 35 | } 36 | 37 | // Response 38 | resBody := new(bytes.Buffer) 39 | mw := io.MultiWriter(w, resBody) 40 | writer := &requestResponseDumper{Writer: mw, ResponseWriter: w} 41 | w = writer 42 | 43 | next.ServeHTTP(w, r) 44 | 45 | logObject("Response", resBody.Bytes()) 46 | } else { 47 | next.ServeHTTP(w, r) 48 | } 49 | }) 50 | } 51 | 52 | func (w *requestResponseDumper) WriteHeader(code int) { 53 | w.ResponseWriter.WriteHeader(code) 54 | } 55 | 56 | func (w *requestResponseDumper) Write(b []byte) (int, error) { 57 | return w.Writer.Write(b) 58 | } 59 | 60 | func (w *requestResponseDumper) Flush() { 61 | if flusher, ok := w.ResponseWriter.(http.Flusher); ok { 62 | flusher.Flush() 63 | } 64 | } 65 | 66 | func (w *requestResponseDumper) Hijack() (net.Conn, *bufio.ReadWriter, error) { 67 | return w.ResponseWriter.(http.Hijacker).Hijack() 68 | } 69 | 70 | func logObject(prefix string, o interface{}) { 71 | switch v := o.(type) { 72 | case string: 73 | m := map[string]interface{}{} 74 | err := json.Unmarshal([]byte(v), &m) 75 | if err == nil { 76 | logAsJSON(prefix, m) 77 | } else { 78 | log.Printf("%s: %v\n", prefix, o) 79 | } 80 | case []uint8: 81 | m := map[string]interface{}{} 82 | err := json.Unmarshal(v, &m) 83 | if err == nil { 84 | logAsJSON(prefix, m) 85 | } else { 86 | log.Printf("%s: %v\n", prefix, o) 87 | } 88 | default: 89 | logAsJSON(prefix, o) 90 | } 91 | } 92 | 93 | func logAsJSON(prefix string, o interface{}) { 94 | data, err := json.MarshalIndent(o, "", " ") 95 | if err == nil { 96 | log.Printf("%s: %s\n", prefix, data) 97 | } else { 98 | log.Printf("%s: %v\n", prefix, o) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /pkg/k8s/objects.go: -------------------------------------------------------------------------------- 1 | package k8s 2 | 3 | import ( 4 | corev1 "k8s.io/api/core/v1" 5 | "k8s.io/apimachinery/pkg/runtime/schema" 6 | ) 7 | 8 | func GetEmptyEventList() *corev1.EventList { 9 | r := &corev1.EventList{ 10 | Items: []corev1.Event{}, 11 | } 12 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 13 | Version: "v1", 14 | Kind: "EventList", 15 | }) 16 | return r 17 | } 18 | 19 | func GetEmptyPodList() *corev1.PodList { 20 | r := &corev1.PodList{ 21 | Items: []corev1.Pod{}, 22 | } 23 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 24 | Version: "v1", 25 | Kind: "PodList", 26 | }) 27 | return r 28 | } 29 | 30 | func GetEmptyLimitRangeList() *corev1.LimitRangeList { 31 | r := &corev1.LimitRangeList{ 32 | Items: []corev1.LimitRange{}, 33 | } 34 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 35 | Version: "v1", 36 | Kind: "LimitRangeList", 37 | }) 38 | return r 39 | } 40 | 41 | func GetEmptyServiceList() *corev1.ServiceList { 42 | r := &corev1.ServiceList{ 43 | Items: []corev1.Service{}, 44 | } 45 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 46 | Version: "v1", 47 | Kind: "ServiceList", 48 | }) 49 | return r 50 | } 51 | 52 | func GetEmptyPersistentVolumeClaimList() *corev1.PersistentVolumeClaimList { 53 | r := &corev1.PersistentVolumeClaimList{ 54 | Items: []corev1.PersistentVolumeClaim{}, 55 | } 56 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 57 | Version: "v1", 58 | Kind: "PersistentVolumeClaimList", 59 | }) 60 | return r 61 | } 62 | 63 | func GetEmptyConfigMapList() *corev1.ConfigMapList { 64 | r := &corev1.ConfigMapList{ 65 | Items: []corev1.ConfigMap{}, 66 | } 67 | r.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 68 | Version: "v1", 69 | Kind: "ConfigMapList", 70 | }) 71 | return r 72 | } 73 | -------------------------------------------------------------------------------- /pkg/sbctl/compatibility.go: -------------------------------------------------------------------------------- 1 | package sbctl 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "sort" 7 | 8 | "github.com/pkg/errors" 9 | log "github.com/sirupsen/logrus" 10 | appsv1 "k8s.io/api/apps/v1" 11 | batchv1 "k8s.io/api/batch/v1" 12 | batchv1beta1 "k8s.io/api/batch/v1beta1" 13 | corev1 "k8s.io/api/core/v1" 14 | storagev1 "k8s.io/api/storage/v1" 15 | extensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" 16 | "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 17 | "k8s.io/apimachinery/pkg/runtime" 18 | "k8s.io/apimachinery/pkg/runtime/schema" 19 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 20 | "k8s.io/kubectl/pkg/scheme" 21 | ) 22 | 23 | func init() { 24 | utilruntime.Must(extensionsv1.AddToScheme(scheme.Scheme)) 25 | } 26 | 27 | func Decode(resource string, data []byte) (runtime.Object, *schema.GroupVersionKind, error) { 28 | originalData := data 29 | decode := scheme.Codecs.UniversalDeserializer().Decode 30 | decoded, gvk, err := decode(data, nil, nil) 31 | if err == nil { 32 | return decoded, gvk, nil 33 | } 34 | 35 | log.Warn("could not to decode data, will try adding list GVK", err) 36 | data, err = wrapListData(resource, data) 37 | if err != nil { 38 | log.Warn(err) 39 | } else { 40 | decoded, gvk, err = decode(data, nil, nil) 41 | if err != nil { 42 | log.Warn("could not decode wrapped data: ", err) 43 | } 44 | } 45 | 46 | if decoded == nil { 47 | // Try to decode object into an unstructured object 48 | var v unstructured.Unstructured 49 | err = json.Unmarshal(originalData, &v) 50 | if err == nil { 51 | o := v.DeepCopyObject() 52 | gvk := o.GetObjectKind().GroupVersionKind() 53 | return o, &gvk, nil 54 | } 55 | log.Warn("could not decode data into an unstructured object: ", err) 56 | 57 | // Try to decode object into an unstructured list 58 | var vList []unstructured.Unstructured 59 | err = json.Unmarshal(originalData, &vList) 60 | if err == nil && len(vList) > 0 { 61 | o := vList[0].DeepCopyObject() 62 | gvk := o.GetObjectKind().GroupVersionKind() 63 | list := unstructured.UnstructuredList{} 64 | list.SetGroupVersionKind(gvk) 65 | list.Items = append(list.Items, vList...) 66 | return &list, &gvk, nil 67 | } 68 | if err != nil { 69 | log.Warn("could not decode data into an unstructured list object: ", err) 70 | } 71 | return nil, nil, errors.Wrap(err, "could not decode data into a k8s object") 72 | } 73 | 74 | switch o := decoded.(type) { 75 | case *corev1.EventList: 76 | for i := range o.Items { 77 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 78 | Kind: "Event", 79 | Version: "v1", 80 | }) 81 | } 82 | case *corev1.PodList: 83 | for i := range o.Items { 84 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 85 | Kind: "Pod", 86 | Version: "v1", 87 | }) 88 | } 89 | case *corev1.LimitRangeList: 90 | for i := range o.Items { 91 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 92 | Kind: "LimitRange", 93 | Version: "v1", 94 | }) 95 | } 96 | case *corev1.ServiceList: 97 | for i := range o.Items { 98 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 99 | Kind: "Service", 100 | Version: "v1", 101 | }) 102 | } 103 | case *corev1.NamespaceList: 104 | for i := range o.Items { 105 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 106 | Kind: "Namespace", 107 | Version: "v1", 108 | }) 109 | } 110 | case *corev1.NodeList: 111 | for i := range o.Items { 112 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 113 | Kind: "Node", 114 | Version: "v1", 115 | }) 116 | } 117 | case *corev1.PersistentVolumeList: 118 | for i := range o.Items { 119 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 120 | Kind: "PersistentVolume", 121 | Version: "v1", 122 | }) 123 | } 124 | case *corev1.PersistentVolumeClaimList: 125 | for i := range o.Items { 126 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 127 | Kind: "PersistentVolumeClaim", 128 | Version: "v1", 129 | }) 130 | } 131 | case *batchv1.JobList: 132 | for i := range o.Items { 133 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 134 | Group: "batch", 135 | Kind: "Job", 136 | Version: "v1", 137 | }) 138 | } 139 | case *batchv1beta1.CronJobList: 140 | for i := range o.Items { 141 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 142 | Group: "batch", 143 | Kind: "CronJob", 144 | Version: "v1beta1", 145 | }) 146 | } 147 | case *appsv1.DeploymentList: 148 | for i := range o.Items { 149 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 150 | Group: "apps", 151 | Kind: "Deployment", 152 | Version: "v1", 153 | }) 154 | } 155 | case *appsv1.ReplicaSetList: 156 | for i := range o.Items { 157 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 158 | Group: "apps", 159 | Kind: "ReplicaSet", 160 | Version: "v1", 161 | }) 162 | } 163 | case *appsv1.StatefulSetList: 164 | for i := range o.Items { 165 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 166 | Group: "apps", 167 | Kind: "StatefulSet", 168 | Version: "v1", 169 | }) 170 | } 171 | case *storagev1.StorageClassList: 172 | for i := range o.Items { 173 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 174 | Group: "storage.k8s.io", 175 | Kind: "StorageClass", 176 | Version: "v1", 177 | }) 178 | } 179 | case *extensionsv1.CustomResourceDefinitionList: 180 | for i := range o.Items { 181 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 182 | Group: "apiextensions.k8s.io", 183 | Kind: "CustomResourceDefinitionList", 184 | Version: "v1", 185 | }) 186 | } 187 | case *corev1.ConfigMapList: 188 | for i := range o.Items { 189 | o.Items[i].GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{ 190 | Kind: "ConfigMap", 191 | Version: "v1", 192 | }) 193 | } 194 | } 195 | 196 | return decoded, gvk, nil 197 | } 198 | 199 | func wrapListData(resource string, data []byte) ([]byte, error) { 200 | var kind, apiVersion string 201 | switch resource { 202 | case "pods": 203 | kind = "PodList" 204 | apiVersion = "v1" 205 | case "events": 206 | kind = "EventList" 207 | apiVersion = "v1" 208 | case "cronjobs": 209 | kind = "CronJobList" 210 | apiVersion = "batch/v1beta1" 211 | case "deployments": 212 | kind = "DeploymentList" 213 | apiVersion = "apps/v1" 214 | case "ingress", "ingresses": 215 | kind = "IngressList" 216 | apiVersion = "networking.k8s.io/v1" 217 | case "jobs": 218 | kind = "JobList" 219 | apiVersion = "batch/v1" 220 | case "limitranges": 221 | kind = "LimitRangeList" 222 | apiVersion = "v1" 223 | case "pvcs": 224 | kind = "PersistentVolumeClaimList" 225 | apiVersion = "v1" 226 | case "replicasets": 227 | kind = "ReplicaSetList" 228 | apiVersion = "apps/v1" 229 | case "services": 230 | kind = "ServiceList" 231 | apiVersion = "v1" 232 | case "statefulsets": 233 | kind = "StatefulSetList" 234 | apiVersion = "apps/v1" 235 | case "namespaces": 236 | kind = "NamespaceList" 237 | apiVersion = "v1" 238 | case "nodes": 239 | kind = "NodeList" 240 | apiVersion = "v1" 241 | case "persistentvolumes": 242 | kind = "PersistentVolumeList" 243 | apiVersion = "v1" 244 | case "persistentvolumeclaims": 245 | kind = "PersistentVolumeClaimList" 246 | apiVersion = "v1" 247 | case "storageclasses": 248 | kind = "StorageClassList" 249 | apiVersion = "storage.k8s.io/v1" 250 | case "customresourcedefinitions": 251 | kind = "CustomResourceDefinitionList" 252 | apiVersion = "apiextensions.k8s.io/v1" 253 | default: 254 | return nil, errors.Errorf("don't know how to wrap %s", resource) 255 | } 256 | 257 | return []byte(fmt.Sprintf(`{ 258 | "kind": "%s", 259 | "apiVersion": "%s", 260 | "metadata": { 261 | "resourceVersion": "1" 262 | }, 263 | "items": %s 264 | }`, kind, apiVersion, data)), nil 265 | } 266 | 267 | func ToUnstructured(o runtime.Object) (*unstructured.Unstructured, error) { 268 | data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(o) 269 | if err != nil { 270 | return nil, err 271 | } 272 | 273 | return &unstructured.Unstructured{Object: data}, nil 274 | } 275 | 276 | func ToUnstructuredList(o runtime.Object) (*unstructured.UnstructuredList, error) { 277 | obj, err := ToUnstructured(o) 278 | if err != nil { 279 | return nil, err 280 | } 281 | 282 | return obj.ToList() 283 | } 284 | 285 | func SortUnstructuredList(list *unstructured.UnstructuredList) { 286 | sort.Slice(list.Items, func(i, j int) bool { 287 | iT := list.Items[i].GetCreationTimestamp() 288 | jT := list.Items[j].GetCreationTimestamp() 289 | return iT.Before(&jT) 290 | }) 291 | } 292 | -------------------------------------------------------------------------------- /pkg/sbctl/support-bundle.go: -------------------------------------------------------------------------------- 1 | package sbctl 2 | 3 | import ( 4 | "archive/tar" 5 | "compress/gzip" 6 | "io" 7 | "os" 8 | "path/filepath" 9 | 10 | "github.com/pkg/errors" 11 | ) 12 | 13 | type ClusterData struct { 14 | ClusterInfoFile string 15 | ClusterResourcesDir string 16 | } 17 | 18 | func ExtractBundle(filename string, outDir string) error { 19 | fileReader, err := os.Open(filename) 20 | if err != nil { 21 | return errors.Wrap(err, "failed to open input file") 22 | } 23 | 24 | gzf, err := gzip.NewReader(fileReader) 25 | if err != nil { 26 | return errors.Wrap(err, "failed to get new gzip reader") 27 | } 28 | 29 | tarReader := tar.NewReader(gzf) 30 | 31 | for { 32 | header, err := tarReader.Next() 33 | 34 | if err == io.EOF { 35 | return nil 36 | } 37 | 38 | if err != nil { 39 | return errors.Wrap(err, "failed to read tar header") 40 | } 41 | 42 | if header.Typeflag != tar.TypeReg { 43 | continue 44 | } 45 | 46 | err = func() error { 47 | outFilename := filepath.Join(outDir, header.Name) // nolint: gosec // ignore decompression bombs 48 | outPath := filepath.Dir(outFilename) 49 | err = os.MkdirAll(outPath, 0755) 50 | if err != nil { 51 | return errors.Wrap(err, "failed to create file path") 52 | } 53 | 54 | outFile, err := os.Create(outFilename) 55 | if err != nil { 56 | return errors.Wrap(err, "failed to create output file") 57 | } 58 | defer outFile.Close() 59 | 60 | // ignore decompression bombs 61 | _, err = io.Copy(outFile, tarReader) // nolint: gosec // ignore decompression bombs) 62 | if err != nil { 63 | return errors.Wrap(err, "failed to copy file") 64 | } 65 | 66 | return nil 67 | }() 68 | 69 | if err != nil { 70 | return err 71 | } 72 | } 73 | } 74 | 75 | func FindClusterData(bundlePath string) (ClusterData, error) { 76 | result := ClusterData{} 77 | 78 | err := filepath.Walk(bundlePath, func(path string, info os.FileInfo, err error) error { 79 | if err != nil { 80 | return err 81 | } 82 | 83 | if info.IsDir() { 84 | if info.Name() == "cluster-resources" { 85 | // Support bundle can have multiple cluster-resources directories. 86 | // We want the one at the root, so find the file with the shortest name 87 | if result.ClusterResourcesDir == "" || len(path) < len(result.ClusterResourcesDir) { 88 | result.ClusterResourcesDir = path 89 | } 90 | } 91 | } else if info.Name() == "cluster_version.json" { 92 | result.ClusterInfoFile = path 93 | } 94 | 95 | return nil 96 | }) 97 | 98 | if err != nil { 99 | return result, errors.Wrap(err, "failed to walk bundle dir") 100 | } 101 | 102 | return result, nil 103 | } 104 | -------------------------------------------------------------------------------- /pkg/util/support-bundle.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | var ( 4 | // sbResourceCompatibilityMap 5 | sbResourceCompatibilityMap = map[string]string{ 6 | "persistentvolumeclaims": "pvcs", 7 | "persistentvolumes": "pvs", 8 | "storageclasses": "storage-classes", 9 | "ingresses": "ingress", 10 | "customresourcedefinitions": "custom-resource-definitions", 11 | "clusterrolebindings": "clusterRoleBindings", 12 | "networkpolicies": "network-policy", 13 | } 14 | ) 15 | 16 | // GetSBCompatibleResourceName returns SupportBundle compatible resource name if exists else the same resource name 17 | func GetSBCompatibleResourceName(resource string) string { 18 | if val, ok := sbResourceCompatibilityMap[resource]; ok { 19 | return val 20 | } 21 | return resource 22 | } 23 | -------------------------------------------------------------------------------- /sbctl.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/replicatedhq/sbctl/cli" 5 | _ "k8s.io/client-go/plugin/pkg/client/auth" 6 | ) 7 | 8 | func main() { 9 | cli.InitAndExecute() 10 | } 11 | -------------------------------------------------------------------------------- /tests/configmaps_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | _ "embed" 5 | "fmt" 6 | "net/http" 7 | 8 | . "github.com/onsi/ginkgo/v2" 9 | . "github.com/onsi/gomega" 10 | ) 11 | 12 | //go:embed results/configmaps_all_namespaces.json 13 | var expectedGetAllConfigmapsResult string 14 | 15 | //go:embed results/configmaps_kube_public_namespace.json 16 | var expectedGetKubePublicConfigmapsResult string 17 | 18 | var _ = Describe("GET /api/v1/configmaps", func() { 19 | Context("When getting configmaps in all namespaces", func() { 20 | It("Returns all configmaps", func() { 21 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf("%s/api/v1/configmaps", apiServerEndpoint), getHeaders) 22 | Expect(err).NotTo(HaveOccurred()) 23 | Expect(statusCode).To(Equal(http.StatusOK)) 24 | Expect(resp).To(Similar(expectedGetAllConfigmapsResult)) 25 | }) 26 | }) 27 | }) 28 | 29 | var _ = Describe("GET /api/v1/namespaces/{namespace}/configmaps", func() { 30 | Context("When getting configmaps in kube-public namespace", func() { 31 | It("Returns kube-public configmaps", func() { 32 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf("%s/api/v1/namespaces/kube-public/configmaps", apiServerEndpoint), getHeaders) 33 | Expect(err).NotTo(HaveOccurred()) 34 | Expect(statusCode).To(Equal(http.StatusOK)) 35 | Expect(resp).To(Similar(expectedGetKubePublicConfigmapsResult)) 36 | }) 37 | }) 38 | }) 39 | -------------------------------------------------------------------------------- /tests/pods_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | _ "embed" 5 | "fmt" 6 | "net/http" 7 | "net/url" 8 | 9 | . "github.com/onsi/ginkgo/v2" 10 | . "github.com/onsi/gomega" 11 | ) 12 | 13 | //go:embed results/pods_all_namespaces.json 14 | var expectedGetAllPodsResult string 15 | 16 | //go:embed results/pods_velero_namespace.json 17 | var expectedGetVeleroPodsResult string 18 | 19 | //go:embed results/pods_restic_only.json 20 | var expectedGetResticPodsResult string 21 | 22 | var _ = Describe("GET /api/v1/pods", func() { 23 | Context("When getting pods in all namespaces", func() { 24 | It("Returns all pods", func() { 25 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf("%s/api/v1/pods", apiServerEndpoint), getHeaders) 26 | Expect(err).NotTo(HaveOccurred()) 27 | Expect(statusCode).To(Equal(http.StatusOK)) 28 | Expect(resp).To(Similar(expectedGetAllPodsResult)) 29 | }) 30 | }) 31 | 32 | Context("When getting pods in all namespaces by label", func() { 33 | It("Returns restic pods", func() { 34 | v := url.Values{} 35 | v.Set("labelSelector", "name=restic") 36 | 37 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf(`%s/api/v1/pods?%s`, apiServerEndpoint, v.Encode()), getHeaders) 38 | Expect(err).NotTo(HaveOccurred()) 39 | Expect(statusCode).To(Equal(http.StatusOK)) 40 | Expect(resp).To(Similar(expectedGetResticPodsResult)) 41 | }) 42 | }) 43 | }) 44 | 45 | var _ = Describe("GET /api/v1/namespaces/{namespace}/pods", func() { 46 | Context("When getting pods in velero namespace", func() { 47 | It("Returns velero pods", func() { 48 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf("%s/api/v1/namespaces/velero/pods", apiServerEndpoint), getHeaders) 49 | Expect(err).NotTo(HaveOccurred()) 50 | Expect(statusCode).To(Equal(http.StatusOK)) 51 | Expect(resp).To(Similar(expectedGetVeleroPodsResult)) 52 | }) 53 | }) 54 | 55 | Context("When getting pods in velero namespace by label", func() { 56 | It("Returns restic pods", func() { 57 | v := url.Values{} 58 | v.Set("labelSelector", "name=restic") 59 | 60 | resp, statusCode, err := HTTPExec("GET", fmt.Sprintf("%s/api/v1/namespaces/velero/pods?%s", apiServerEndpoint, v.Encode()), getHeaders) 61 | Expect(err).NotTo(HaveOccurred()) 62 | Expect(statusCode).To(Equal(http.StatusOK)) 63 | Expect(resp).To(Similar(expectedGetResticPodsResult)) 64 | }) 65 | }) 66 | }) 67 | -------------------------------------------------------------------------------- /tests/results/configmaps_all_namespaces.json: -------------------------------------------------------------------------------- 1 | {"kind":"Table","apiVersion":"meta.k8s.io/v1","metadata":{},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names","priority":0},{"name":"Data","type":"string","format":"","description":"Data contains the configuration data. Each key must consist of alphanumeric characters, '-', '_' or '.'. Values with non-UTF-8 byte sequences must use the BinaryData field. The keys stored in Data must not overlap with the keys in the BinaryData field, this is enforced during validation process.","priority":0},{"name":"Age","type":"string","format":"","description":"CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata","priority":0}],"rows":[{"cells":["kotsadm-application-metadata",2,"64d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1","metadata":{"name":"kotsadm-application-metadata","namespace":"default","uid":"eb16ac64-ffce-4963-83e9-de63850b736e","resourceVersion":"5021","creationTimestamp":"2024-02-17T06:16:47Z","labels":{"kots.io/backup":"velero","kots.io/kotsadm":"true","kotsadm":"application"},"managedFields":[{"manager":"kubectl-kots","operation":"Update","apiVersion":"v1","time":"2024-02-17T06:16:47Z","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:application.yaml":{},"f:upstreamUri":{}},"f:metadata":{"f:labels":{".":{},"f:kots.io/backup":{},"f:kots.io/kotsadm":{},"f:kotsadm":{}}}}}]}}},{"cells":["kube-root-ca.crt",1,"64d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1","metadata":{"name":"kube-root-ca.crt","namespace":"default","uid":"f3f8cc0f-8434-465b-87a8-d58a44fdb575","resourceVersion":"331","creationTimestamp":"2024-02-17T05:55:36Z","annotations":{"kubernetes.io/description":"Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters."},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2024-02-17T05:55:36Z","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:ca.crt":{}},"f:metadata":{"f:annotations":{".":{},"f:kubernetes.io/description":{}}}}}]}}},{"cells":["kube-root-ca.crt",1,"64d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1","metadata":{"name":"kube-root-ca.crt","namespace":"kube-node-lease","uid":"01acb543-79cc-4e17-a3de-e846b80a20f9","resourceVersion":"332","creationTimestamp":"2024-02-17T05:55:36Z","annotations":{"kubernetes.io/description":"Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters."},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2024-02-17T05:55:36Z","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:ca.crt":{}},"f:metadata":{"f:annotations":{".":{},"f:kubernetes.io/description":{}}}}}]}}},{"cells":["kube-root-ca.crt",1,"64d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1","metadata":{"name":"kube-root-ca.crt","namespace":"kube-public","uid":"c42025cc-2d96-4626-805a-b7fc0575f24c","resourceVersion":"333","creationTimestamp":"2024-02-17T05:55:36Z","annotations":{"kubernetes.io/description":"Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters."},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2024-02-17T05:55:36Z","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:ca.crt":{}},"f:metadata":{"f:annotations":{".":{},"f:kubernetes.io/description":{}}}}}]}}}]} 2 | -------------------------------------------------------------------------------- /tests/results/configmaps_kube_public_namespace.json: -------------------------------------------------------------------------------- 1 | {"kind":"Table","apiVersion":"meta.k8s.io/v1","metadata":{"resourceVersion":"32367474"},"columnDefinitions":[{"name":"Name","type":"string","format":"name","description":"Name must be unique within a namespace. Is required when creating resources, although some resources may allow a client to request the generation of an appropriate name automatically. Name is primarily intended for creation idempotence and configuration definition. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names","priority":0},{"name":"Data","type":"string","format":"","description":"Data contains the configuration data. Each key must consist of alphanumeric characters, '-', '_' or '.'. Values with non-UTF-8 byte sequences must use the BinaryData field. The keys stored in Data must not overlap with the keys in the BinaryData field, this is enforced during validation process.","priority":0},{"name":"Age","type":"string","format":"","description":"CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC.\n\nPopulated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata","priority":0}],"rows":[{"cells":["kube-root-ca.crt",1,"64d"],"object":{"kind":"PartialObjectMetadata","apiVersion":"meta.k8s.io/v1","metadata":{"name":"kube-root-ca.crt","namespace":"kube-public","uid":"c42025cc-2d96-4626-805a-b7fc0575f24c","resourceVersion":"333","creationTimestamp":"2024-02-17T05:55:36Z","annotations":{"kubernetes.io/description":"Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters."},"managedFields":[{"manager":"kube-controller-manager","operation":"Update","apiVersion":"v1","time":"2024-02-17T05:55:36Z","fieldsType":"FieldsV1","fieldsV1":{"f:data":{".":{},"f:ca.crt":{}},"f:metadata":{"f:annotations":{".":{},"f:kubernetes.io/description":{}}}}}]}}}]} 2 | -------------------------------------------------------------------------------- /tests/suite_test.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "fmt" 5 | "os" 6 | "testing" 7 | 8 | . "github.com/onsi/ginkgo/v2" 9 | . "github.com/onsi/gomega" 10 | 11 | "github.com/antzucaro/matchr" 12 | "github.com/onsi/gomega/format" 13 | "github.com/onsi/gomega/types" 14 | "github.com/pkg/errors" 15 | "github.com/replicatedhq/sbctl/pkg/api" 16 | "github.com/replicatedhq/sbctl/pkg/sbctl" 17 | yaml "gopkg.in/yaml.v2" 18 | ) 19 | 20 | var ( 21 | apiServerEndpoint string 22 | ) 23 | 24 | var ( 25 | getHeaders = map[string]string{ 26 | "Content-Type": "application/json", 27 | "Accept": "application/json;as=Table;v=v1;g=meta.k8s.io,application/json;as=Table;v=v1beta1;g=meta.k8s.io,application/json", 28 | } 29 | ) 30 | 31 | func TestE2e(t *testing.T) { 32 | RegisterFailHandler(Fail) 33 | RunSpecs(t, "Integration Suite") 34 | } 35 | 36 | var _ = BeforeSuite(func() { 37 | clusterData, err := sbctl.FindClusterData("./support-bundle") 38 | Expect(err).NotTo(HaveOccurred()) 39 | 40 | Expect(clusterData.ClusterResourcesDir).To(Equal("support-bundle/cluster-resources")) 41 | Expect(clusterData.ClusterInfoFile).To(Equal("support-bundle/cluster-info/cluster_version.json")) 42 | 43 | kubeConfig, err := api.StartAPIServer(clusterData, os.Stderr) 44 | Expect(err).NotTo(HaveOccurred()) 45 | cleanup := func() error { 46 | return os.RemoveAll(kubeConfig) 47 | } 48 | DeferCleanup(cleanup) 49 | 50 | endpoint, err := getAPIEndpoint(kubeConfig) 51 | Expect(err).NotTo(HaveOccurred()) 52 | apiServerEndpoint = endpoint 53 | }) 54 | 55 | var _ = AfterSuite(func() { 56 | }) 57 | 58 | func getAPIEndpoint(filename string) (string, error) { 59 | configData, err := os.ReadFile(filename) 60 | if err != nil { 61 | return "", errors.Wrap(err, "failed to read config data") 62 | } 63 | 64 | config := struct { 65 | Clusters []struct { 66 | Cluster struct { 67 | Server string `yaml:"server"` 68 | } `yaml:"cluster"` 69 | } `yaml:"clusters"` 70 | }{} 71 | err = yaml.Unmarshal(configData, &config) 72 | if err != nil { 73 | return "", errors.Wrap(err, "failed to unmarshal config data") 74 | } 75 | 76 | return config.Clusters[0].Cluster.Server, nil 77 | } 78 | 79 | func Similar(expected string) types.GomegaMatcher { 80 | return &similarMatcher{ 81 | expected: expected, 82 | } 83 | } 84 | 85 | type similarMatcher struct { 86 | expected string 87 | } 88 | 89 | func (matcher *similarMatcher) Match(actual interface{}) (success bool, err error) { 90 | actualString, ok := actual.(string) 91 | if !ok { 92 | return false, errors.Errorf("cannot match %T, only stings are supported", actual) 93 | } 94 | score := matchr.Jaro(actualString, matcher.expected) 95 | fmt.Printf("Jaro score is %v\n", score) 96 | return score > 0.80, nil // 0.80 found by trial and error and may need to be adjusted 97 | } 98 | 99 | func (matcher *similarMatcher) FailureMessage(actual interface{}) (message string) { 100 | actualString, actualOK := actual.(string) 101 | if actualOK { 102 | return format.MessageWithDiff(actualString, "to equal", matcher.expected) 103 | } 104 | 105 | return format.Message(actual, "to equal", matcher.expected) 106 | } 107 | 108 | func (matcher *similarMatcher) NegatedFailureMessage(actual interface{}) (message string) { 109 | return format.Message(actual, "not to equal", matcher.expected) 110 | } 111 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-info/cluster_version.json: -------------------------------------------------------------------------------- 1 | { 2 | "info": { 3 | "major": "1", 4 | "minor": "23", 5 | "gitVersion": "v1.23.5", 6 | "gitCommit": "c285e781331a3785a7f436042c65c5641ce8a9e9", 7 | "gitTreeState": "clean", 8 | "buildDate": "2022-03-16T15:52:18Z", 9 | "goVersion": "go1.17.8", 10 | "compiler": "gc", 11 | "platform": "linux/amd64" 12 | }, 13 | "string": "v1.23.5" 14 | } 15 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/default.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "create" 5 | ], 6 | "apiGroups": [ 7 | "authorization.k8s.io" 8 | ], 9 | "resources": [ 10 | "selfsubjectaccessreviews", 11 | "selfsubjectrulesreviews" 12 | ] 13 | }, 14 | { 15 | "verbs": [ 16 | "*" 17 | ], 18 | "apiGroups": [ 19 | "*" 20 | ], 21 | "resources": [ 22 | "*" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "*" 5 | ], 6 | "apiGroups": [ 7 | "*" 8 | ], 9 | "resources": [ 10 | "*" 11 | ] 12 | }, 13 | { 14 | "verbs": [ 15 | "create" 16 | ], 17 | "apiGroups": [ 18 | "authorization.k8s.io" 19 | ], 20 | "resources": [ 21 | "selfsubjectaccessreviews", 22 | "selfsubjectrulesreviews" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/kube-public.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "*" 5 | ], 6 | "apiGroups": [ 7 | "*" 8 | ], 9 | "resources": [ 10 | "*" 11 | ] 12 | }, 13 | { 14 | "verbs": [ 15 | "create" 16 | ], 17 | "apiGroups": [ 18 | "authorization.k8s.io" 19 | ], 20 | "resources": [ 21 | "selfsubjectaccessreviews", 22 | "selfsubjectrulesreviews" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/kube-system.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "create" 5 | ], 6 | "apiGroups": [ 7 | "authorization.k8s.io" 8 | ], 9 | "resources": [ 10 | "selfsubjectaccessreviews", 11 | "selfsubjectrulesreviews" 12 | ] 13 | }, 14 | { 15 | "verbs": [ 16 | "*" 17 | ], 18 | "apiGroups": [ 19 | "*" 20 | ], 21 | "resources": [ 22 | "*" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/kurl.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "*" 5 | ], 6 | "apiGroups": [ 7 | "*" 8 | ], 9 | "resources": [ 10 | "*" 11 | ] 12 | }, 13 | { 14 | "verbs": [ 15 | "create" 16 | ], 17 | "apiGroups": [ 18 | "authorization.k8s.io" 19 | ], 20 | "resources": [ 21 | "selfsubjectaccessreviews", 22 | "selfsubjectrulesreviews" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "*" 28 | ], 29 | "nonResourceURLs": [ 30 | "*" 31 | ] 32 | }, 33 | { 34 | "verbs": [ 35 | "get" 36 | ], 37 | "nonResourceURLs": [ 38 | "/healthz", 39 | "/livez", 40 | "/readyz", 41 | "/version", 42 | "/version/" 43 | ] 44 | }, 45 | { 46 | "verbs": [ 47 | "get" 48 | ], 49 | "nonResourceURLs": [ 50 | "/api", 51 | "/api/*", 52 | "/apis", 53 | "/apis/*", 54 | "/healthz", 55 | "/livez", 56 | "/openapi", 57 | "/openapi/*", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/longhorn-system.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "create" 5 | ], 6 | "apiGroups": [ 7 | "authorization.k8s.io" 8 | ], 9 | "resources": [ 10 | "selfsubjectaccessreviews", 11 | "selfsubjectrulesreviews" 12 | ] 13 | }, 14 | { 15 | "verbs": [ 16 | "*" 17 | ], 18 | "apiGroups": [ 19 | "*" 20 | ], 21 | "resources": [ 22 | "*" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/healthz", 31 | "/livez", 32 | "/readyz", 33 | "/version", 34 | "/version/" 35 | ] 36 | }, 37 | { 38 | "verbs": [ 39 | "get" 40 | ], 41 | "nonResourceURLs": [ 42 | "/api", 43 | "/api/*", 44 | "/apis", 45 | "/apis/*", 46 | "/healthz", 47 | "/livez", 48 | "/openapi", 49 | "/openapi/*", 50 | "/readyz", 51 | "/version", 52 | "/version/" 53 | ] 54 | }, 55 | { 56 | "verbs": [ 57 | "*" 58 | ], 59 | "nonResourceURLs": [ 60 | "*" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/minio.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "*" 5 | ], 6 | "apiGroups": [ 7 | "*" 8 | ], 9 | "resources": [ 10 | "*" 11 | ] 12 | }, 13 | { 14 | "verbs": [ 15 | "create" 16 | ], 17 | "apiGroups": [ 18 | "authorization.k8s.io" 19 | ], 20 | "resources": [ 21 | "selfsubjectaccessreviews", 22 | "selfsubjectrulesreviews" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "*" 28 | ], 29 | "nonResourceURLs": [ 30 | "*" 31 | ] 32 | }, 33 | { 34 | "verbs": [ 35 | "get" 36 | ], 37 | "nonResourceURLs": [ 38 | "/healthz", 39 | "/livez", 40 | "/readyz", 41 | "/version", 42 | "/version/" 43 | ] 44 | }, 45 | { 46 | "verbs": [ 47 | "get" 48 | ], 49 | "nonResourceURLs": [ 50 | "/api", 51 | "/api/*", 52 | "/apis", 53 | "/apis/*", 54 | "/healthz", 55 | "/livez", 56 | "/openapi", 57 | "/openapi/*", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/projectcontour.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "*" 5 | ], 6 | "apiGroups": [ 7 | "*" 8 | ], 9 | "resources": [ 10 | "*" 11 | ] 12 | }, 13 | { 14 | "verbs": [ 15 | "create" 16 | ], 17 | "apiGroups": [ 18 | "authorization.k8s.io" 19 | ], 20 | "resources": [ 21 | "selfsubjectaccessreviews", 22 | "selfsubjectrulesreviews" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/auth-cani-list/velero.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "verbs": [ 4 | "create" 5 | ], 6 | "apiGroups": [ 7 | "authorization.k8s.io" 8 | ], 9 | "resources": [ 10 | "selfsubjectaccessreviews", 11 | "selfsubjectrulesreviews" 12 | ] 13 | }, 14 | { 15 | "verbs": [ 16 | "*" 17 | ], 18 | "apiGroups": [ 19 | "*" 20 | ], 21 | "resources": [ 22 | "*" 23 | ] 24 | }, 25 | { 26 | "verbs": [ 27 | "get" 28 | ], 29 | "nonResourceURLs": [ 30 | "/api", 31 | "/api/*", 32 | "/apis", 33 | "/apis/*", 34 | "/healthz", 35 | "/livez", 36 | "/openapi", 37 | "/openapi/*", 38 | "/readyz", 39 | "/version", 40 | "/version/" 41 | ] 42 | }, 43 | { 44 | "verbs": [ 45 | "*" 46 | ], 47 | "nonResourceURLs": [ 48 | "*" 49 | ] 50 | }, 51 | { 52 | "verbs": [ 53 | "get" 54 | ], 55 | "nonResourceURLs": [ 56 | "/healthz", 57 | "/livez", 58 | "/readyz", 59 | "/version", 60 | "/version/" 61 | ] 62 | } 63 | ] 64 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/configmaps/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ConfigMapList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "32367468" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "ConfigMap", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "kotsadm-application-metadata", 13 | "namespace": "default", 14 | "uid": "eb16ac64-ffce-4963-83e9-de63850b736e", 15 | "resourceVersion": "5021", 16 | "creationTimestamp": "2024-02-17T06:16:47Z", 17 | "labels": { 18 | "kots.io/backup": "velero", 19 | "kots.io/kotsadm": "true", 20 | "kotsadm": "application" 21 | }, 22 | "managedFields": [ 23 | { 24 | "manager": "kubectl-kots", 25 | "operation": "Update", 26 | "apiVersion": "v1", 27 | "time": "2024-02-17T06:16:47Z", 28 | "fieldsType": "FieldsV1", 29 | "fieldsV1": { 30 | "f:data": { 31 | ".": {}, 32 | "f:application.yaml": {}, 33 | "f:upstreamUri": {} 34 | }, 35 | "f:metadata": { 36 | "f:labels": { 37 | ".": {}, 38 | "f:kots.io/backup": {}, 39 | "f:kots.io/kotsadm": {}, 40 | "f:kotsadm": {} 41 | } 42 | } 43 | } 44 | } 45 | ] 46 | }, 47 | "data": { 48 | "application.yaml": "apiVersion: kots.io/v1beta1\nkind: Application\nmetadata:\n annotations:\n kots.io/exclude: \"true\"\n creationTimestamp: null\n name: Stoplight\nspec:\n icon: https://stoplight.io/images/mark_light_bg.png\n releaseNotes: See https://stoplight.io/blog/ for release updates.\n requireMinimalRBACPrivileges: true\n statusInformers:\n - deployment/platform-worker\n title: Stoplight\nstatus: {}\n", 49 | "upstreamUri": "replicated://replicatehq/stable" 50 | } 51 | }, 52 | { 53 | "kind": "ConfigMap", 54 | "Kind": "ConfigMap", 55 | "apiVersion": "v1", 56 | "metadata": { 57 | "name": "kube-root-ca.crt", 58 | "namespace": "default", 59 | "uid": "f3f8cc0f-8434-465b-87a8-d58a44fdb575", 60 | "resourceVersion": "331", 61 | "creationTimestamp": "2024-02-17T05:55:36Z", 62 | "annotations": { 63 | "kubernetes.io/description": "Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters." 64 | }, 65 | "managedFields": [ 66 | { 67 | "manager": "kube-controller-manager", 68 | "operation": "Update", 69 | "apiVersion": "v1", 70 | "time": "2024-02-17T05:55:36Z", 71 | "fieldsType": "FieldsV1", 72 | "fieldsV1": { 73 | "f:data": { 74 | ".": {}, 75 | "f:ca.crt": {} 76 | }, 77 | "f:metadata": { 78 | "f:annotations": { 79 | ".": {}, 80 | "f:kubernetes.io/description": {} 81 | } 82 | } 83 | } 84 | } 85 | ] 86 | }, 87 | "data": { 88 | "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIDBTCCAe2gAwIBAgIIaDHtQlkhzfMwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE\nAxMKa3ViZXJuZXRlczAeFw0yNDAyMTcwNTQ5NTdaFw0zNDAyMTQwNTU0NTdaMBUx\nEzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQDH/Q7uWgAMLl/KKv4jL9N+eRdcvU00S08IWF81aAW9vCKkrn9fUhdjznP0\njHXhTnRIyOjkLsRif60pFM9eziHPHMLMlwqvPzVq4RPtOJCLGvWsdm18DTzBIM0v\ncvj3ZhCHqwNoHpEcmeLcIPZhXUTP9P/HymHN7McPWlCubkUK0Rd3ZJcZTwlzNiSV\nLVm34/28sY0zQZslDKIz3prUQ9r4LtEX4Vj56Zj4H+DH+82JpIh3CQ2BCiLzUzrg\n5c1L4uQ6FKj9FH/Hgyz2ttVcCU38ObgX1ASaBXZtsHZPY07S7GLi6czrdcxdSEvb\nZDeCuG5c/4M0dP6Skz07sr3tF26tAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP\nBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSzYh2i904R82VVx7d3syCW0ZkS7DAV\nBgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQC+T2TvKB/V\ncPQ5QIeSNEolAe/B5MoSCao+WZTpo9P46Xq5kU9pGUVRFPi1/fVdHSgd1ZuRUPxl\n83GVy4Wsf2squXW8IrYFMeX2jZKVEGh6roAb4wUexTpouSyv+5Mln5Ov/dt8oV1a\nMUeRfWUiDlwunEX9Luly6BITE9uB5m3VR4GxlnuFL4f92rurXXNVoGMBwJohaYSj\nwYoZ+HvG2rl8aB7pnjiypAcZUpBtB9xkY4wtTOZ1lrR5jXjAYwDh4N1TvSRsSk60\nLUpoWZ+nAq3qvKoe1/511lKNWYvHW6cx//Bn3MZKfILInBLA0VK0OJJ0x+Kh6TFl\nV77zhWyQ9IXN\n-----END CERTIFICATE-----\n" 89 | } 90 | } 91 | ] 92 | } 93 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/configmaps/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ConfigMapList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "32367473" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "ConfigMap", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "kube-root-ca.crt", 13 | "namespace": "kube-node-lease", 14 | "uid": "01acb543-79cc-4e17-a3de-e846b80a20f9", 15 | "resourceVersion": "332", 16 | "creationTimestamp": "2024-02-17T05:55:36Z", 17 | "annotations": { 18 | "kubernetes.io/description": "Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters." 19 | }, 20 | "managedFields": [ 21 | { 22 | "manager": "kube-controller-manager", 23 | "operation": "Update", 24 | "apiVersion": "v1", 25 | "time": "2024-02-17T05:55:36Z", 26 | "fieldsType": "FieldsV1", 27 | "fieldsV1": { 28 | "f:data": { 29 | ".": {}, 30 | "f:ca.crt": {} 31 | }, 32 | "f:metadata": { 33 | "f:annotations": { 34 | ".": {}, 35 | "f:kubernetes.io/description": {} 36 | } 37 | } 38 | } 39 | } 40 | ] 41 | }, 42 | "data": { 43 | "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIDBTCCAe2gAwIBAgIIaDHtQlkhzfMwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE\nAxMKa3ViZXJuZXRlczAeFw0yNDAyMTcwNTQ5NTdaFw0zNDAyMTQwNTU0NTdaMBUx\nEzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQDH/Q7uWgAMLl/KKv4jL9N+eRdcvU00S08IWF81aAW9vCKkrn9fUhdjznP0\njHXhTnRIyOjkLsRif60pFM9eziHPHMLMlwqvPzVq4RPtOJCLGvWsdm18DTzBIM0v\ncvj3ZhCHqwNoHpEcmeLcIPZhXUTP9P/HymHN7McPWlCubkUK0Rd3ZJcZTwlzNiSV\nLVm34/28sY0zQZslDKIz3prUQ9r4LtEX4Vj56Zj4H+DH+82JpIh3CQ2BCiLzUzrg\n5c1L4uQ6FKj9FH/Hgyz2ttVcCU38ObgX1ASaBXZtsHZPY07S7GLi6czrdcxdSEvb\nZDeCuG5c/4M0dP6Skz07sr3tF26tAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP\nBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSzYh2i904R82VVx7d3syCW0ZkS7DAV\nBgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQC+T2TvKB/V\ncPQ5QIeSNEolAe/B5MoSCao+WZTpo9P46Xq5kU9pGUVRFPi1/fVdHSgd1ZuRUPxl\n83GVy4Wsf2squXW8IrYFMeX2jZKVEGh6roAb4wUexTpouSyv+5Mln5Ov/dt8oV1a\nMUeRfWUiDlwunEX9Luly6BITE9uB5m3VR4GxlnuFL4f92rurXXNVoGMBwJohaYSj\nwYoZ+HvG2rl8aB7pnjiypAcZUpBtB9xkY4wtTOZ1lrR5jXjAYwDh4N1TvSRsSk60\nLUpoWZ+nAq3qvKoe1/511lKNWYvHW6cx//Bn3MZKfILInBLA0VK0OJJ0x+Kh6TFl\nV77zhWyQ9IXN\n-----END CERTIFICATE-----\n" 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/configmaps/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ConfigMapList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "32367474" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "ConfigMap", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "kube-root-ca.crt", 13 | "namespace": "kube-public", 14 | "uid": "c42025cc-2d96-4626-805a-b7fc0575f24c", 15 | "resourceVersion": "333", 16 | "creationTimestamp": "2024-02-17T05:55:36Z", 17 | "annotations": { 18 | "kubernetes.io/description": "Contains a CA bundle that can be used to verify the kube-apiserver when using internal endpoints such as the internal service IP or kubernetes.default.svc. No other usage is guaranteed across distributions of Kubernetes clusters." 19 | }, 20 | "managedFields": [ 21 | { 22 | "manager": "kube-controller-manager", 23 | "operation": "Update", 24 | "apiVersion": "v1", 25 | "time": "2024-02-17T05:55:36Z", 26 | "fieldsType": "FieldsV1", 27 | "fieldsV1": { 28 | "f:data": { 29 | ".": {}, 30 | "f:ca.crt": {} 31 | }, 32 | "f:metadata": { 33 | "f:annotations": { 34 | ".": {}, 35 | "f:kubernetes.io/description": {} 36 | } 37 | } 38 | } 39 | } 40 | ] 41 | }, 42 | "data": { 43 | "ca.crt": "-----BEGIN CERTIFICATE-----\nMIIDBTCCAe2gAwIBAgIIaDHtQlkhzfMwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE\nAxMKa3ViZXJuZXRlczAeFw0yNDAyMTcwNTQ5NTdaFw0zNDAyMTQwNTU0NTdaMBUx\nEzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\nAoIBAQDH/Q7uWgAMLl/KKv4jL9N+eRdcvU00S08IWF81aAW9vCKkrn9fUhdjznP0\njHXhTnRIyOjkLsRif60pFM9eziHPHMLMlwqvPzVq4RPtOJCLGvWsdm18DTzBIM0v\ncvj3ZhCHqwNoHpEcmeLcIPZhXUTP9P/HymHN7McPWlCubkUK0Rd3ZJcZTwlzNiSV\nLVm34/28sY0zQZslDKIz3prUQ9r4LtEX4Vj56Zj4H+DH+82JpIh3CQ2BCiLzUzrg\n5c1L4uQ6FKj9FH/Hgyz2ttVcCU38ObgX1ASaBXZtsHZPY07S7GLi6czrdcxdSEvb\nZDeCuG5c/4M0dP6Skz07sr3tF26tAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP\nBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSzYh2i904R82VVx7d3syCW0ZkS7DAV\nBgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQC+T2TvKB/V\ncPQ5QIeSNEolAe/B5MoSCao+WZTpo9P46Xq5kU9pGUVRFPi1/fVdHSgd1ZuRUPxl\n83GVy4Wsf2squXW8IrYFMeX2jZKVEGh6roAb4wUexTpouSyv+5Mln5Ov/dt8oV1a\nMUeRfWUiDlwunEX9Luly6BITE9uB5m3VR4GxlnuFL4f92rurXXNVoGMBwJohaYSj\nwYoZ+HvG2rl8aB7pnjiypAcZUpBtB9xkY4wtTOZ1lrR5jXjAYwDh4N1TvSRsSk60\nLUpoWZ+nAq3qvKoe1/511lKNWYvHW6cx//Bn3MZKfILInBLA0VK0OJJ0x+Kh6TFl\nV77zhWyQ9IXN\n-----END CERTIFICATE-----\n" 44 | } 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/cronjobs/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "CronJobList", 3 | "apiVersion": "batch/v1beta1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/backupstoragelocations.velero.io/velero.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: velero.io/v1 2 | kind: BackupStorageLocation 3 | metadata: 4 | annotations: 5 | kubectl.kubernetes.io/last-applied-configuration: | 6 | {"apiVersion":"velero.io/v1","kind":"BackupStorageLocation","metadata":{"annotations":{},"creationTimestamp":null,"labels":{"component":"velero"},"name":"default","namespace":"velero"},"spec":{"config":{"publicUrl":"http://***HIDDEN***","region":"us-east-1","s3ForcePathStyle":"true","s3Url":"http://minio.minio"},"default":true,"objectStorage":{"bucket":"velero"},"provider":"aws"}} 7 | creationTimestamp: "2022-04-11T22:52:59Z" 8 | generation: 1 9 | labels: 10 | component: velero 11 | managedFields: 12 | - apiVersion: velero.io/v1 13 | fieldsType: FieldsV1 14 | fieldsV1: 15 | f:metadata: 16 | f:annotations: 17 | .: {} 18 | f:kubectl.kubernetes.io/last-applied-configuration: {} 19 | f:labels: 20 | .: {} 21 | f:component: {} 22 | f:spec: 23 | .: {} 24 | f:config: 25 | .: {} 26 | f:publicUrl: {} 27 | f:region: {} 28 | f:s3ForcePathStyle: {} 29 | f:s3Url: {} 30 | f:default: {} 31 | f:objectStorage: 32 | .: {} 33 | f:bucket: {} 34 | f:provider: {} 35 | manager: kubectl-client-side-apply 36 | operation: Update 37 | time: "2022-04-11T22:52:59Z" 38 | - apiVersion: velero.io/v1 39 | fieldsType: FieldsV1 40 | fieldsV1: 41 | f:status: 42 | .: {} 43 | f:lastSyncedTime: {} 44 | f:lastValidationTime: {} 45 | f:phase: {} 46 | manager: velero-server 47 | operation: Update 48 | subresource: status 49 | time: "2022-04-11T22:53:11Z" 50 | name: default 51 | namespace: velero 52 | resourceVersion: "27054" 53 | uid: 1687f392-ec83-4581-a3a8-a402186c7902 54 | spec: 55 | config: 56 | publicUrl: http://***HIDDEN*** 57 | region: us-east-1 58 | s3ForcePathStyle: "true" 59 | s3Url: http://minio.minio 60 | default: true 61 | objectStorage: 62 | bucket: velero 63 | provider: aws 64 | status: 65 | lastSyncedTime: "2022-04-12T00:59:13Z" 66 | lastValidationTime: "2022-04-12T00:59:13Z" 67 | phase: Available 68 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/backuptargets.longhorn.io/longhorn-system.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: longhorn.io/v1beta1 2 | kind: BackupTarget 3 | metadata: 4 | creationTimestamp: "2022-04-11T22:51:56Z" 5 | generation: 1 6 | managedFields: 7 | - apiVersion: longhorn.io/v1beta1 8 | fieldsType: FieldsV1 9 | fieldsV1: 10 | f:spec: 11 | .: {} 12 | f:backupTargetURL: {} 13 | f:credentialSecret: {} 14 | f:pollInterval: {} 15 | f:syncRequestedAt: {} 16 | manager: longhorn-manager 17 | operation: Update 18 | time: "2022-04-11T22:51:56Z" 19 | - apiVersion: longhorn.io/v1beta1 20 | fieldsType: FieldsV1 21 | fieldsV1: 22 | f:status: 23 | .: {} 24 | f:available: {} 25 | f:conditions: 26 | .: {} 27 | f:Unavailable: 28 | .: {} 29 | f:lastProbeTime: {} 30 | f:lastTransitionTime: {} 31 | f:message: {} 32 | f:reason: {} 33 | f:status: {} 34 | f:type: {} 35 | f:lastSyncedAt: {} 36 | f:ownerID: {} 37 | manager: longhorn-manager 38 | operation: Update 39 | subresource: status 40 | time: "2022-04-11T22:52:02Z" 41 | name: default 42 | namespace: longhorn-system 43 | resourceVersion: "1114" 44 | uid: b972629d-1504-4c6b-9e8c-40a29931e16b 45 | spec: 46 | backupTargetURL: "" 47 | credentialSecret: "" 48 | pollInterval: 5m0s 49 | syncRequestedAt: "0001-01-01T00:00:00Z" 50 | status: 51 | available: false 52 | conditions: 53 | Unavailable: 54 | lastProbeTime: "" 55 | lastTransitionTime: "2022-04-11T22:52:02Z" 56 | message: backup target URL is empty 57 | reason: Unavailable 58 | status: "True" 59 | type: Unavailable 60 | lastSyncedAt: "0001-01-01T00:00:00Z" 61 | ownerID: troubleshoot-demo-001 62 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/engineimages.longhorn.io/longhorn-system.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: longhorn.io/v1beta1 2 | kind: EngineImage 3 | metadata: 4 | creationTimestamp: "2022-04-11T22:51:51Z" 5 | finalizers: 6 | - longhorn.io 7 | generation: 1 8 | labels: 9 | longhorn.io/component: engine-image 10 | longhorn.io/engine-image: ei-d4c780c6 11 | longhorn.io/managed-by: longhorn-manager 12 | managedFields: 13 | - apiVersion: longhorn.io/v1beta1 14 | fieldsType: FieldsV1 15 | fieldsV1: 16 | f:metadata: 17 | f:finalizers: 18 | .: {} 19 | v:"longhorn.io": {} 20 | f:labels: 21 | .: {} 22 | f:longhorn.io/component: {} 23 | f:longhorn.io/engine-image: {} 24 | f:longhorn.io/managed-by: {} 25 | f:spec: 26 | .: {} 27 | f:image: {} 28 | manager: longhorn-manager 29 | operation: Update 30 | time: "2022-04-11T22:51:51Z" 31 | - apiVersion: longhorn.io/v1beta1 32 | fieldsType: FieldsV1 33 | fieldsV1: 34 | f:status: 35 | .: {} 36 | f:buildDate: {} 37 | f:cliAPIMinVersion: {} 38 | f:cliAPIVersion: {} 39 | f:conditions: 40 | .: {} 41 | f:ready: 42 | .: {} 43 | f:lastProbeTime: {} 44 | f:lastTransitionTime: {} 45 | f:message: {} 46 | f:reason: {} 47 | f:status: {} 48 | f:type: {} 49 | f:controllerAPIMinVersion: {} 50 | f:controllerAPIVersion: {} 51 | f:dataFormatMinVersion: {} 52 | f:dataFormatVersion: {} 53 | f:gitCommit: {} 54 | f:noRefSince: {} 55 | f:nodeDeploymentMap: 56 | .: {} 57 | f:troubleshoot-demo-001: {} 58 | f:troubleshoot-demo-002: {} 59 | f:troubleshoot-demo-003: {} 60 | f:ownerID: {} 61 | f:refCount: {} 62 | f:state: {} 63 | f:version: {} 64 | manager: longhorn-manager 65 | operation: Update 66 | subresource: status 67 | time: "2022-04-11T23:03:44Z" 68 | name: ei-d4c780c6 69 | namespace: longhorn-system 70 | resourceVersion: "4352" 71 | uid: 2d9d6886-108d-42f5-b185-eeee670e285c 72 | spec: 73 | image: longhornio/longhorn-engine:v1.2.2 74 | status: 75 | buildDate: "2021-10-07T17:57:05+00:00" 76 | cliAPIMinVersion: 3 77 | cliAPIVersion: 5 78 | conditions: 79 | ready: 80 | lastProbeTime: "" 81 | lastTransitionTime: "2022-04-11T22:52:02Z" 82 | message: Engine image ei-d4c780c6 (longhornio/longhorn-engine:v1.2.2) is fully 83 | deployed on all ready nodes 84 | reason: "" 85 | status: "True" 86 | type: ready 87 | controllerAPIMinVersion: 3 88 | controllerAPIVersion: 3 89 | dataFormatMinVersion: 1 90 | dataFormatVersion: 1 91 | gitCommit: dec6a9c3073fab743417b6d49f9f4c61c9aea034 92 | noRefSince: "" 93 | nodeDeploymentMap: 94 | troubleshoot-demo-001: true 95 | troubleshoot-demo-002: true 96 | troubleshoot-demo-003: true 97 | ownerID: troubleshoot-demo-001 98 | refCount: 1 99 | state: deployed 100 | version: v1.2.2 101 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/engines.longhorn.io/longhorn-system.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: longhorn.io/v1beta1 2 | kind: Engine 3 | metadata: 4 | creationTimestamp: "2022-04-11T22:52:12Z" 5 | finalizers: 6 | - longhorn.io 7 | generation: 4 8 | labels: 9 | longhornnode: troubleshoot-demo-001 10 | longhornvolume: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 11 | managedFields: 12 | - apiVersion: longhorn.io/v1beta1 13 | fieldsType: FieldsV1 14 | fieldsV1: 15 | f:spec: 16 | f:replicaAddressMap: 17 | f:pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: {} 18 | f:status: 19 | f:cloneStatus: 20 | f:tcp://***HIDDEN***:10000: 21 | .: {} 22 | f:error: {} 23 | f:fromReplicaAddress: {} 24 | f:isCloning: {} 25 | f:progress: {} 26 | f:snapshotName: {} 27 | f:state: {} 28 | f:currentReplicaAddressMap: 29 | f:pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328: {} 30 | f:purgeStatus: 31 | f:tcp://***HIDDEN***:10000: 32 | f:progress: {} 33 | f:state: {} 34 | f:tcp://***HIDDEN***:10000: 35 | .: {} 36 | f:error: {} 37 | f:isPurging: {} 38 | f:progress: {} 39 | f:state: {} 40 | f:replicaModeMap: 41 | f:pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328: {} 42 | f:restoreStatus: 43 | f:tcp://***HIDDEN***:10000: 44 | .: {} 45 | f:backupURL: {} 46 | f:currentRestoringBackup: {} 47 | f:isRestoring: {} 48 | f:lastRestored: {} 49 | f:state: {} 50 | f:snapshots: 51 | f:volume-head: 52 | f:size: {} 53 | manager: longhorn-manager 54 | operation: Update 55 | time: "2022-04-11T23:04:10Z" 56 | - apiVersion: longhorn.io/v1beta1 57 | fieldsType: FieldsV1 58 | fieldsV1: 59 | f:status: 60 | f:cloneStatus: 61 | f:tcp://***HIDDEN***:10000: 62 | .: {} 63 | f:error: {} 64 | f:fromReplicaAddress: {} 65 | f:isCloning: {} 66 | f:progress: {} 67 | f:snapshotName: {} 68 | f:state: {} 69 | f:currentReplicaAddressMap: 70 | f:pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: {} 71 | f:purgeStatus: 72 | f:tcp://***HIDDEN***:10000: 73 | .: {} 74 | f:error: {} 75 | f:isPurging: {} 76 | f:progress: {} 77 | f:state: {} 78 | f:replicaModeMap: 79 | f:pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: {} 80 | f:restoreStatus: 81 | f:tcp://***HIDDEN***:10000: 82 | .: {} 83 | f:backupURL: {} 84 | f:currentRestoringBackup: {} 85 | f:isRestoring: {} 86 | f:lastRestored: {} 87 | f:state: {} 88 | f:snapshots: 89 | f:8afb0be0-addc-40c0-93b1-e5f5cc6f8c17: 90 | .: {} 91 | f:children: 92 | .: {} 93 | f:volume-head: {} 94 | f:created: {} 95 | f:labels: {} 96 | f:name: {} 97 | f:parent: {} 98 | f:removed: {} 99 | f:size: {} 100 | f:usercreated: {} 101 | f:volume-head: 102 | f:created: {} 103 | f:parent: {} 104 | manager: longhorn-manager 105 | operation: Update 106 | subresource: status 107 | time: "2022-04-11T23:04:19Z" 108 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-e-0886512b 109 | namespace: longhorn-system 110 | ownerReferences: 111 | - apiVersion: longhorn.io/v1beta1 112 | kind: Volume 113 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 114 | uid: 45f8c38f-23a5-440c-b36b-49c94491239f 115 | resourceVersion: "4499" 116 | uid: d26a9725-4796-4abf-b4f6-5bf389012220 117 | spec: 118 | backupVolume: "" 119 | desireState: running 120 | disableFrontend: false 121 | engineImage: longhornio/longhorn-engine:v1.2.2 122 | frontend: blockdev 123 | logRequested: false 124 | nodeID: troubleshoot-demo-001 125 | replicaAddressMap: 126 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328: ***HIDDEN***:10000 127 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: ***HIDDEN***:10000 128 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-d711caf5: ***HIDDEN***:10000 129 | requestedBackupRestore: "" 130 | requestedDataSource: "" 131 | revisionCounterDisabled: false 132 | salvageRequested: false 133 | upgradedReplicaAddressMap: {} 134 | volumeName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 135 | volumeSize: "10737418240" 136 | status: 137 | backupStatus: {} 138 | cloneStatus: 139 | tcp://***HIDDEN***:10000: 140 | error: "" 141 | fromReplicaAddress: "" 142 | isCloning: false 143 | progress: 0 144 | snapshotName: "" 145 | state: "" 146 | tcp://***HIDDEN***:10000: 147 | error: "" 148 | fromReplicaAddress: "" 149 | isCloning: false 150 | progress: 0 151 | snapshotName: "" 152 | state: "" 153 | tcp://***HIDDEN***:10000: 154 | error: "" 155 | fromReplicaAddress: "" 156 | isCloning: false 157 | progress: 0 158 | snapshotName: "" 159 | state: "" 160 | currentImage: longhornio/longhorn-engine:v1.2.2 161 | currentReplicaAddressMap: 162 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328: ***HIDDEN***:10000 163 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: ***HIDDEN***:10000 164 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-d711caf5: ***HIDDEN***:10000 165 | currentSize: "10737418240" 166 | currentState: running 167 | endpoint: /dev/longhorn/pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 168 | instanceManagerName: instance-manager-e-20c7e80d 169 | ip: ***HIDDEN*** 170 | isExpanding: false 171 | lastExpansionError: "" 172 | lastExpansionFailedAt: "" 173 | lastRestoredBackup: "" 174 | logFetched: false 175 | ownerID: troubleshoot-demo-001 176 | port: 10000 177 | purgeStatus: 178 | tcp://***HIDDEN***:10000: 179 | error: "" 180 | isPurging: false 181 | progress: 100 182 | state: complete 183 | tcp://***HIDDEN***:10000: 184 | error: "" 185 | isPurging: false 186 | progress: 100 187 | state: complete 188 | tcp://***HIDDEN***:10000: 189 | error: "" 190 | isPurging: false 191 | progress: 100 192 | state: complete 193 | rebuildStatus: {} 194 | replicaModeMap: 195 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328: RW 196 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc: RW 197 | pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-d711caf5: RW 198 | restoreStatus: 199 | tcp://***HIDDEN***:10000: 200 | backupURL: "" 201 | currentRestoringBackup: "" 202 | isRestoring: false 203 | lastRestored: "" 204 | state: "" 205 | tcp://***HIDDEN***:10000: 206 | backupURL: "" 207 | currentRestoringBackup: "" 208 | isRestoring: false 209 | lastRestored: "" 210 | state: "" 211 | tcp://***HIDDEN***:10000: 212 | backupURL: "" 213 | currentRestoringBackup: "" 214 | isRestoring: false 215 | lastRestored: "" 216 | state: "" 217 | salvageExecuted: false 218 | snapshots: 219 | 8afb0be0-addc-40c0-93b1-e5f5cc6f8c17: 220 | children: 221 | volume-head: true 222 | created: "2022-04-11T23:04:10Z" 223 | labels: {} 224 | name: 8afb0be0-addc-40c0-93b1-e5f5cc6f8c17 225 | parent: "" 226 | removed: true 227 | size: "239411200" 228 | usercreated: false 229 | volume-head: 230 | children: {} 231 | created: "2022-04-11T23:04:10Z" 232 | labels: {} 233 | name: volume-head 234 | parent: 8afb0be0-addc-40c0-93b1-e5f5cc6f8c17 235 | removed: false 236 | size: "0" 237 | usercreated: false 238 | snapshotsError: "" 239 | started: true 240 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/installers.cluster.kurl.sh/default.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: cluster.kurl.sh/v1beta1 2 | kind: Installer 3 | metadata: 4 | annotations: 5 | kubectl.kubernetes.io/last-applied-configuration: '***HIDDEN***' 6 | creationTimestamp: "2022-04-11T22:50:22Z" 7 | generation: 1 8 | labels: 9 | velero.io/exclude-from-backup: "true" 10 | managedFields: 11 | - apiVersion: cluster.kurl.sh/v1beta1 12 | fieldsType: FieldsV1 13 | fieldsV1: 14 | f:metadata: 15 | f:annotations: 16 | .: {} 17 | f:kubectl.kubernetes.io/last-applied-configuration: {} 18 | f:spec: 19 | .: {} 20 | f:contour: 21 | .: {} 22 | f:version: {} 23 | f:docker: 24 | .: {} 25 | f:version: {} 26 | f:ekco: 27 | .: {} 28 | f:version: {} 29 | f:kubernetes: 30 | .: {} 31 | f:HACluster: {} 32 | f:version: {} 33 | f:longhorn: 34 | .: {} 35 | f:version: {} 36 | f:minio: 37 | .: {} 38 | f:version: {} 39 | f:registry: 40 | .: {} 41 | f:version: {} 42 | f:velero: 43 | .: {} 44 | f:version: {} 45 | f:weave: 46 | .: {} 47 | f:version: {} 48 | f:status: {} 49 | manager: kubectl-client-side-apply 50 | operation: Update 51 | time: "2022-04-11T22:50:22Z" 52 | - apiVersion: cluster.kurl.sh/v1beta1 53 | fieldsType: FieldsV1 54 | fieldsV1: 55 | f:metadata: 56 | f:labels: 57 | .: {} 58 | f:velero.io/exclude-from-backup: {} 59 | manager: kubectl-label 60 | operation: Update 61 | time: "2022-04-11T22:50:22Z" 62 | name: f84c3b7 63 | namespace: default 64 | resourceVersion: "505" 65 | uid: 54961f1c-dea5-4c75-8fe4-862db9544bf2 66 | spec: 67 | contour: 68 | version: 1.20.1 69 | docker: 70 | version: 20.10.5 71 | ekco: 72 | version: 0.19.0 73 | kubernetes: 74 | HACluster: true 75 | version: 1.23.5 76 | longhorn: 77 | version: 1.2.2 78 | minio: 79 | version: 2020-01-25T02-50-51Z 80 | registry: 81 | version: 2.7.1 82 | velero: 83 | version: 1.7.1 84 | weave: 85 | version: 2.6.5 86 | status: {} 87 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/replicas.longhorn.io/longhorn-system.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: longhorn.io/v1beta1 2 | kind: Replica 3 | metadata: 4 | creationTimestamp: "2022-04-11T22:52:12Z" 5 | finalizers: 6 | - longhorn.io 7 | generation: 3 8 | labels: 9 | longhorn.io/backing-image: "" 10 | longhorndiskuuid: 7fd273ed-95c1-452f-87e0-8ecc94b6b8f1 11 | longhornnode: troubleshoot-demo-003 12 | longhornvolume: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 13 | managedFields: 14 | - apiVersion: longhorn.io/v1beta1 15 | fieldsType: FieldsV1 16 | fieldsV1: 17 | f:spec: 18 | f:healthyAt: {} 19 | f:status: 20 | f:currentImage: {} 21 | f:currentState: {} 22 | f:instanceManagerName: {} 23 | f:ip: {} 24 | f:ownerID: {} 25 | f:port: {} 26 | f:started: {} 27 | manager: longhorn-manager 28 | operation: Update 29 | time: "2022-04-11T23:03:49Z" 30 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-1cb3e328 31 | namespace: longhorn-system 32 | ownerReferences: 33 | - apiVersion: longhorn.io/v1beta1 34 | kind: Volume 35 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 36 | uid: 45f8c38f-23a5-440c-b36b-49c94491239f 37 | resourceVersion: "4276" 38 | uid: 2501c5e5-a419-4ef3-ac9c-69c54473f997 39 | spec: 40 | active: true 41 | backingImage: "" 42 | baseImage: "" 43 | dataDirectoryName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-38ad130c 44 | dataPath: "" 45 | desireState: running 46 | diskID: 7fd273ed-95c1-452f-87e0-8ecc94b6b8f1 47 | diskPath: /var/lib/longhorn/ 48 | engineImage: longhornio/longhorn-engine:v1.2.2 49 | engineName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-e-0886512b 50 | failedAt: "" 51 | hardNodeAffinity: "" 52 | healthyAt: "2022-04-11T23:03:49Z" 53 | logRequested: false 54 | nodeID: troubleshoot-demo-003 55 | rebuildRetryCount: 0 56 | revisionCounterDisabled: false 57 | salvageRequested: false 58 | volumeName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 59 | volumeSize: "10737418240" 60 | status: 61 | currentImage: longhornio/longhorn-engine:v1.2.2 62 | currentState: running 63 | evictionRequested: false 64 | instanceManagerName: instance-manager-r-af1c7a93 65 | ip: ***HIDDEN*** 66 | logFetched: false 67 | ownerID: troubleshoot-demo-003 68 | port: 10000 69 | salvageExecuted: false 70 | started: true 71 | - apiVersion: longhorn.io/v1beta1 72 | kind: Replica 73 | metadata: 74 | creationTimestamp: "2022-04-11T22:52:12Z" 75 | finalizers: 76 | - longhorn.io 77 | generation: 3 78 | labels: 79 | longhorn.io/backing-image: "" 80 | longhorndiskuuid: 5f349161-6348-494a-abb6-ead2a3c5e64b 81 | longhornnode: troubleshoot-demo-002 82 | longhornvolume: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 83 | managedFields: 84 | - apiVersion: longhorn.io/v1beta1 85 | fieldsType: FieldsV1 86 | fieldsV1: 87 | f:spec: 88 | f:healthyAt: {} 89 | f:status: 90 | f:currentImage: {} 91 | f:currentState: {} 92 | f:instanceManagerName: {} 93 | f:ip: {} 94 | f:ownerID: {} 95 | f:port: {} 96 | f:started: {} 97 | manager: longhorn-manager 98 | operation: Update 99 | time: "2022-04-11T23:04:19Z" 100 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-260e62dc 101 | namespace: longhorn-system 102 | ownerReferences: 103 | - apiVersion: longhorn.io/v1beta1 104 | kind: Volume 105 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 106 | uid: 45f8c38f-23a5-440c-b36b-49c94491239f 107 | resourceVersion: "4501" 108 | uid: 5906fef7-7bdc-4c21-93cf-c692346da861 109 | spec: 110 | active: true 111 | backingImage: "" 112 | baseImage: "" 113 | dataDirectoryName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-0a40a8a2 114 | dataPath: "" 115 | desireState: running 116 | diskID: 5f349161-6348-494a-abb6-ead2a3c5e64b 117 | diskPath: /var/lib/longhorn/ 118 | engineImage: longhornio/longhorn-engine:v1.2.2 119 | engineName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-e-0886512b 120 | failedAt: "" 121 | hardNodeAffinity: "" 122 | healthyAt: "2022-04-11T23:04:19Z" 123 | logRequested: false 124 | nodeID: troubleshoot-demo-002 125 | rebuildRetryCount: 0 126 | revisionCounterDisabled: false 127 | salvageRequested: false 128 | volumeName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 129 | volumeSize: "10737418240" 130 | status: 131 | currentImage: longhornio/longhorn-engine:v1.2.2 132 | currentState: running 133 | evictionRequested: false 134 | instanceManagerName: instance-manager-r-a5bf42e3 135 | ip: ***HIDDEN*** 136 | logFetched: false 137 | ownerID: troubleshoot-demo-002 138 | port: 10000 139 | salvageExecuted: false 140 | started: true 141 | - apiVersion: longhorn.io/v1beta1 142 | kind: Replica 143 | metadata: 144 | creationTimestamp: "2022-04-11T22:52:12Z" 145 | finalizers: 146 | - longhorn.io 147 | generation: 4 148 | labels: 149 | longhorn.io/backing-image: "" 150 | longhorndiskuuid: 7e36f026-0b23-466b-991c-d46fb322c462 151 | longhornnode: troubleshoot-demo-001 152 | longhornvolume: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 153 | managedFields: 154 | - apiVersion: longhorn.io/v1beta1 155 | fieldsType: FieldsV1 156 | fieldsV1: 157 | f:spec: 158 | f:healthyAt: {} 159 | f:status: 160 | f:currentImage: {} 161 | f:currentState: {} 162 | f:instanceManagerName: {} 163 | f:ip: {} 164 | f:port: {} 165 | f:started: {} 166 | manager: longhorn-manager 167 | operation: Update 168 | time: "2022-04-11T22:52:29Z" 169 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-r-d711caf5 170 | namespace: longhorn-system 171 | ownerReferences: 172 | - apiVersion: longhorn.io/v1beta1 173 | kind: Volume 174 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 175 | uid: 45f8c38f-23a5-440c-b36b-49c94491239f 176 | resourceVersion: "1460" 177 | uid: 8accc8e1-3d3a-43b7-b9b9-04fd7e740114 178 | spec: 179 | active: true 180 | backingImage: "" 181 | baseImage: "" 182 | dataDirectoryName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-d411d0d7 183 | dataPath: "" 184 | desireState: running 185 | diskID: 7e36f026-0b23-466b-991c-d46fb322c462 186 | diskPath: /var/lib/longhorn/ 187 | engineImage: longhornio/longhorn-engine:v1.2.2 188 | engineName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b-e-0886512b 189 | failedAt: "" 190 | hardNodeAffinity: "" 191 | healthyAt: "2022-04-11T22:52:29Z" 192 | logRequested: false 193 | nodeID: troubleshoot-demo-001 194 | rebuildRetryCount: 0 195 | revisionCounterDisabled: false 196 | salvageRequested: false 197 | volumeName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 198 | volumeSize: "10737418240" 199 | status: 200 | currentImage: longhornio/longhorn-engine:v1.2.2 201 | currentState: running 202 | evictionRequested: false 203 | instanceManagerName: instance-manager-r-f0f1e9d6 204 | ip: ***HIDDEN*** 205 | logFetched: false 206 | ownerID: troubleshoot-demo-001 207 | port: 10000 208 | salvageExecuted: false 209 | started: true 210 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/custom-resources/volumes.longhorn.io/longhorn-system.yaml: -------------------------------------------------------------------------------- 1 | - apiVersion: longhorn.io/v1beta1 2 | kind: Volume 3 | metadata: 4 | creationTimestamp: "2022-04-11T22:52:12Z" 5 | finalizers: 6 | - longhorn.io 7 | generation: 2 8 | labels: 9 | longhornvolume: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 10 | recurring-job-group.longhorn.io/default: enabled 11 | managedFields: 12 | - apiVersion: longhorn.io/v1beta1 13 | fieldsType: FieldsV1 14 | fieldsV1: 15 | f:spec: 16 | f:nodeID: {} 17 | f:status: 18 | .: {} 19 | f:cloneStatus: 20 | .: {} 21 | f:snapshot: {} 22 | f:sourceVolume: {} 23 | f:state: {} 24 | f:conditions: 25 | .: {} 26 | f:restore: 27 | .: {} 28 | f:lastProbeTime: {} 29 | f:lastTransitionTime: {} 30 | f:message: {} 31 | f:reason: {} 32 | f:status: {} 33 | f:type: {} 34 | f:scheduled: 35 | .: {} 36 | f:lastProbeTime: {} 37 | f:type: {} 38 | f:toomanysnapshots: 39 | .: {} 40 | f:lastProbeTime: {} 41 | f:lastTransitionTime: {} 42 | f:message: {} 43 | f:reason: {} 44 | f:status: {} 45 | f:type: {} 46 | f:currentImage: {} 47 | f:expansionRequired: {} 48 | f:frontendDisabled: {} 49 | f:isStandby: {} 50 | f:kubernetesStatus: 51 | .: {} 52 | f:lastPVCRefAt: {} 53 | f:lastPodRefAt: {} 54 | f:namespace: {} 55 | f:pvName: {} 56 | f:pvStatus: {} 57 | f:pvcName: {} 58 | f:lastBackup: {} 59 | f:lastBackupAt: {} 60 | f:ownerID: {} 61 | f:pendingNodeID: {} 62 | f:remountRequestedAt: {} 63 | f:restoreInitiated: {} 64 | f:restoreRequired: {} 65 | f:shareEndpoint: {} 66 | f:shareState: {} 67 | manager: longhorn-manager 68 | operation: Update 69 | time: "2022-04-11T22:52:18Z" 70 | - apiVersion: longhorn.io/v1beta1 71 | fieldsType: FieldsV1 72 | fieldsV1: 73 | f:status: 74 | f:actualSize: {} 75 | f:conditions: 76 | f:scheduled: 77 | f:lastTransitionTime: {} 78 | f:message: {} 79 | f:reason: {} 80 | f:status: {} 81 | f:currentNodeID: {} 82 | f:kubernetesStatus: 83 | f:workloadsStatus: {} 84 | f:lastDegradedAt: {} 85 | f:robustness: {} 86 | f:state: {} 87 | manager: longhorn-manager 88 | operation: Update 89 | subresource: status 90 | time: "2022-04-11T22:52:34Z" 91 | name: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 92 | namespace: longhorn-system 93 | resourceVersion: "4502" 94 | uid: 45f8c38f-23a5-440c-b36b-49c94491239f 95 | spec: 96 | Standby: false 97 | accessMode: rwo 98 | backingImage: "" 99 | baseImage: "" 100 | dataLocality: disabled 101 | dataSource: "" 102 | disableFrontend: false 103 | diskSelector: null 104 | encrypted: false 105 | engineImage: longhornio/longhorn-engine:v1.2.2 106 | fromBackup: "" 107 | frontend: blockdev 108 | lastAttachedBy: "" 109 | migratable: false 110 | migrationNodeID: "" 111 | nodeID: troubleshoot-demo-001 112 | nodeSelector: null 113 | numberOfReplicas: 3 114 | replicaAutoBalance: ignored 115 | revisionCounterDisabled: false 116 | size: "10737418240" 117 | staleReplicaTimeout: 2880 118 | status: 119 | actualSize: 239411200 120 | cloneStatus: 121 | snapshot: "" 122 | sourceVolume: "" 123 | state: "" 124 | conditions: 125 | restore: 126 | lastProbeTime: "" 127 | lastTransitionTime: "2022-04-11T22:52:14Z" 128 | message: "" 129 | reason: "" 130 | status: "False" 131 | type: restore 132 | scheduled: 133 | lastProbeTime: "" 134 | lastTransitionTime: "2022-04-11T23:04:10Z" 135 | message: "" 136 | reason: "" 137 | status: "True" 138 | type: scheduled 139 | toomanysnapshots: 140 | lastProbeTime: "" 141 | lastTransitionTime: "2022-04-11T22:52:14Z" 142 | message: "" 143 | reason: "" 144 | status: "False" 145 | type: toomanysnapshots 146 | currentImage: longhornio/longhorn-engine:v1.2.2 147 | currentNodeID: troubleshoot-demo-001 148 | expansionRequired: false 149 | frontendDisabled: false 150 | isStandby: false 151 | kubernetesStatus: 152 | lastPVCRefAt: "" 153 | lastPodRefAt: "" 154 | namespace: minio 155 | pvName: pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b 156 | pvStatus: Bound 157 | pvcName: minio-pv-claim 158 | workloadsStatus: 159 | - podName: minio-7b45cd544d-2gwml 160 | podStatus: Running 161 | workloadName: minio-7b45cd544d 162 | workloadType: ReplicaSet 163 | lastBackup: "" 164 | lastBackupAt: "" 165 | lastDegradedAt: "" 166 | ownerID: troubleshoot-demo-001 167 | pendingNodeID: "" 168 | remountRequestedAt: "" 169 | restoreInitiated: false 170 | restoreRequired: false 171 | robustness: healthy 172 | shareEndpoint: "" 173 | shareState: "" 174 | state: attached 175 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/deployments/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "DeploymentList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/deployments/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "DeploymentList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/deployments/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "DeploymentList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27215" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27215" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27215" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27216" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/events/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "EventList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27217" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/groups.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "name": "", 4 | "versions": [ 5 | { 6 | "groupVersion": "v1", 7 | "version": "v1" 8 | } 9 | ], 10 | "preferredVersion": { 11 | "groupVersion": "v1", 12 | "version": "v1" 13 | } 14 | }, 15 | { 16 | "name": "apiregistration.k8s.io", 17 | "versions": [ 18 | { 19 | "groupVersion": "apiregistration.k8s.io/v1", 20 | "version": "v1" 21 | } 22 | ], 23 | "preferredVersion": { 24 | "groupVersion": "apiregistration.k8s.io/v1", 25 | "version": "v1" 26 | } 27 | }, 28 | { 29 | "name": "apps", 30 | "versions": [ 31 | { 32 | "groupVersion": "apps/v1", 33 | "version": "v1" 34 | } 35 | ], 36 | "preferredVersion": { 37 | "groupVersion": "apps/v1", 38 | "version": "v1" 39 | } 40 | }, 41 | { 42 | "name": "events.k8s.io", 43 | "versions": [ 44 | { 45 | "groupVersion": "events.k8s.io/v1", 46 | "version": "v1" 47 | }, 48 | { 49 | "groupVersion": "events.k8s.io/v1beta1", 50 | "version": "v1beta1" 51 | } 52 | ], 53 | "preferredVersion": { 54 | "groupVersion": "events.k8s.io/v1", 55 | "version": "v1" 56 | } 57 | }, 58 | { 59 | "name": "authentication.k8s.io", 60 | "versions": [ 61 | { 62 | "groupVersion": "authentication.k8s.io/v1", 63 | "version": "v1" 64 | } 65 | ], 66 | "preferredVersion": { 67 | "groupVersion": "authentication.k8s.io/v1", 68 | "version": "v1" 69 | } 70 | }, 71 | { 72 | "name": "authorization.k8s.io", 73 | "versions": [ 74 | { 75 | "groupVersion": "authorization.k8s.io/v1", 76 | "version": "v1" 77 | } 78 | ], 79 | "preferredVersion": { 80 | "groupVersion": "authorization.k8s.io/v1", 81 | "version": "v1" 82 | } 83 | }, 84 | { 85 | "name": "autoscaling", 86 | "versions": [ 87 | { 88 | "groupVersion": "autoscaling/v2", 89 | "version": "v2" 90 | }, 91 | { 92 | "groupVersion": "autoscaling/v1", 93 | "version": "v1" 94 | }, 95 | { 96 | "groupVersion": "autoscaling/v2beta1", 97 | "version": "v2beta1" 98 | }, 99 | { 100 | "groupVersion": "autoscaling/v2beta2", 101 | "version": "v2beta2" 102 | } 103 | ], 104 | "preferredVersion": { 105 | "groupVersion": "autoscaling/v2", 106 | "version": "v2" 107 | } 108 | }, 109 | { 110 | "name": "batch", 111 | "versions": [ 112 | { 113 | "groupVersion": "batch/v1", 114 | "version": "v1" 115 | }, 116 | { 117 | "groupVersion": "batch/v1beta1", 118 | "version": "v1beta1" 119 | } 120 | ], 121 | "preferredVersion": { 122 | "groupVersion": "batch/v1", 123 | "version": "v1" 124 | } 125 | }, 126 | { 127 | "name": "certificates.k8s.io", 128 | "versions": [ 129 | { 130 | "groupVersion": "certificates.k8s.io/v1", 131 | "version": "v1" 132 | } 133 | ], 134 | "preferredVersion": { 135 | "groupVersion": "certificates.k8s.io/v1", 136 | "version": "v1" 137 | } 138 | }, 139 | { 140 | "name": "networking.k8s.io", 141 | "versions": [ 142 | { 143 | "groupVersion": "networking.k8s.io/v1", 144 | "version": "v1" 145 | } 146 | ], 147 | "preferredVersion": { 148 | "groupVersion": "networking.k8s.io/v1", 149 | "version": "v1" 150 | } 151 | }, 152 | { 153 | "name": "policy", 154 | "versions": [ 155 | { 156 | "groupVersion": "policy/v1", 157 | "version": "v1" 158 | }, 159 | { 160 | "groupVersion": "policy/v1beta1", 161 | "version": "v1beta1" 162 | } 163 | ], 164 | "preferredVersion": { 165 | "groupVersion": "policy/v1", 166 | "version": "v1" 167 | } 168 | }, 169 | { 170 | "name": "rbac.authorization.k8s.io", 171 | "versions": [ 172 | { 173 | "groupVersion": "rbac.authorization.k8s.io/v1", 174 | "version": "v1" 175 | } 176 | ], 177 | "preferredVersion": { 178 | "groupVersion": "rbac.authorization.k8s.io/v1", 179 | "version": "v1" 180 | } 181 | }, 182 | { 183 | "name": "storage.k8s.io", 184 | "versions": [ 185 | { 186 | "groupVersion": "storage.k8s.io/v1", 187 | "version": "v1" 188 | }, 189 | { 190 | "groupVersion": "storage.k8s.io/v1beta1", 191 | "version": "v1beta1" 192 | } 193 | ], 194 | "preferredVersion": { 195 | "groupVersion": "storage.k8s.io/v1", 196 | "version": "v1" 197 | } 198 | }, 199 | { 200 | "name": "admissionregistration.k8s.io", 201 | "versions": [ 202 | { 203 | "groupVersion": "admissionregistration.k8s.io/v1", 204 | "version": "v1" 205 | } 206 | ], 207 | "preferredVersion": { 208 | "groupVersion": "admissionregistration.k8s.io/v1", 209 | "version": "v1" 210 | } 211 | }, 212 | { 213 | "name": "apiextensions.k8s.io", 214 | "versions": [ 215 | { 216 | "groupVersion": "apiextensions.k8s.io/v1", 217 | "version": "v1" 218 | } 219 | ], 220 | "preferredVersion": { 221 | "groupVersion": "apiextensions.k8s.io/v1", 222 | "version": "v1" 223 | } 224 | }, 225 | { 226 | "name": "scheduling.k8s.io", 227 | "versions": [ 228 | { 229 | "groupVersion": "scheduling.k8s.io/v1", 230 | "version": "v1" 231 | } 232 | ], 233 | "preferredVersion": { 234 | "groupVersion": "scheduling.k8s.io/v1", 235 | "version": "v1" 236 | } 237 | }, 238 | { 239 | "name": "coordination.k8s.io", 240 | "versions": [ 241 | { 242 | "groupVersion": "coordination.k8s.io/v1", 243 | "version": "v1" 244 | } 245 | ], 246 | "preferredVersion": { 247 | "groupVersion": "coordination.k8s.io/v1", 248 | "version": "v1" 249 | } 250 | }, 251 | { 252 | "name": "node.k8s.io", 253 | "versions": [ 254 | { 255 | "groupVersion": "node.k8s.io/v1", 256 | "version": "v1" 257 | }, 258 | { 259 | "groupVersion": "node.k8s.io/v1beta1", 260 | "version": "v1beta1" 261 | } 262 | ], 263 | "preferredVersion": { 264 | "groupVersion": "node.k8s.io/v1", 265 | "version": "v1" 266 | } 267 | }, 268 | { 269 | "name": "discovery.k8s.io", 270 | "versions": [ 271 | { 272 | "groupVersion": "discovery.k8s.io/v1", 273 | "version": "v1" 274 | }, 275 | { 276 | "groupVersion": "discovery.k8s.io/v1beta1", 277 | "version": "v1beta1" 278 | } 279 | ], 280 | "preferredVersion": { 281 | "groupVersion": "discovery.k8s.io/v1", 282 | "version": "v1" 283 | } 284 | }, 285 | { 286 | "name": "flowcontrol.apiserver.k8s.io", 287 | "versions": [ 288 | { 289 | "groupVersion": "flowcontrol.apiserver.k8s.io/v1beta2", 290 | "version": "v1beta2" 291 | }, 292 | { 293 | "groupVersion": "flowcontrol.apiserver.k8s.io/v1beta1", 294 | "version": "v1beta1" 295 | } 296 | ], 297 | "preferredVersion": { 298 | "groupVersion": "flowcontrol.apiserver.k8s.io/v1beta2", 299 | "version": "v1beta2" 300 | } 301 | }, 302 | { 303 | "name": "projectcontour.io", 304 | "versions": [ 305 | { 306 | "groupVersion": "projectcontour.io/v1", 307 | "version": "v1" 308 | }, 309 | { 310 | "groupVersion": "projectcontour.io/v1alpha1", 311 | "version": "v1alpha1" 312 | } 313 | ], 314 | "preferredVersion": { 315 | "groupVersion": "projectcontour.io/v1", 316 | "version": "v1" 317 | } 318 | }, 319 | { 320 | "name": "velero.io", 321 | "versions": [ 322 | { 323 | "groupVersion": "velero.io/v1", 324 | "version": "v1" 325 | } 326 | ], 327 | "preferredVersion": { 328 | "groupVersion": "velero.io/v1", 329 | "version": "v1" 330 | } 331 | }, 332 | { 333 | "name": "cluster.kurl.sh", 334 | "versions": [ 335 | { 336 | "groupVersion": "cluster.kurl.sh/v1beta1", 337 | "version": "v1beta1" 338 | } 339 | ], 340 | "preferredVersion": { 341 | "groupVersion": "cluster.kurl.sh/v1beta1", 342 | "version": "v1beta1" 343 | } 344 | }, 345 | { 346 | "name": "longhorn.io", 347 | "versions": [ 348 | { 349 | "groupVersion": "longhorn.io/v1beta1", 350 | "version": "v1beta1" 351 | } 352 | ], 353 | "preferredVersion": { 354 | "groupVersion": "longhorn.io/v1beta1", 355 | "version": "v1beta1" 356 | } 357 | } 358 | ] 359 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/image-pull-secrets/default/registry-creds.json: -------------------------------------------------------------------------------- 1 | {"***HIDDEN***":"kurl"} 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/ingress/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "IngressList", 3 | "apiVersion": "networking.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Job", 10 | "apiVersion": "batch/v1", 11 | "metadata": { 12 | "name": "contour-certgen-v1.20.1", 13 | "namespace": "projectcontour", 14 | "uid": "28ea83d9-637b-4b58-9a9f-cf6dbef4f441", 15 | "resourceVersion": "1622", 16 | "generation": 1, 17 | "creationTimestamp": "2022-04-11T22:52:43Z", 18 | "labels": { 19 | "app": "contour-certgen", 20 | "controller-uid": "28ea83d9-637b-4b58-9a9f-cf6dbef4f441", 21 | "job-name": "contour-certgen-v1.20.1" 22 | }, 23 | "annotations": { 24 | "batch.kubernetes.io/job-tracking": "", 25 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"batch/v1\",\"kind\":\"Job\",\"metadata\":{\"annotations\":{},\"name\":\"contour-certgen-v1.20.1\",\"namespace\":\"projectcontour\"},\"spec\":{\"backoffLimit\":1,\"completions\":1,\"parallelism\":1,\"template\":{\"metadata\":{\"labels\":{\"app\":\"contour-certgen\"}},\"spec\":{\"containers\":[{\"command\":[\"contour\",\"certgen\",\"--kube\",\"--incluster\",\"--overwrite\",\"--secrets-format=compact\",\"--namespace=$(CONTOUR_NAMESPACE)\"],\"env\":[{\"name\":\"CONTOUR_NAMESPACE\",\"valueFrom\":{\"fieldRef\":{\"fieldPath\":\"metadata.namespace\"}}}],\"image\":\"ghcr.io/projectcontour/contour:v1.20.1\",\"imagePullPolicy\":\"IfNotPresent\",\"name\":\"contour\"}],\"restartPolicy\":\"Never\",\"securityContext\":{\"runAsGroup\":65534,\"runAsNonRoot\":true,\"runAsUser\":65534},\"serviceAccountName\":\"contour-certgen\"}}}}\n" 26 | }, 27 | "managedFields": [ 28 | { 29 | "manager": "kubectl-client-side-apply", 30 | "operation": "Update", 31 | "apiVersion": "batch/v1", 32 | "time": "2022-04-11T22:52:43Z", 33 | "fieldsType": "FieldsV1", 34 | "fieldsV1": { 35 | "f:metadata": { 36 | "f:annotations": { 37 | ".": {}, 38 | "f:kubectl.kubernetes.io/last-applied-configuration": {} 39 | }, 40 | "f:labels": { 41 | ".": {}, 42 | "f:app": {} 43 | } 44 | }, 45 | "f:spec": { 46 | "f:backoffLimit": {}, 47 | "f:completionMode": {}, 48 | "f:completions": {}, 49 | "f:parallelism": {}, 50 | "f:suspend": {}, 51 | "f:template": { 52 | "f:metadata": { 53 | "f:labels": { 54 | ".": {}, 55 | "f:app": {} 56 | } 57 | }, 58 | "f:spec": { 59 | "f:containers": { 60 | "k:{\"name\":\"contour\"}": { 61 | ".": {}, 62 | "f:command": {}, 63 | "f:env": { 64 | ".": {}, 65 | "k:{\"name\":\"CONTOUR_NAMESPACE\"}": { 66 | ".": {}, 67 | "f:name": {}, 68 | "f:valueFrom": { 69 | ".": {}, 70 | "f:fieldRef": {} 71 | } 72 | } 73 | }, 74 | "f:image": {}, 75 | "f:imagePullPolicy": {}, 76 | "f:name": {}, 77 | "f:resources": {}, 78 | "f:terminationMessagePath": {}, 79 | "f:terminationMessagePolicy": {} 80 | } 81 | }, 82 | "f:dnsPolicy": {}, 83 | "f:restartPolicy": {}, 84 | "f:schedulerName": {}, 85 | "f:securityContext": { 86 | ".": {}, 87 | "f:runAsGroup": {}, 88 | "f:runAsNonRoot": {}, 89 | "f:runAsUser": {} 90 | }, 91 | "f:serviceAccount": {}, 92 | "f:serviceAccountName": {}, 93 | "f:terminationGracePeriodSeconds": {} 94 | } 95 | } 96 | } 97 | } 98 | }, 99 | { 100 | "manager": "kube-controller-manager", 101 | "operation": "Update", 102 | "apiVersion": "batch/v1", 103 | "time": "2022-04-11T22:52:46Z", 104 | "fieldsType": "FieldsV1", 105 | "fieldsV1": { 106 | "f:status": { 107 | "f:completionTime": {}, 108 | "f:conditions": {}, 109 | "f:startTime": {}, 110 | "f:succeeded": {}, 111 | "f:uncountedTerminatedPods": {} 112 | } 113 | }, 114 | "subresource": "status" 115 | } 116 | ] 117 | }, 118 | "spec": { 119 | "parallelism": 1, 120 | "completions": 1, 121 | "backoffLimit": 1, 122 | "selector": { 123 | "matchLabels": { 124 | "controller-uid": "28ea83d9-637b-4b58-9a9f-cf6dbef4f441" 125 | } 126 | }, 127 | "template": { 128 | "metadata": { 129 | "creationTimestamp": null, 130 | "labels": { 131 | "app": "contour-certgen", 132 | "controller-uid": "28ea83d9-637b-4b58-9a9f-cf6dbef4f441", 133 | "job-name": "contour-certgen-v1.20.1" 134 | } 135 | }, 136 | "spec": { 137 | "containers": [ 138 | { 139 | "name": "contour", 140 | "image": "ghcr.io/projectcontour/contour:v1.20.1", 141 | "command": [ 142 | "contour", 143 | "certgen", 144 | "--kube", 145 | "--incluster", 146 | "--overwrite", 147 | "--secrets-format=compact", 148 | "--namespace=$(CONTOUR_NAMESPACE)" 149 | ], 150 | "env": [ 151 | { 152 | "name": "CONTOUR_NAMESPACE", 153 | "valueFrom": { 154 | "fieldRef": { 155 | "apiVersion": "v1", 156 | "fieldPath": "metadata.namespace" 157 | } 158 | } 159 | } 160 | ], 161 | "resources": {}, 162 | "terminationMessagePath": "/dev/termination-log", 163 | "terminationMessagePolicy": "File", 164 | "imagePullPolicy": "IfNotPresent" 165 | } 166 | ], 167 | "restartPolicy": "Never", 168 | "terminationGracePeriodSeconds": 30, 169 | "dnsPolicy": "ClusterFirst", 170 | "serviceAccountName": "contour-certgen", 171 | "serviceAccount": "contour-certgen", 172 | "securityContext": { 173 | "runAsUser": 65534, 174 | "runAsGroup": 65534, 175 | "runAsNonRoot": true 176 | }, 177 | "schedulerName": "default-scheduler" 178 | } 179 | }, 180 | "completionMode": "NonIndexed", 181 | "suspend": false 182 | }, 183 | "status": { 184 | "conditions": [ 185 | { 186 | "type": "Complete", 187 | "status": "True", 188 | "lastProbeTime": "2022-04-11T22:52:46Z", 189 | "lastTransitionTime": "2022-04-11T22:52:46Z" 190 | } 191 | ], 192 | "startTime": "2022-04-11T22:52:43Z", 193 | "completionTime": "2022-04-11T22:52:46Z", 194 | "succeeded": 1, 195 | "uncountedTerminatedPods": {} 196 | } 197 | } 198 | ] 199 | } 200 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/jobs/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "JobList", 3 | "apiVersion": "batch/v1", 4 | "metadata": { 5 | "resourceVersion": "27157" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27212" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27212" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27212" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/limitranges/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "LimitRangeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27214" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PodList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27131" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PodList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27131" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PodList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27131" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/replicated-kurl-util.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/replicated-local-volume-provider.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/velero-previous.log: -------------------------------------------------------------------------------- 1 | Error: unknown command "server-junk" for "velero" 2 | Run 'velero --help' for usage. 3 | An error occurred: unknown command "server-junk" for "velero" 4 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/velero-velero-plugin-for-aws.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/velero-velero-plugin-for-gcp.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/velero-velero-plugin-for-microsoft-azure.log: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pods/logs/velero/velero-6996dd565b-xl44t/velero.log: -------------------------------------------------------------------------------- 1 | Error: unknown command "server-junk" for "velero" 2 | Run 'velero --help' for usage. 3 | An error occurred: unknown command "server-junk" for "velero" 4 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27221" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27223" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27223" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27223" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27223" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27224" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27224" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "PersistentVolumeClaim", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "minio-pv-claim", 13 | "namespace": "minio", 14 | "uid": "36557d76-e15e-4abe-91ee-0be6075eaa7b", 15 | "resourceVersion": "1396", 16 | "creationTimestamp": "2022-04-11T22:51:59Z", 17 | "annotations": { 18 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"PersistentVolumeClaim\",\"metadata\":{\"annotations\":{},\"name\":\"minio-pv-claim\",\"namespace\":\"minio\"},\"spec\":{\"accessModes\":[\"ReadWriteOnce\"],\"resources\":{\"requests\":{\"storage\":\"10Gi\"}}}}\n", 19 | "pv.kubernetes.io/bind-completed": "yes", 20 | "pv.kubernetes.io/bound-by-controller": "yes", 21 | "volume.beta.kubernetes.io/storage-provisioner": "driver.longhorn.io", 22 | "volume.kubernetes.io/storage-provisioner": "driver.longhorn.io" 23 | }, 24 | "finalizers": [ 25 | "kubernetes.io/pvc-protection" 26 | ], 27 | "managedFields": [ 28 | { 29 | "manager": "kubectl-client-side-apply", 30 | "operation": "Update", 31 | "apiVersion": "v1", 32 | "time": "2022-04-11T22:51:59Z", 33 | "fieldsType": "FieldsV1", 34 | "fieldsV1": { 35 | "f:metadata": { 36 | "f:annotations": { 37 | ".": {}, 38 | "f:kubectl.kubernetes.io/last-applied-configuration": {} 39 | } 40 | }, 41 | "f:spec": { 42 | "f:accessModes": {}, 43 | "f:resources": { 44 | "f:requests": { 45 | ".": {}, 46 | "f:storage": {} 47 | } 48 | }, 49 | "f:volumeMode": {} 50 | } 51 | } 52 | }, 53 | { 54 | "manager": "kube-controller-manager", 55 | "operation": "Update", 56 | "apiVersion": "v1", 57 | "time": "2022-04-11T22:52:16Z", 58 | "fieldsType": "FieldsV1", 59 | "fieldsV1": { 60 | "f:metadata": { 61 | "f:annotations": { 62 | "f:pv.kubernetes.io/bind-completed": {}, 63 | "f:pv.kubernetes.io/bound-by-controller": {}, 64 | "f:volume.beta.kubernetes.io/storage-provisioner": {}, 65 | "f:volume.kubernetes.io/storage-provisioner": {} 66 | } 67 | }, 68 | "f:spec": { 69 | "f:volumeName": {} 70 | } 71 | } 72 | }, 73 | { 74 | "manager": "kube-controller-manager", 75 | "operation": "Update", 76 | "apiVersion": "v1", 77 | "time": "2022-04-11T22:52:16Z", 78 | "fieldsType": "FieldsV1", 79 | "fieldsV1": { 80 | "f:status": { 81 | "f:accessModes": {}, 82 | "f:capacity": { 83 | ".": {}, 84 | "f:storage": {} 85 | }, 86 | "f:phase": {} 87 | } 88 | }, 89 | "subresource": "status" 90 | } 91 | ] 92 | }, 93 | "spec": { 94 | "accessModes": [ 95 | "ReadWriteOnce" 96 | ], 97 | "resources": { 98 | "requests": { 99 | "storage": "10Gi" 100 | } 101 | }, 102 | "volumeName": "pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b", 103 | "storageClassName": "longhorn", 104 | "volumeMode": "Filesystem" 105 | }, 106 | "status": { 107 | "phase": "Bound", 108 | "accessModes": [ 109 | "ReadWriteOnce" 110 | ], 111 | "capacity": { 112 | "storage": "10Gi" 113 | } 114 | } 115 | } 116 | ] 117 | } 118 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27226" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvcs/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeClaimList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27226" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/pvs.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "PersistentVolumeList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27221" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "PersistentVolume", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b", 13 | "uid": "a297a34a-03d7-4e34-82a3-f46ef2d78816", 14 | "resourceVersion": "1420", 15 | "creationTimestamp": "2022-04-11T22:52:16Z", 16 | "annotations": { 17 | "pv.kubernetes.io/provisioned-by": "driver.longhorn.io" 18 | }, 19 | "finalizers": [ 20 | "kubernetes.io/pv-protection", 21 | "external-attacher/driver-longhorn-io" 22 | ], 23 | "managedFields": [ 24 | { 25 | "manager": "csi-provisioner", 26 | "operation": "Update", 27 | "apiVersion": "v1", 28 | "time": "2022-04-11T22:52:16Z", 29 | "fieldsType": "FieldsV1", 30 | "fieldsV1": { 31 | "f:metadata": { 32 | "f:annotations": { 33 | ".": {}, 34 | "f:pv.kubernetes.io/provisioned-by": {} 35 | } 36 | }, 37 | "f:spec": { 38 | "f:accessModes": {}, 39 | "f:capacity": { 40 | ".": {}, 41 | "f:storage": {} 42 | }, 43 | "f:claimRef": {}, 44 | "f:csi": { 45 | ".": {}, 46 | "f:driver": {}, 47 | "f:fsType": {}, 48 | "f:volumeAttributes": { 49 | ".": {}, 50 | "f:fromBackup": {}, 51 | "f:numberOfReplicas": {}, 52 | "f:staleReplicaTimeout": {}, 53 | "f:storage.kubernetes.io/csiProvisionerIdentity": {} 54 | }, 55 | "f:volumeHandle": {} 56 | }, 57 | "f:persistentVolumeReclaimPolicy": {}, 58 | "f:storageClassName": {}, 59 | "f:volumeMode": {} 60 | } 61 | } 62 | }, 63 | { 64 | "manager": "kube-controller-manager", 65 | "operation": "Update", 66 | "apiVersion": "v1", 67 | "time": "2022-04-11T22:52:16Z", 68 | "fieldsType": "FieldsV1", 69 | "fieldsV1": { 70 | "f:status": { 71 | "f:phase": {} 72 | } 73 | }, 74 | "subresource": "status" 75 | }, 76 | { 77 | "manager": "csi-attacher", 78 | "operation": "Update", 79 | "apiVersion": "v1", 80 | "time": "2022-04-11T22:52:18Z", 81 | "fieldsType": "FieldsV1", 82 | "fieldsV1": { 83 | "f:metadata": { 84 | "f:finalizers": { 85 | "v:\"external-attacher/driver-longhorn-io\"": {} 86 | } 87 | } 88 | } 89 | } 90 | ] 91 | }, 92 | "spec": { 93 | "capacity": { 94 | "storage": "10Gi" 95 | }, 96 | "csi": { 97 | "driver": "driver.longhorn.io", 98 | "volumeHandle": "pvc-36557d76-e15e-4abe-91ee-0be6075eaa7b", 99 | "fsType": "ext4", 100 | "volumeAttributes": { 101 | "fromBackup": "", 102 | "numberOfReplicas": "3", 103 | "staleReplicaTimeout": "2880", 104 | "storage.kubernetes.io/csiProvisionerIdentity": "1649717531982-8081-driver.longhorn.io" 105 | } 106 | }, 107 | "accessModes": [ 108 | "ReadWriteOnce" 109 | ], 110 | "claimRef": { 111 | "kind": "PersistentVolumeClaim", 112 | "namespace": "minio", 113 | "name": "minio-pv-claim", 114 | "uid": "36557d76-e15e-4abe-91ee-0be6075eaa7b", 115 | "apiVersion": "v1", 116 | "resourceVersion": "1079" 117 | }, 118 | "persistentVolumeReclaimPolicy": "Delete", 119 | "storageClassName": "longhorn", 120 | "volumeMode": "Filesystem" 121 | }, 122 | "status": { 123 | "phase": "Bound" 124 | } 125 | } 126 | ] 127 | } 128 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/replicasets/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ReplicaSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27150" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/replicasets/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ReplicaSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27150" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/replicasets/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ReplicaSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27153" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/replicasets/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ReplicaSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27156" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "ReplicaSet", 10 | "apiVersion": "apps/v1", 11 | "metadata": { 12 | "name": "minio-7b45cd544d", 13 | "namespace": "minio", 14 | "uid": "385d3831-e8f4-4ca4-81c6-8efcb2026413", 15 | "resourceVersion": "1498", 16 | "generation": 1, 17 | "creationTimestamp": "2022-04-11T22:51:59Z", 18 | "labels": { 19 | "app": "minio", 20 | "pod-template-hash": "7b45cd544d" 21 | }, 22 | "annotations": { 23 | "deployment.kubernetes.io/desired-replicas": "1", 24 | "deployment.kubernetes.io/max-replicas": "1", 25 | "deployment.kubernetes.io/revision": "1" 26 | }, 27 | "ownerReferences": [ 28 | { 29 | "apiVersion": "apps/v1", 30 | "kind": "Deployment", 31 | "name": "minio", 32 | "uid": "f81a0357-8160-47fb-9a0e-898b763cb6ef", 33 | "controller": true, 34 | "blockOwnerDeletion": true 35 | } 36 | ], 37 | "managedFields": [ 38 | { 39 | "manager": "kube-controller-manager", 40 | "operation": "Update", 41 | "apiVersion": "apps/v1", 42 | "time": "2022-04-11T22:51:59Z", 43 | "fieldsType": "FieldsV1", 44 | "fieldsV1": { 45 | "f:metadata": { 46 | "f:annotations": { 47 | ".": {}, 48 | "f:deployment.kubernetes.io/desired-replicas": {}, 49 | "f:deployment.kubernetes.io/max-replicas": {}, 50 | "f:deployment.kubernetes.io/revision": {} 51 | }, 52 | "f:labels": { 53 | ".": {}, 54 | "f:app": {}, 55 | "f:pod-template-hash": {} 56 | }, 57 | "f:ownerReferences": { 58 | ".": {}, 59 | "k:{\"uid\":\"f81a0357-8160-47fb-9a0e-898b763cb6ef\"}": {} 60 | } 61 | }, 62 | "f:spec": { 63 | "f:replicas": {}, 64 | "f:selector": {}, 65 | "f:template": { 66 | "f:metadata": { 67 | "f:labels": { 68 | ".": {}, 69 | "f:app": {}, 70 | "f:pod-template-hash": {} 71 | } 72 | }, 73 | "f:spec": { 74 | "f:containers": { 75 | "k:{\"name\":\"minio\"}": { 76 | ".": {}, 77 | "f:args": {}, 78 | "f:env": { 79 | ".": {}, 80 | "k:{\"name\":\"MINIO_ACCESS_KEY\"}": { 81 | ".": {}, 82 | "f:name": {}, 83 | "f:valueFrom": { 84 | ".": {}, 85 | "f:secretKeyRef": {} 86 | } 87 | }, 88 | "k:{\"name\":\"MINIO_SECRET_KEY\"}": { 89 | ".": {}, 90 | "f:name": {}, 91 | "f:valueFrom": { 92 | ".": {}, 93 | "f:secretKeyRef": {} 94 | } 95 | }, 96 | "k:{\"name\":\"MINIO_UPDATE\"}": { 97 | ".": {}, 98 | "f:name": {}, 99 | "f:value": {} 100 | } 101 | }, 102 | "f:image": {}, 103 | "f:imagePullPolicy": {}, 104 | "f:livenessProbe": { 105 | ".": {}, 106 | "f:failureThreshold": {}, 107 | "f:httpGet": { 108 | ".": {}, 109 | "f:path": {}, 110 | "f:port": {}, 111 | "f:scheme": {} 112 | }, 113 | "f:initialDelaySeconds": {}, 114 | "f:periodSeconds": {}, 115 | "f:successThreshold": {}, 116 | "f:timeoutSeconds": {} 117 | }, 118 | "f:name": {}, 119 | "f:ports": { 120 | ".": {}, 121 | "k:{\"containerPort\":9000,\"protocol\":\"TCP\"}": { 122 | ".": {}, 123 | "f:containerPort": {}, 124 | "f:protocol": {} 125 | } 126 | }, 127 | "f:readinessProbe": { 128 | ".": {}, 129 | "f:failureThreshold": {}, 130 | "f:httpGet": { 131 | ".": {}, 132 | "f:path": {}, 133 | "f:port": {}, 134 | "f:scheme": {} 135 | }, 136 | "f:initialDelaySeconds": {}, 137 | "f:periodSeconds": {}, 138 | "f:successThreshold": {}, 139 | "f:timeoutSeconds": {} 140 | }, 141 | "f:resources": {}, 142 | "f:terminationMessagePath": {}, 143 | "f:terminationMessagePolicy": {}, 144 | "f:volumeMounts": { 145 | ".": {}, 146 | "k:{\"mountPath\":\"/data\"}": { 147 | ".": {}, 148 | "f:mountPath": {}, 149 | "f:name": {} 150 | } 151 | } 152 | } 153 | }, 154 | "f:dnsPolicy": {}, 155 | "f:restartPolicy": {}, 156 | "f:schedulerName": {}, 157 | "f:securityContext": {}, 158 | "f:terminationGracePeriodSeconds": {}, 159 | "f:volumes": { 160 | ".": {}, 161 | "k:{\"name\":\"data\"}": { 162 | ".": {}, 163 | "f:name": {}, 164 | "f:persistentVolumeClaim": { 165 | ".": {}, 166 | "f:claimName": {} 167 | } 168 | } 169 | } 170 | } 171 | } 172 | } 173 | } 174 | }, 175 | { 176 | "manager": "kube-controller-manager", 177 | "operation": "Update", 178 | "apiVersion": "apps/v1", 179 | "time": "2022-04-11T22:52:38Z", 180 | "fieldsType": "FieldsV1", 181 | "fieldsV1": { 182 | "f:status": { 183 | "f:availableReplicas": {}, 184 | "f:fullyLabeledReplicas": {}, 185 | "f:observedGeneration": {}, 186 | "f:readyReplicas": {}, 187 | "f:replicas": {} 188 | } 189 | }, 190 | "subresource": "status" 191 | } 192 | ] 193 | }, 194 | "spec": { 195 | "replicas": 1, 196 | "selector": { 197 | "matchLabels": { 198 | "app": "minio", 199 | "pod-template-hash": "7b45cd544d" 200 | } 201 | }, 202 | "template": { 203 | "metadata": { 204 | "creationTimestamp": null, 205 | "labels": { 206 | "app": "minio", 207 | "pod-template-hash": "7b45cd544d" 208 | } 209 | }, 210 | "spec": { 211 | "volumes": [ 212 | { 213 | "name": "data", 214 | "persistentVolumeClaim": { 215 | "claimName": "minio-pv-claim" 216 | } 217 | } 218 | ], 219 | "containers": [ 220 | { 221 | "name": "minio", 222 | "image": "minio/minio:RELEASE.2020-01-25T02-50-51Z", 223 | "args": [ 224 | "--quiet", 225 | "server", 226 | "/data" 227 | ], 228 | "ports": [ 229 | { 230 | "containerPort": 9000, 231 | "protocol": "TCP" 232 | } 233 | ], 234 | "env": [ 235 | { 236 | "name": "MINIO_UPDATE", 237 | "value": "off" 238 | }, 239 | { 240 | "name": "MINIO_ACCESS_KEY", 241 | "valueFrom": { 242 | "secretKeyRef": { 243 | "name": "minio-credentials", 244 | "key": "MINIO_ACCESS_KEY" 245 | } 246 | } 247 | }, 248 | { 249 | "name": "MINIO_SECRET_KEY", 250 | "valueFrom": { 251 | "secretKeyRef": { 252 | "name": "minio-credentials", 253 | "key": "MINIO_SECRET_KEY" 254 | } 255 | } 256 | } 257 | ], 258 | "resources": {}, 259 | "volumeMounts": [ 260 | { 261 | "name": "data", 262 | "mountPath": "/data" 263 | } 264 | ], 265 | "livenessProbe": { 266 | "httpGet": { 267 | "path": "/minio/health/live", 268 | "port": 9000, 269 | "scheme": "HTTP" 270 | }, 271 | "initialDelaySeconds": 5, 272 | "timeoutSeconds": 1, 273 | "periodSeconds": 20, 274 | "successThreshold": 1, 275 | "failureThreshold": 3 276 | }, 277 | "readinessProbe": { 278 | "httpGet": { 279 | "path": "/minio/health/ready", 280 | "port": 9000, 281 | "scheme": "HTTP" 282 | }, 283 | "initialDelaySeconds": 5, 284 | "timeoutSeconds": 1, 285 | "periodSeconds": 20, 286 | "successThreshold": 1, 287 | "failureThreshold": 3 288 | }, 289 | "terminationMessagePath": "/dev/termination-log", 290 | "terminationMessagePolicy": "File", 291 | "imagePullPolicy": "IfNotPresent" 292 | } 293 | ], 294 | "restartPolicy": "Always", 295 | "terminationGracePeriodSeconds": 30, 296 | "dnsPolicy": "ClusterFirst", 297 | "securityContext": {}, 298 | "schedulerName": "default-scheduler" 299 | } 300 | } 301 | }, 302 | "status": { 303 | "replicas": 1, 304 | "fullyLabeledReplicas": 1, 305 | "readyReplicas": 1, 306 | "availableReplicas": 1, 307 | "observedGeneration": 1 308 | } 309 | } 310 | ] 311 | } 312 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27142" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Service", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "kubernetes", 13 | "namespace": "default", 14 | "uid": "968eef15-756e-49f0-a821-e17967ca6be4", 15 | "resourceVersion": "1883", 16 | "creationTimestamp": "2022-04-11T22:50:00Z", 17 | "labels": { 18 | "component": "apiserver", 19 | "provider": "kubernetes", 20 | "velero.io/exclude-from-backup": "true" 21 | }, 22 | "managedFields": [ 23 | { 24 | "manager": "kube-apiserver", 25 | "operation": "Update", 26 | "apiVersion": "v1", 27 | "time": "2022-04-11T22:50:00Z", 28 | "fieldsType": "FieldsV1", 29 | "fieldsV1": { 30 | "f:metadata": { 31 | "f:labels": { 32 | ".": {}, 33 | "f:component": {}, 34 | "f:provider": {} 35 | } 36 | }, 37 | "f:spec": { 38 | "f:clusterIP": {}, 39 | "f:internalTrafficPolicy": {}, 40 | "f:ipFamilyPolicy": {}, 41 | "f:ports": { 42 | ".": {}, 43 | "k:{\"port\":443,\"protocol\":\"TCP\"}": { 44 | ".": {}, 45 | "f:name": {}, 46 | "f:port": {}, 47 | "f:protocol": {}, 48 | "f:targetPort": {} 49 | } 50 | }, 51 | "f:sessionAffinity": {}, 52 | "f:type": {} 53 | } 54 | } 55 | }, 56 | { 57 | "manager": "kubectl-label", 58 | "operation": "Update", 59 | "apiVersion": "v1", 60 | "time": "2022-04-11T22:53:00Z", 61 | "fieldsType": "FieldsV1", 62 | "fieldsV1": { 63 | "f:metadata": { 64 | "f:labels": { 65 | "f:velero.io/exclude-from-backup": {} 66 | } 67 | } 68 | } 69 | } 70 | ] 71 | }, 72 | "spec": { 73 | "ports": [ 74 | { 75 | "name": "https", 76 | "protocol": "TCP", 77 | "port": 443, 78 | "targetPort": 6443 79 | } 80 | ], 81 | "clusterIP": "***HIDDEN***", 82 | "clusterIPs": [ 83 | "***HIDDEN***" 84 | ], 85 | "type": "ClusterIP", 86 | "sessionAffinity": "None", 87 | "ipFamilies": [ 88 | "IPv4" 89 | ], 90 | "ipFamilyPolicy": "SingleStack", 91 | "internalTrafficPolicy": "Cluster" 92 | }, 93 | "status": { 94 | "loadBalancer": {} 95 | } 96 | } 97 | ] 98 | } 99 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27142" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27142" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27142" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Service", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "kube-dns", 13 | "namespace": "kube-system", 14 | "uid": "6327a670-0243-46e0-8990-2b634a757104", 15 | "resourceVersion": "295", 16 | "creationTimestamp": "2022-04-11T22:50:02Z", 17 | "labels": { 18 | "k8s-app": "kube-dns", 19 | "kubernetes.io/cluster-service": "true", 20 | "kubernetes.io/name": "CoreDNS" 21 | }, 22 | "annotations": { 23 | "prometheus.io/port": "9153", 24 | "prometheus.io/scrape": "true" 25 | }, 26 | "managedFields": [ 27 | { 28 | "manager": "Go-http-client", 29 | "operation": "Update", 30 | "apiVersion": "v1", 31 | "time": "2022-04-11T22:50:02Z", 32 | "fieldsType": "FieldsV1", 33 | "fieldsV1": { 34 | "f:metadata": { 35 | "f:annotations": { 36 | ".": {}, 37 | "f:prometheus.io/port": {}, 38 | "f:prometheus.io/scrape": {} 39 | }, 40 | "f:labels": { 41 | ".": {}, 42 | "f:k8s-app": {}, 43 | "f:kubernetes.io/cluster-service": {}, 44 | "f:kubernetes.io/name": {} 45 | } 46 | }, 47 | "f:spec": { 48 | "f:clusterIP": {}, 49 | "f:internalTrafficPolicy": {}, 50 | "f:ports": { 51 | ".": {}, 52 | "k:{\"port\":53,\"protocol\":\"TCP\"}": { 53 | ".": {}, 54 | "f:name": {}, 55 | "f:port": {}, 56 | "f:protocol": {}, 57 | "f:targetPort": {} 58 | }, 59 | "k:{\"port\":53,\"protocol\":\"UDP\"}": { 60 | ".": {}, 61 | "f:name": {}, 62 | "f:port": {}, 63 | "f:protocol": {}, 64 | "f:targetPort": {} 65 | }, 66 | "k:{\"port\":9153,\"protocol\":\"TCP\"}": { 67 | ".": {}, 68 | "f:name": {}, 69 | "f:port": {}, 70 | "f:protocol": {}, 71 | "f:targetPort": {} 72 | } 73 | }, 74 | "f:selector": {}, 75 | "f:sessionAffinity": {}, 76 | "f:type": {} 77 | } 78 | } 79 | } 80 | ] 81 | }, 82 | "spec": { 83 | "ports": [ 84 | { 85 | "name": "dns", 86 | "protocol": "UDP", 87 | "port": 53, 88 | "targetPort": 53 89 | }, 90 | { 91 | "name": "dns-tcp", 92 | "protocol": "TCP", 93 | "port": 53, 94 | "targetPort": 53 95 | }, 96 | { 97 | "name": "metrics", 98 | "protocol": "TCP", 99 | "port": 9153, 100 | "targetPort": 9153 101 | } 102 | ], 103 | "selector": { 104 | "k8s-app": "kube-dns" 105 | }, 106 | "clusterIP": "***HIDDEN***", 107 | "clusterIPs": [ 108 | "***HIDDEN***" 109 | ], 110 | "type": "ClusterIP", 111 | "sessionAffinity": "None", 112 | "ipFamilies": [ 113 | "IPv4" 114 | ], 115 | "ipFamilyPolicy": "SingleStack", 116 | "internalTrafficPolicy": "Cluster" 117 | }, 118 | "status": { 119 | "loadBalancer": {} 120 | } 121 | } 122 | ] 123 | } 124 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27143" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Service", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "registry", 13 | "namespace": "kurl", 14 | "uid": "f6b87ed8-0ab5-4d12-8faf-d35e73278ff9", 15 | "resourceVersion": "1629", 16 | "creationTimestamp": "2022-04-11T22:50:19Z", 17 | "labels": { 18 | "app": "registry" 19 | }, 20 | "annotations": { 21 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{},\"labels\":{\"app\":\"registry\"},\"name\":\"registry\",\"namespace\":\"kurl\"},\"spec\":{\"clusterIP\":\"***HIDDEN***\",\"ports\":[{\"name\":\"registry\",\"port\":443,\"protocol\":\"TCP\",\"targetPort\":443}],\"selector\":{\"app\":\"registry\"},\"type\":\"ClusterIP\"}}\n" 22 | }, 23 | "managedFields": [ 24 | { 25 | "manager": "kubectl-client-side-apply", 26 | "operation": "Update", 27 | "apiVersion": "v1", 28 | "time": "2022-04-11T22:50:19Z", 29 | "fieldsType": "FieldsV1", 30 | "fieldsV1": { 31 | "f:metadata": { 32 | "f:annotations": { 33 | ".": {}, 34 | "f:kubectl.kubernetes.io/last-applied-configuration": {} 35 | }, 36 | "f:labels": { 37 | ".": {}, 38 | "f:app": {} 39 | } 40 | }, 41 | "f:spec": { 42 | "f:internalTrafficPolicy": {}, 43 | "f:ports": { 44 | ".": {}, 45 | "k:{\"port\":443,\"protocol\":\"TCP\"}": { 46 | ".": {}, 47 | "f:name": {}, 48 | "f:port": {}, 49 | "f:protocol": {}, 50 | "f:targetPort": {} 51 | } 52 | }, 53 | "f:selector": {}, 54 | "f:sessionAffinity": {}, 55 | "f:type": {} 56 | } 57 | } 58 | } 59 | ] 60 | }, 61 | "spec": { 62 | "ports": [ 63 | { 64 | "name": "registry", 65 | "protocol": "TCP", 66 | "port": 443, 67 | "targetPort": 443 68 | } 69 | ], 70 | "selector": { 71 | "app": "registry" 72 | }, 73 | "clusterIP": "***HIDDEN***", 74 | "clusterIPs": [ 75 | "***HIDDEN***" 76 | ], 77 | "type": "ClusterIP", 78 | "sessionAffinity": "None", 79 | "ipFamilies": [ 80 | "IPv4" 81 | ], 82 | "ipFamilyPolicy": "SingleStack", 83 | "internalTrafficPolicy": "Cluster" 84 | }, 85 | "status": { 86 | "loadBalancer": {} 87 | } 88 | } 89 | ] 90 | } 91 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Service", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "minio", 13 | "namespace": "minio", 14 | "uid": "43bebf1a-c18b-4d76-ae79-257c7cca2398", 15 | "resourceVersion": "1075", 16 | "creationTimestamp": "2022-04-11T22:51:59Z", 17 | "annotations": { 18 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{},\"name\":\"minio\",\"namespace\":\"minio\"},\"spec\":{\"ports\":[{\"port\":80,\"protocol\":\"TCP\",\"targetPort\":9000}],\"selector\":{\"app\":\"minio\"},\"type\":\"ClusterIP\"}}\n" 19 | }, 20 | "managedFields": [ 21 | { 22 | "manager": "kubectl-client-side-apply", 23 | "operation": "Update", 24 | "apiVersion": "v1", 25 | "time": "2022-04-11T22:51:59Z", 26 | "fieldsType": "FieldsV1", 27 | "fieldsV1": { 28 | "f:metadata": { 29 | "f:annotations": { 30 | ".": {}, 31 | "f:kubectl.kubernetes.io/last-applied-configuration": {} 32 | } 33 | }, 34 | "f:spec": { 35 | "f:internalTrafficPolicy": {}, 36 | "f:ports": { 37 | ".": {}, 38 | "k:{\"port\":80,\"protocol\":\"TCP\"}": { 39 | ".": {}, 40 | "f:port": {}, 41 | "f:protocol": {}, 42 | "f:targetPort": {} 43 | } 44 | }, 45 | "f:selector": {}, 46 | "f:sessionAffinity": {}, 47 | "f:type": {} 48 | } 49 | } 50 | } 51 | ] 52 | }, 53 | "spec": { 54 | "ports": [ 55 | { 56 | "protocol": "TCP", 57 | "port": 80, 58 | "targetPort": 9000 59 | } 60 | ], 61 | "selector": { 62 | "app": "minio" 63 | }, 64 | "clusterIP": "***HIDDEN***", 65 | "clusterIPs": [ 66 | "***HIDDEN***" 67 | ], 68 | "type": "ClusterIP", 69 | "sessionAffinity": "None", 70 | "ipFamilies": [ 71 | "IPv4" 72 | ], 73 | "ipFamilyPolicy": "SingleStack", 74 | "internalTrafficPolicy": "Cluster" 75 | }, 76 | "status": { 77 | "loadBalancer": {} 78 | } 79 | } 80 | ] 81 | } 82 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "Service", 10 | "apiVersion": "v1", 11 | "metadata": { 12 | "name": "contour", 13 | "namespace": "projectcontour", 14 | "uid": "6eec3fd6-9db4-4732-b5ee-df3623d5ec7f", 15 | "resourceVersion": "1551", 16 | "creationTimestamp": "2022-04-11T22:52:42Z", 17 | "annotations": { 18 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{},\"name\":\"contour\",\"namespace\":\"projectcontour\"},\"spec\":{\"ports\":[{\"name\":\"xds\",\"port\":8001,\"protocol\":\"TCP\",\"targetPort\":8001}],\"selector\":{\"app\":\"contour\"},\"type\":\"ClusterIP\"}}\n" 19 | }, 20 | "managedFields": [ 21 | { 22 | "manager": "kubectl-client-side-apply", 23 | "operation": "Update", 24 | "apiVersion": "v1", 25 | "time": "2022-04-11T22:52:42Z", 26 | "fieldsType": "FieldsV1", 27 | "fieldsV1": { 28 | "f:metadata": { 29 | "f:annotations": { 30 | ".": {}, 31 | "f:kubectl.kubernetes.io/last-applied-configuration": {} 32 | } 33 | }, 34 | "f:spec": { 35 | "f:internalTrafficPolicy": {}, 36 | "f:ports": { 37 | ".": {}, 38 | "k:{\"port\":8001,\"protocol\":\"TCP\"}": { 39 | ".": {}, 40 | "f:name": {}, 41 | "f:port": {}, 42 | "f:protocol": {}, 43 | "f:targetPort": {} 44 | } 45 | }, 46 | "f:selector": {}, 47 | "f:sessionAffinity": {}, 48 | "f:type": {} 49 | } 50 | } 51 | } 52 | ] 53 | }, 54 | "spec": { 55 | "ports": [ 56 | { 57 | "name": "xds", 58 | "protocol": "TCP", 59 | "port": 8001, 60 | "targetPort": 8001 61 | } 62 | ], 63 | "selector": { 64 | "app": "contour" 65 | }, 66 | "clusterIP": "***HIDDEN***", 67 | "clusterIPs": [ 68 | "***HIDDEN***" 69 | ], 70 | "type": "ClusterIP", 71 | "sessionAffinity": "None", 72 | "ipFamilies": [ 73 | "IPv4" 74 | ], 75 | "ipFamilyPolicy": "SingleStack", 76 | "internalTrafficPolicy": "Cluster" 77 | }, 78 | "status": { 79 | "loadBalancer": {} 80 | } 81 | }, 82 | { 83 | "kind": "Service", 84 | "apiVersion": "v1", 85 | "metadata": { 86 | "name": "envoy", 87 | "namespace": "projectcontour", 88 | "uid": "32dbaa18-32d6-45fe-a80b-f6a5336c2e6d", 89 | "resourceVersion": "1557", 90 | "creationTimestamp": "2022-04-11T22:52:42Z", 91 | "annotations": { 92 | "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"annotations\":{\"service.beta.kubernetes.io/aws-load-balancer-backend-protocol\":\"tcp\"},\"name\":\"envoy\",\"namespace\":\"projectcontour\"},\"spec\":{\"externalTrafficPolicy\":\"Local\",\"ports\":[{\"name\":\"http\",\"nodePort\":80,\"port\":80,\"protocol\":\"TCP\",\"targetPort\":8080},{\"name\":\"https\",\"nodePort\":443,\"port\":443,\"protocol\":\"TCP\",\"targetPort\":8443}],\"selector\":{\"app\":\"envoy\"},\"type\":\"NodePort\"}}\n", 93 | "service.beta.kubernetes.io/aws-load-balancer-backend-protocol": "tcp" 94 | }, 95 | "managedFields": [ 96 | { 97 | "manager": "kubectl-client-side-apply", 98 | "operation": "Update", 99 | "apiVersion": "v1", 100 | "time": "2022-04-11T22:52:42Z", 101 | "fieldsType": "FieldsV1", 102 | "fieldsV1": { 103 | "f:metadata": { 104 | "f:annotations": { 105 | ".": {}, 106 | "f:kubectl.kubernetes.io/last-applied-configuration": {}, 107 | "f:service.beta.kubernetes.io/aws-load-balancer-backend-protocol": {} 108 | } 109 | }, 110 | "f:spec": { 111 | "f:externalTrafficPolicy": {}, 112 | "f:internalTrafficPolicy": {}, 113 | "f:ports": { 114 | ".": {}, 115 | "k:{\"port\":80,\"protocol\":\"TCP\"}": { 116 | ".": {}, 117 | "f:name": {}, 118 | "f:nodePort": {}, 119 | "f:port": {}, 120 | "f:protocol": {}, 121 | "f:targetPort": {} 122 | }, 123 | "k:{\"port\":443,\"protocol\":\"TCP\"}": { 124 | ".": {}, 125 | "f:name": {}, 126 | "f:nodePort": {}, 127 | "f:port": {}, 128 | "f:protocol": {}, 129 | "f:targetPort": {} 130 | } 131 | }, 132 | "f:selector": {}, 133 | "f:sessionAffinity": {}, 134 | "f:type": {} 135 | } 136 | } 137 | } 138 | ] 139 | }, 140 | "spec": { 141 | "ports": [ 142 | { 143 | "name": "http", 144 | "protocol": "TCP", 145 | "port": 80, 146 | "targetPort": 8080, 147 | "nodePort": 80 148 | }, 149 | { 150 | "name": "https", 151 | "protocol": "TCP", 152 | "port": 443, 153 | "targetPort": 8443, 154 | "nodePort": 443 155 | } 156 | ], 157 | "selector": { 158 | "app": "envoy" 159 | }, 160 | "clusterIP": "***HIDDEN***", 161 | "clusterIPs": [ 162 | "***HIDDEN***" 163 | ], 164 | "type": "NodePort", 165 | "sessionAffinity": "None", 166 | "externalTrafficPolicy": "Local", 167 | "ipFamilies": [ 168 | "IPv4" 169 | ], 170 | "ipFamilyPolicy": "SingleStack", 171 | "internalTrafficPolicy": "Cluster" 172 | }, 173 | "status": { 174 | "loadBalancer": {} 175 | } 176 | } 177 | ] 178 | } 179 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/services/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "ServiceList", 3 | "apiVersion": "v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/kube-node-lease.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27146" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/kube-public.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/kube-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/kurl.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/longhorn-system.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/minio.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/projectcontour.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27148" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/statefulsets/velero.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StatefulSetList", 3 | "apiVersion": "apps/v1", 4 | "metadata": { 5 | "resourceVersion": "27150" 6 | }, 7 | "items": [] 8 | } 9 | -------------------------------------------------------------------------------- /tests/support-bundle/cluster-resources/storage-classes.json: -------------------------------------------------------------------------------- 1 | { 2 | "kind": "StorageClassList", 3 | "apiVersion": "storage.k8s.io/v1", 4 | "metadata": { 5 | "resourceVersion": "27159" 6 | }, 7 | "items": [ 8 | { 9 | "kind": "StorageClass", 10 | "apiVersion": "storage.k8s.io/v1", 11 | "metadata": { 12 | "name": "longhorn", 13 | "uid": "d97312ff-9b7c-4b07-b964-17ece23f9025", 14 | "resourceVersion": "937", 15 | "creationTimestamp": "2022-04-11T22:51:41Z", 16 | "annotations": { 17 | "longhorn.io/last-applied-configmap": "kind: StorageClass\napiVersion: storage.k8s.io/v1\nmetadata:\n name: longhorn\n annotations:\n storageclass.kubernetes.io/is-default-class: \"true\"\nprovisioner: driver.longhorn.io\nallowVolumeExpansion: true\nreclaimPolicy: Delete\nvolumeBindingMode: Immediate\nparameters:\n numberOfReplicas: \"3\"\n staleReplicaTimeout: \"2880\"\n fromBackup: \"\"\n", 18 | "storageclass.kubernetes.io/is-default-class": "true" 19 | }, 20 | "managedFields": [ 21 | { 22 | "manager": "longhorn-manager", 23 | "operation": "Update", 24 | "apiVersion": "storage.k8s.io/v1", 25 | "time": "2022-04-11T22:51:41Z", 26 | "fieldsType": "FieldsV1", 27 | "fieldsV1": { 28 | "f:allowVolumeExpansion": {}, 29 | "f:metadata": { 30 | "f:annotations": { 31 | ".": {}, 32 | "f:longhorn.io/last-applied-configmap": {}, 33 | "f:storageclass.kubernetes.io/is-default-class": {} 34 | } 35 | }, 36 | "f:parameters": { 37 | ".": {}, 38 | "f:fromBackup": {}, 39 | "f:numberOfReplicas": {}, 40 | "f:staleReplicaTimeout": {} 41 | }, 42 | "f:provisioner": {}, 43 | "f:reclaimPolicy": {}, 44 | "f:volumeBindingMode": {} 45 | } 46 | } 47 | ] 48 | }, 49 | "provisioner": "driver.longhorn.io", 50 | "parameters": { 51 | "fromBackup": "", 52 | "numberOfReplicas": "3", 53 | "staleReplicaTimeout": "2880" 54 | }, 55 | "reclaimPolicy": "Delete", 56 | "allowVolumeExpansion": true, 57 | "volumeBindingMode": "Immediate" 58 | } 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /tests/tests.go: -------------------------------------------------------------------------------- 1 | package tests 2 | 3 | import ( 4 | "io" 5 | "net/http" 6 | 7 | "github.com/pkg/errors" 8 | ) 9 | 10 | func HTTPExec(verb string, url string, headers map[string]string) (string, int, error) { 11 | req, err := http.NewRequest(verb, url, nil) 12 | if err != nil { 13 | return "", 0, errors.Wrap(err, "failed to create http request") 14 | } 15 | 16 | for k, v := range headers { 17 | req.Header.Set(k, v) 18 | } 19 | 20 | res, err := http.DefaultClient.Do(req) 21 | if err != nil { 22 | return "", 0, errors.Wrap(err, "failed to execute http request") 23 | } 24 | defer res.Body.Close() 25 | 26 | data, err := io.ReadAll(res.Body) 27 | if err != nil { 28 | return "", 0, errors.Wrap(err, "failed to read response body") 29 | } 30 | 31 | return string(data), res.StatusCode, nil 32 | } 33 | --------------------------------------------------------------------------------